/// <summary> /// 描 述:redis操作方法 /// </summary> public class RedisCache { #region -- 连接信息 -- /// <summary> /// syncTimeout:允许同步操作的时间(ms) /// connectTimeout:连接操作的超时时间(ms) /// responseTimeout:socket 健康检查的响应时间(ms,毫秒) /// </summary> public static string connString = "127.0.0.1:6379,password=,abortConnect=False,syncTimeout = 30000,connectTimeout=30000,responseTimeout=30000,allowAdmin = true"; /// <summary> /// redis锁对象 /// </summary> private static readonly object Locker = new object(); private static ConnectionMultiplexer _instance; /// <summary> /// 单例获取链接对象 /// </summary> public static ConnectionMultiplexer _conn { get { if (_instance == null) { lock (Locker) { if (_instance == null || !_instance.IsConnected) { _instance = GetManager(); } } } return _instance; } } /// <summary> /// 获取redis对象 /// </summary> /// <param name="connectionString">链接字符串</param> /// <returns></returns> private static ConnectionMultiplexer GetManager(string connectionString = null) { connectionString = connectionString ?? connString; var connect = ConnectionMultiplexer.Connect(connectionString); //注册如下事件 connect.ConnectionFailed += RedisCacheEvent.MuxerConnectionFailed; connect.ConnectionRestored += RedisCacheEvent.MuxerConnectionRestored; connect.ErrorMessage += RedisCacheEvent.MuxerErrorMessage; connect.ConfigurationChanged += RedisCacheEvent.MuxerConfigurationChanged; connect.HashSlotMoved += RedisCacheEvent.MuxerHashSlotMoved; connect.InternalError += RedisCacheEvent.MuxerInternalError; return connect; } /// <summary> /// 获取redis客户端根据库ID号 /// </summary> /// <param name="dbId">redis库Id</param> /// <returns></returns> private static IDatabase GetClientManager(int dbId) { ////预防死锁 _conn.PreserveAsyncOrder = false; IDatabase dbObj = _conn.GetDatabase(dbId); return dbObj; } #endregion #region 执行redis命令公共方法 /// <summary> /// 执行redis命令公共方法 /// </summary> /// <typeparam name="T">返回类型(泛型)</typeparam> /// <param name="func">委托(参数为委托)</param> /// <returns></returns> private static T Do<T>(Func<IDatabase, T> func, long dbId = 0) { try { var database = GetClientManager((int)dbId); return func(database); } catch (Exception ex) { WriteSqlErrorLog(ex); return default(T); } } #endregion #region 判断Key是否存在 /// <summary> /// 判断Key是否存在 /// </summary> /// <param name="key">键</param> /// <param name="dbId">redis库名称</param> /// <returns></returns> public static bool ExitKey(string key, long dbId = 0) { var res = Do(db => { return db.KeyExists(key); }, dbId); return res; } #endregion #region 模糊查找KeyList /// <summary> /// 模糊查找KeyList /// </summary> /// <param name="keyname"></param> /// <param name="dbId"></param> /// <returns></returns> public static List<string> SearchKeyList(string keyname, long dbId = 0) { List<string> res = new List<string>(); try { var db = _conn.GetEndPoints(); foreach (var ep in db) { var server = _conn.GetServer(ep); var keys = server.Keys((int)dbId, "*" + keyname + "*"); foreach (var item in keys) { res.Add((string)item); } } return res; } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } #endregion #region 获取某个库所有的Key /// <summary> /// 获取某个库所有的Key /// </summary> /// <param name="dbId"></param> /// <returns></returns> public static List<string> GetAllKeys(long dbId = 0) { List<string> res = new List<string>(); try { var db = _conn.GetEndPoints(); foreach (var ep in db) { var server = _conn.GetServer(ep); var keys = server.Keys((int)dbId); foreach (var item in keys) { res.Add((string)item); } } return res; } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } #endregion #region -- Key-Value -- /// <summary> /// 设置单体 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="key">键值</param> /// <param name="t">值</param> /// <param name="dbId">库Id</param> /// <returns></returns> public static bool Set<T>(string key, T t, long dbId = 0) { var res = Do(db => { return db.StringSet(key, ConvertJson(t)); }, dbId); return res; } /// <summary> /// 设置单体 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="key">键值</param> /// <param name="t">值</param> /// <param name="timeSpan">保存时间</param> /// <param name="dbId">库Id</param> /// <returns></returns> public static bool Set<T>(string key, T t, TimeSpan timeSpan, long dbId = 0) { var res = Do(db => { return db.StringSet(key, ConvertJson(t), timeSpan); }, dbId); return res; } /// <summary> /// 设置单体 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="key">键值</param> /// <param name="t">值</param> /// <param name="dateTime">过期时间</param> /// <returns></returns> public static bool Set<T>(string key, T t, DateTime dateTime, long dbId = 0) { var res = Do(db => { DateTime nowDate = DateTime.Now; TimeSpan timeSpan = dateTime.Subtract(nowDate).Duration(); return db.StringSet(key, ConvertJson(t), timeSpan); }, dbId); return res; } /// <summary> /// 获取单体 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="key">键值</param> /// <returns></returns> public static T Get<T>(string key, long dbId = 0) where T : class { var resStr = Do(db => { return db.StringGet(key); }, dbId); var res = ConvertObj<T>(resStr); return res; } /// <summary> /// 移除单体 /// </summary> /// <param name="key">键值</param> public static bool Remove(string key, long dbId = 0) { try { var res = Do(db => { return db.KeyDelete(key); }, dbId); return res; } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } /// <summary> /// 清空所有缓存 /// </summary> public static bool RemoveAll(long dbId = 0) { try { var db = _conn.GetEndPoints(); foreach (var ep in db) { var server = _conn.GetServer(ep); server.FlushDatabase((int)dbId); } return true; } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } #endregion #region -- List -- /// <summary> /// 添加列表 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="t">值</param> /// <param name="sp">过期时间</param> /// <param name="dbId">库</param> public static void List_Add<T>(string key, T t, TimeSpan sp, long dbId = 0) { var res = Do(db => { if (db.ListRightPush(key, ConvertJson(t)) >= 0) { return db.KeyExpire(key, sp); } else { return false; }; }, dbId); } /// <summary> /// 移除列表某个值 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="t">值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool List_Remove<T>(string key, T t, long dbId = 0) { var res = Do(db => { return db.ListRemove(key, ConvertJson(t)) >= 0; }, dbId); return res; } /// <summary> /// 移除列表所有值 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="dbId">库Id</param> public static void List_RemoveAll(string key, long dbId = 0) { var res = Do(db => { return db.KeyDelete(key); }, dbId); } /// <summary> /// 获取列表数据条数 /// </summary> /// <param name="key"></param> /// <param name="dbId"></param> /// <returns></returns> public static long List_Count(string key, long dbId = 0) { var res = Do(db => { return db.ListLength(key); }, dbId); return res; } /// <summary> /// 获取指定条数列表数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="start">开始编号</param> /// <param name="count">条数</param> /// <param name="dbId">库</param> /// <returns></returns> public static List<T> List_GetRange<T>(string key, int start, int count, long dbId = 0) { var res = Do(db => { int end = start + count - 1; var resArry = db.ListRange(key, start, end); List<T> result = ConvetList<T>(resArry); return result; }, dbId); return res; } /// <summary> /// 获取列表所有数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="dbId">库数据</param> /// <returns></returns> public static List<T> List_GetList<T>(string key, long dbId = 0) { var res = Do(db => { List<T> result = new List<T>(); var resArry = db.ListRange(key); result.AddRange(ConvetList<T>(resArry)); return result; }, dbId); return res; } /// <summary> /// 获取列表分页数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="pageIndex">页码</param> /// <param name="pageSize">每页条数</param> /// <param name="dbId">库</param> /// <returns></returns> public static List<T> List_GetList<T>(string key, int pageIndex, int pageSize, long dbId = 0) { var res = Do(db => { List<T> result = new List<T>(); int start = pageSize * (pageIndex - 1); int end = pageIndex * pageSize - 1; var resArry = db.ListRange(key, start, end); result.AddRange(ConvetList<T>(resArry)); return result; }, dbId); return res; } #endregion #region -- Set -- /// <summary> /// 添加集合 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="t">数值</param> /// <param name="sp">有效时间</param> /// <param name="dbId">库</param> public static bool Set_Add<T>(string key, T t, TimeSpan sp, long dbId = 0) { var res = Do(db => { string value = ConvertJson(t); if (db.SetAdd(key, value) == true) { return db.KeyExpire(key, sp); } else { return false; } }, dbId); return res; } /// <summary> /// 集合是否包含指定数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="t">数值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Set_Contains<T>(string key, T t, long dbId = 0) { var res = Do(db => { return db.SetContains(key, ConvertJson(t)); }, dbId); return res; } /// <summary> /// 移除集合某个值 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="t">数值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Set_Remove<T>(string key, T t, long dbId = 0) { var res = Do(db => { return db.SetRemove(key, ConvertJson(t)); }, dbId); return res; } #endregion #region -- SortedSet -- /// <summary> /// 添加数据到 SortedSet /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">集合id</param> /// <param name="t">数值</param> /// <param name="sp">有效时间</param> /// <param name="score">排序码</param> /// <param name="dbId">库</param> public static bool SortedSet_Add<T>(string key, T t, TimeSpan sp, double score, long dbId = 0) { var res = Do(db => { string value = ConvertJson(t); if (db.SortedSetAdd(key, value, score) == true) { return db.KeyExpire(key, sp); } else { return false; } }, dbId); return res; } /// <summary> /// 移除数据从SortedSet /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">集合id</param> /// <param name="t">数值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool SortedSet_Remove<T>(string key, T t, long dbId = 0) { var res = Do(db => { return db.SortedSetRemove(key, ConvertJson<T>(t)); }, dbId); return res; } /// <summary> /// 修剪SortedSet /// </summary> /// <param name="key">键值</param> /// <param name="size">保留的条数</param> /// <param name="dbId">库</param> /// <param name="stop">删除的最大排名</param> /// <returns></returns> public static long SortedSet_Trim(string key, int size, long dbId = 0, long stop = 9999999) { var res = Do(db => { return db.SortedSetRemoveRangeByRank(key, size, stop); }, dbId); return res; } /// <summary> /// 获取SortedSet的长度 /// </summary> /// <param name="key">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static long SortedSet_Count(string key, long dbId = 0) { var res = Do(db => { return db.SortedSetLength(key); }, dbId); return res; } /// <summary> /// 获取SortedSet的分页数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">键值</param> /// <param name="pageIndex">页码</param> /// <param name="pageSize">每页条数</param> /// <param name="dbId">库</param> /// <returns></returns> public static List<T> SortedSet_GetList<T>(string key, int pageIndex, int pageSize, long dbId = 0) { var res = Do(db => { var list = db.SortedSetRangeByValue(key, RedisValue.Null, RedisValue.Null, Exclude.None, (pageIndex - 1) * pageSize, pageSize); var result = ConvetList<T>(list); return result; }, dbId); return res; } /// <summary> /// 获取SortedSet的全部数据 /// </summary> /// <typeparam name="T">类</typeparam> /// <param name="key">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static List<T> SortedSet_GetListALL<T>(string key, long dbId = 0) { var res = Do(db => { var list = db.SortedSetRangeByRank(key); List<T> result = ConvetList<T>(list); return result; }, dbId); return res; } #endregion #region -- Hash -- /// <summary> /// 判断某个数据是否已经被缓存 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">hashID</param> /// <param name="dataKey">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Hash_Exist(string key, string dataKey, long dbId = 0) { var res = Do(db => db.HashExists(key, dataKey), dbId); return res; } /// <summary> /// 存储数据到hash表需要设置失效时间 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">hashID</param> /// <param name="dataKey">键值</param> /// <param name="t">数值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Hash_Set<T>(string key, string dataKey, T t, TimeSpan sp, long dbId = 0) { var res = Do(db => { string value = ConvertJson(t); if (db.HashSet(key, dataKey, value) == true) { return db.KeyExpire(key, sp); } else { return false; } }, dbId); return res; } /// <summary> /// 存储数据到hash表不需要设置失效时间 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="t"></param> /// <param name="dbId"></param> /// <returns></returns> public static bool Hash_Set<T>(string key, string dataKey, T t, long dbId = 0) { var res = Do(db => { string value = ConvertJson(t); return db.HashSet(key, dataKey, value); }, dbId); return res; } /// <summary> /// 存储文本数据到hash表需要设置失效时间 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="value"></param> /// <param name="dbId"></param> /// <returns></returns> public static bool Hash_SetText(string key, string dataKey, string value, TimeSpan sp, long dbId = 0) { var res = Do(db => { if (db.HashSet(key, dataKey, value) == true) { return db.KeyExpire(key, sp); } else { return false; } }, dbId); return res; } /// <summary> /// 存储文本数据到hash表不需要设置失效时间 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="value"></param> /// <param name="dbId"></param> /// <returns></returns> public static bool Hash_SetText(string key, string dataKey, string value, long dbId = 0) { var res = Do(db => { return db.HashSet(key, dataKey, value); }, dbId); return res; } /// <summary> /// 获取hashid数据集中所有key的集合 /// </summary> public static List<string> GetHashKeys(string hashid, long dbId = 0) { var res = Do(db => { List<string> result = new List<string>(); RedisValue[] arr = db.HashKeys(hashid); foreach (var item in arr) { if (!item.IsNullOrEmpty) { result.Add(item.ToString()); } } return result; }, dbId); return res; } /// <summary> /// 获取hashid数据集中的所有value集合 /// </summary> public static List<string> GetHashValues(string hashid, long dbId = 0) { var res = Do(db => { List<string> result = new List<string>(); RedisValue[] arr = db.HashValues(hashid); foreach (var item in arr) { if (!item.IsNullOrEmpty) { result.Add(item.ToString()); } } return result; }, dbId); return res; } /// <summary> /// 移除hash中的某值 /// </summary> /// <param name="key">hashID</param> /// <param name="dataKey">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Hash_Remove(string key, string dataKey, long dbId = 0) { var res = Do(db => { return db.HashDelete(key, dataKey); }, dbId); return res; } /// <summary> /// 移除整个hash /// </summary> /// <param name="key">hashID</param> /// <param name="dbId">库</param> /// <returns></returns> public static bool Hash_Remove(string key, long dbId = 0) { var res = Do(db => { RedisValue[] arr = db.HashKeys(key); return db.HashDelete(key, arr) >= 0; }, dbId); return res; } /// <summary> /// 从hash表获取数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">hashID</param> /// <param name="dataKey">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static T Hash_Get<T>(string key, string dataKey, long dbId = 0) { var res = Do(db => { string value = db.HashGet(key, dataKey); return ConvertObj<T>(value); }, dbId); return res; } /// <summary> /// 从hash表获取文本数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">hashID</param> /// <param name="dataKey">键值</param> /// <param name="dbId">库</param> /// <returns></returns> public static string Hash_GetText(string key, string dataKey, long dbId = 0) { var res = Do(db => { return db.HashGet(key, dataKey); }, dbId); return res; } /// <summary> /// 获取整个hash的数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="key">hashID</param> /// <param name="dbId">库</param> /// <returns></returns> public static List<T> Hash_GetAll<T>(string key, long dbId = 0) { var res = Do(db => { List<T> list = new List<T>(); RedisValue[] arr = db.HashKeys(key); foreach (var item in arr) { if (!item.IsNullOrEmpty) { string value = db.HashGet(key, item); list.Add(ConvertObj<T>(value)); } } return list; }, dbId); return res; } #endregion #region -- Stream 消息队列 -- /// <summary> /// 发送Redis消息 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static bool SendMessage(string key, string value, long dbId = 0) { Do(db => db.ListLeftPush(key, value), dbId); return true; } /// <summary> /// 接收Redis消息 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static T ReceiveMessages<T>(string key, long dbId = 0) { return Do(db => { var value = db.ListRightPop(key); return ConvertObj<T>(value); }, dbId); } #endregion #region 帮助方法 /// <summary> /// 反序列化 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <returns></returns> private static T ConvertObj<T>(RedisValue value) { try { if (typeof(T).Name.Equals(typeof(string).Name)) { return JsonConvert.DeserializeObject<T>($"'{value}'"); } if (value.HasValue) { return JsonConvert.DeserializeObject<T>(value); } else { return default(T); } } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } /// <summary> /// 反序列化(集合) /// </summary> /// <typeparam name="T">返回值类型</typeparam> /// <param name="values">反序列化参数</param> /// <returns></returns> private static List<T> ConvetList<T>(RedisValue[] values) { List<T> result = new List<T>(); if (values != null) { foreach (var item in values) { var model = ConvertObj<T>(item); result.Add(model); } } return result; } /// <summary> /// 序列化 /// </summary> /// <typeparam name="T">类</typeparam> /// <param name="value">值</param> /// <returns></returns> private static string ConvertJson<T>(T value) { try { string result = value is string ? value.ToString() : JsonConvert.SerializeObject(value); return result; } catch (Exception ex) { WriteSqlErrorLog(ex); throw; } } #endregion #region 操作报错写入日志 public static void WriteSqlErrorLog(Exception ex) { } #endregion }