using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using TalentCloud.Common; using TalentCloud.Base.Utils; namespace TalentCloud.Base.RedisHelper { /// <summary> /// 配置管理和初始化 /// </summary> internal class Managers { /// <summary> /// 最大读写数量 /// </summary> const int writeReadCount = 100000; //private static string hostString = TCConfigManager.GetConfig("RedisHost").ToString(); private static string hostString = ConfigurationManager.AppSettings["RedisHost"].TryString(); private static string[] writeHosts = hostString.Split(','); private static string[] readHosts = hostString.Split(','); private static int poolConnectTimeout = 1000 * 60 * 2; //private static string[] writeHosts = "".Split(','); //private static string[] readHosts = "".Split(','); //Singleton保证只有一个对象 private static Managers PoolManagers = null; private static Dictionary<int,PooledRedisClientManager> ClientManagerList=new Dictionary<int,PooledRedisClientManager>(); private static PooledRedisClientManager ClientManagers { get; set; } internal PooledRedisClientManager GetClientManagers() { return ClientManagers; } public static Managers Instance() { if (PoolManagers == null) { PoolManagers = new Managers(); } return PoolManagers; } //Singleton private Managers() { //Init(); } public void Init() { //初始化时就创建好0~8的数据库连接 for (int i = 0; i <= 8; i++) { GetManagers(i); } } public PooledRedisClientManager GetManagers(int db) { if (ClientManagerList.ContainsKey(db)) { return ClientManagerList[db]; } else { PooledRedisClientManager dbClientManagers = new PooledRedisClientManager(writeHosts, readHosts, new RedisClientManagerConfig { MaxWritePoolSize = writeReadCount,//“写”链接池链接数 MaxReadPoolSize = writeReadCount,//“读”链接池链接数 AutoStart = true, DefaultDb = db //默认数据库 }); dbClientManagers.ConnectTimeout = poolConnectTimeout; ClientManagerList[db]=dbClientManagers; return dbClientManagers; } } } }
using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading; using System.Linq.Expressions; using TalentCloud.Base.Utils; using TalentCloud.Common; namespace TalentCloud.Base.RedisHelper { /// <summary> /// redis客户端调用类 /// </summary> public class RedisClient { #region //初始化链接 public static void InitRedisPool() { Managers.Instance().Init(); } #endregion #region 写对象 private string GetEntryId<T>() { return typeof(T).FullName; } #region string 类型存储及操作 /// <summary> /// 写数据 永久保存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireIn"></param> /// <returns></returns> public bool SetKeyValue<T>(string key, T value,int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.SetEntry(key, value.ToJsonSerialize()); // client.Save();//持久化到硬盘 return true; }; return TryRedisWrite(fun, db); } /// <summary> /// 写数据 永久保存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireIn"></param> /// <returns></returns> public List<T> GetListKeyValue<T>(string key, int db) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { return client.Get<List<T>>(key); }; return TryRedisRead(fun, db); } /// <summary> /// 写数据 永久保存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireIn"></param> /// <returns></returns> public T GetKeyValue<T>(string key, int db) { Func<IRedisClient, T> fun = (IRedisClient client) => { return client.Get<T>(key); }; return TryRedisRead(fun, db); } /// <summary> /// 写数据 需要传过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireIn">TimeSpan.FromMinutes(30)</param> /// <returns></returns> public bool SetKeyValue<T>(string key, T value, int db, TimeSpan expireIn) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.Db = db; client.SetEntry(key, value.ToJsonSerialize(), expireIn); return true; }; return TryRedisWrite(fun, db); } /// <summary> /// 写数据 需要传过期时间 (只能写string类型数据) /// </summary> /// <param name="typeName"></param> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireIn"></param> public void SetKeyValue_String(string key, string value, TimeSpan expireIn, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { if (expireIn == System.TimeSpan.MinValue) { client.SetEntry(key, value, TimeSpan.FromMinutes(30));//默认30分钟 } else { client.SetEntry(key, value, expireIn); } return false; }; TryRedisWrite(fun, db); } /// <summary> /// 以Key/Value的形式存储对象到缓存中 /// </summary> /// <typeparam name="T">对象类别</typeparam> /// <param name="value">要写入的集合</param> public void KSet<T>(Dictionary<string, T> value,int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.SetAll<T>(value); return true; }; TryRedisWrite(fun, db); } #endregion #region LIST 方式存储及操作 /// <summary> /// 获取key包含的所有数据集合T 分页获取 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pageIndex">开始位置</param> /// <param name="pageSize">大小</param> /// <returns></returns> public List<T> GetPageListT<T>(string key, int pageIndex, int pageSize,int db) { int start = pageSize * (pageIndex - 1); return List_GetRange<T>(key, start, pageSize, db); } private List<T> List_GetRange<T>(string key, int start, int count, int db) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { // client.GetRangeFromSortedSet("") var c = client.GetTypedClient<T>(); return c.Lists[key].GetRange(start, start + count - 1); }; return TryRedisRead(fun, db); } /// <summary> /// 获取key包含的所有数据集合T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public List<T> Get<T>(string key, Expression<Func<T, bool>> expression, int db) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { var c = client.GetTypedClient<T>(); if (expression != null) { return c.Lists[key].GetAll().AsQueryable<T>().Where(expression).ToList(); } else { return c.Lists[key].GetAll(); } }; return TryRedisRead(fun, db); } /// <summary> /// 通过多个key包含的所有数据集合T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public List<T> Get<T>(List<string> keys, Expression<Func<T, bool>> expression, int db) { List<T> list = new List<T>(); foreach(string item in keys) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { var c = client.GetTypedClient<T>(); if (expression != null) { return c.Lists[item].GetAll().AsQueryable<T>().Where(expression).ToList(); } else { return c.Lists[item].GetAll(); } }; list.AddRange(TryRedisRead(fun, db)); } return list; } /// <summary> /// 获取key包含的所有数据集合T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public List<T> GetListT<T>(string key,int db) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { var c = client.GetTypedClient<T>(); return c.Lists[key].GetAll(); }; return TryRedisRead(fun,db); } /// <summary> /// 从左侧向list中添加值 T /// </summary> /// <typeparam name="T"><peparam> /// <param name="key"></param> /// <param name="t"></param> public void LPushInList<T>(string key, T t, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); redisTypedClient.PushItemToList(redisTypedClient.Lists[key], t); return true; }; TryRedisRead(fun, db); } /// <summary> /// 入队 /// </summary> /// <typeparam name="T"><peparam> /// <param name="key"></param> /// <param name="t"></param> public bool EnqueueItemOnList<T>(string key, T t) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); redisTypedClient.EnqueueItemOnList(redisTypedClient.Lists[key], t); return true; }; return TryRedisWrite(fun,0); } /// <summary> /// 出对 /// </summary> /// <typeparam name="T"><peparam> /// <param name="key"></param> /// <param name="t"></param> public T DequeueItemFromList<T>(string key) { Func<IRedisClient, T> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); return redisTypedClient.DequeueItemFromList(redisTypedClient.Lists[key]); }; return TryRedisRead(fun,0); } /// <summary> /// 获取队列总数 /// </summary> /// <typeparam name="T"><peparam> /// <param name="key"></param> /// <param name="t"></param> public int GetListCount<T>(string key,int db) { Func<IRedisClient, int> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); return redisTypedClient.GetListCount(redisTypedClient.Lists[key]); }; return TryRedisRead(fun, db); } /// <summary> /// 通过key移除list中某一个集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="t"></param> /// <returns></returns> public bool List_Remove<T>(string key, T t, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0; }; return TryRedisRead(fun, db); } /// <summary> /// 通过key 移除list集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public bool List_RemoveAll<T>(string key, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); redisTypedClient.Lists[key].RemoveAll(); return true; }; return TryRedisRead(fun,db); } /// <summary> /// key中是否包含 t /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="t"></param> /// <returns></returns> public bool Set_Contains<T>(string key, T t) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); return redisTypedClient.Sets[key].Contains(t); }; return TryRedisRead(fun,0); } /// <summary> /// 通过key移除list /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="t"></param> /// <returns></returns> public bool Set_Remove<T>(string key, T t,int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { var redisTypedClient = client.GetTypedClient<T>(); return redisTypedClient.Sets[key].Remove(t); }; return TryRedisRead(fun,db); } #endregion list #region SortedSet 方式存储及操作 /// <summary> /// 添加数据到 SortedSet /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">key</param> /// <param name="t">values</param> /// <param name="score">排序</param> public bool SortedSet_Add<T>(string key, T t, double score) { Func<IRedisClient, bool> fun = (IRedisClient client) => { string value = t.ToJsonSerialize(); return client.AddItemToSortedSet(key, value, score); }; return TryRedisWrite(fun,0); } /// <summary> /// 移除数据从SortedSet /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="t"></param> /// <returns></returns> public bool SortedSet_Remove<T>(string key, T t) { Func<IRedisClient, bool> fun = (IRedisClient client) => { string value = t.ToJsonSerialize(); return client.RemoveItemFromSortedSet(key, value); }; return TryRedisWrite(fun,0); } /// <summary> /// 修剪SortedSet /// </summary> /// <param name="key"></param> /// <param name="size">保留的条数</param> /// <returns></returns> public int SortedSet_Trim(string key, int size) { Func<IRedisClient, int> fun = (IRedisClient client) => { return client.RemoveRangeFromSortedSet(key, size, 9999999); }; return TryRedisWrite(fun,0); } /// <summary> /// 获取SortedSet的长度 /// </summary> /// <param name="key"></param> /// <returns></returns> public int SortedSet_Count(string key) { Func<IRedisClient, int> fun = (IRedisClient client) => { return client.GetSortedSetCount(key); }; return TryRedisWrite(fun,0); } /// <summary> /// 获取SortedSet的分页数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <returns></returns> public List<T> SortedSet_GetList<T>(string key, int pageIndex, int pageSize) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { var list = client.GetRangeFromSortedSet(key, (pageIndex - 1) * pageSize, pageIndex * pageSize - 1); if (list != null && list.Count > 0) { List<T> result = new List<T>(); foreach (var item in list) { var data = item.DeserializeFromJson<T>(false); result.Add(data); } return result; } return null; }; return TryRedisRead(fun,0); } /// <summary> /// 获取SortedSet的全部数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pageIndex"></param> /// <param name="pageSize"></param> /// <returns></returns> public List<T> SortedSet_GetListALL<T>(string key) { Func<IRedisClient, List<T>> fun = (IRedisClient client) => { var list = client.GetRangeFromSortedSet(key, 0, 9999999); if (list != null && list.Count > 0) { List<T> result = new List<T>(); foreach (var item in list) { var data = item.DeserializeFromJson<T>(false); result.Add(data); } return result; } return null; }; return TryRedisWrite(fun,0); } /// <summary> /// 设置缓存过期 /// </summary> /// <param name="key"></param> /// <param name="datetime"></param> public bool SortedSet_SetExpire(string key, DateTime datetime) { Func<IRedisClient, bool> fun = (IRedisClient client) => { return client.ExpireEntryAt(key, datetime); }; return TryRedisWrite(fun,0); } #endregion /// <summary> /// 通过key删除数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public bool KRemove(string key) { Func<IRedisClient, bool> fun = (IRedisClient client) => { return client.Remove(key); }; return TryRedisRead(fun,0); } #endregion 写对象 #region 读对象 /// <summary> /// 根据ID获取指定对象 Hash类型数据 /// </summary> /// <param name="key">需要获取的主键,一般为对象ID值</param> /// <returns></returns> public T HGet<T>(string key) { if (key == null) { return default(T); } Func<IRedisClient, T> fun = (IRedisClient client) => { string ser = ""; string hashId = GetEntryId<T>(); ser = client.GetValueFromHash(hashId, key.ToString()); return ser == null ? default(T) : ser.DeserializeFromJson<T>(false); }; return TryRedisRead(fun,0); } //以hash方式存储 public List<string> GetHashKeys<T>(string hashKey) { Func<IRedisClient, List<string>> fun = (IRedisClient client) => { return client.GetHashKeys(hashKey); }; return TryRedisRead(fun,0); } /// <summary> /// 判断key是否存在 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public bool KIsExist(string key) { Func<IRedisClient, bool> fun = (IRedisClient client) => { string ser = ""; ser = client.GetValue(key.ToString()); return string.IsNullOrEmpty(ser) == false; }; return TryRedisRead(fun,0); } /// <summary> /// 读取Key/Value值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T KGet<T>(string key) { Func<IRedisClient, T> fun = (IRedisClient client) => { string ser = ""; ser = client.GetValue(key); if (string.IsNullOrEmpty(ser) == false) { return ser.DeserializeFromJson<T>(false); } else { return default(T); } }; return TryRedisRead(fun,0); } public string GetStr(string key) { Func<IRedisClient, string> fun = (IRedisClient client) => { string ser = ""; ser = client.GetValue(key); if (string.IsNullOrEmpty(ser) == false) { return ser; } else { return default(string); } }; return TryRedisRead(fun,0); } /// <summary> /// 读取Key/Value值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys"></param> /// <returns></returns> public Dictionary<string, T> KGet<T>(IList<string> keys) { Func<IRedisClient, Dictionary<string, T>> fun = (IRedisClient client) => { return (Dictionary<string, T>)client.GetAll<T>(keys); }; return TryRedisRead(fun,0); } /// <summary> /// 读取Key/Value值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys"></param> /// <returns></returns> public IList<T> KGetList<T>(IList<string> keys) { Dictionary<string, T> dics = KGet<T>(keys); return dics.Values.ToList(); } /// <summary> /// 返回根据条件查找到的KEY对象列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="pattern"></param> /// <returns></returns> public IList<string> KSearchKeys(string pattern) { Func<IRedisClient, IList<string>> fun = (IRedisClient client) => { return client.SearchKeys(pattern); }; return TryRedisRead(fun,0); } /// <summary> /// 返回根据条件查找到的value对象列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="pattern"></param> /// <returns></returns> public IList<T> KSearchValues<T>(string pattern) { Func<IRedisClient, IList<T>> fun = (IRedisClient client) => { IList<string> keys = new List<string>(); //先查找KEY keys = client.SearchKeys(pattern); if (keys != null && keys.Count > 0) { //再直接根据key返回对象列表 Dictionary<string, T> dics = (Dictionary<string, T>)client.GetAll<T>(keys); return dics.Values.ToList<T>(); } else { return new List<T>(); } }; return TryRedisRead(fun,0); } #endregion 读对象 #region List方式存储以及操作 /// <summary> /// 入队 /// </summary> /// <param name="hashKey"></param> /// <param name="key"></param> /// <param name="values"></param> /// <param name="db"></param> /// <returns></returns> public bool EnqueueList(string listId, string values, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.EnqueueItemOnList(listId, values); return true; }; return TryRedisWrite(fun, db); } /// /// 出队 /// </summary> /// <param name="hashKey"></param> /// <param name="key"></param> /// <param name="values"></param> /// <param name="db"></param> /// <returns></returns> public string DequeueList(string listId, int db) { Func<IRedisClient, string> fun = (IRedisClient client) => { return client.DequeueItemFromList(listId); }; return TryRedisRead(fun, db); } /// /// 获取队列的数量 /// </summary> /// <param name="hashKey"></param> /// <param name="key"></param> /// <param name="values"></param> /// <param name="db"></param> /// <returns></returns> public int GetListCount(string listId, int db) { Func<IRedisClient, int> fun = (IRedisClient client) => { return client.GetListCount(listId); }; return TryRedisRead(fun, db); } #endregion #region hash方式存储及操作 /// <summary> /// 以hash方式存储 /// </summary> /// <param name="hashKey"></param> /// <param name="key"></param> /// <param name="values"></param> /// <param name="db"></param> /// <returns></returns> public bool SetHash(string hashKey, string key, string values, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.SetEntryInHash(hashKey, key, values); return true; }; return TryRedisWrite(fun, db); } /// <summary> /// 移除指定的记录 /// </summary> /// <param name="key">需要移除的主键,一般为对象ID值</param> /// <returns></returns> public bool RemoveEntryFromHash(string hashId, string key, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { return client.RemoveEntryFromHash(hashId, key); }; return TryRedisWrite<bool>(fun, db); } /// <summary> /// 获取所有hashid数据集的key/value数据集合 /// </summary> public Dictionary<string, string> GetAllEntriesFromHash(string hashid, int db) { Func<IRedisClient, Dictionary<string, string>> fun = (IRedisClient client) => { return client.GetAllEntriesFromHash(hashid); }; return TryRedisRead(fun, db); } /// <summary> /// 获取hashid数据集中所有key的集合 /// </summary> /// <param name="hashid"></param> /// <param name="db"></param> /// <returns></returns> public List<string> GetHashKeys(string hashid, int db) { Func<IRedisClient, List<string>> fun = (IRedisClient client) => { return client.GetHashKeys(hashid); }; return TryRedisRead(fun, db); } /// <summary> /// 获取hashid数据集中的所有value集合 /// </summary> public List<string> GetHashValues(string hashid, int db) { Func<IRedisClient, List<string>> fun = (IRedisClient client) => { return client.GetHashValues(hashid); }; return TryRedisRead(fun, db); } /// <summary> /// 获取hashid数据集中,key的value数据 /// </summary> public string GetValueFromHash(string hashid, string key, int db) { Func<IRedisClient, string> fun = (IRedisClient client) => { return client.GetValueFromHash(hashid, key); }; return TryRedisRead(fun, db); } /// <summary> /// 判断hashid数据集中是否存在key的数据 /// </summary> public bool HashContainsEntry(string hashid, string key, int db) { Func<IRedisClient, bool> fun = (IRedisClient client) => { return client.HashContainsEntry(hashid, key); }; return TryRedisWrite<bool>(fun, db); } #endregion #region 推送消息 /// <summary> /// 推送消息 /// </summary> /// <param name="toChannel">频道名称</param> /// <param name="message">消息名称</param> /// <param name="db">数据库</param> /// <returns></returns> public int PublishMessage(string toChannel, string message, int db) { Func<IRedisClient, int> fun = (IRedisClient client) => { return client.PublishMessage(toChannel, message); }; return TryRedisWrite<int>(fun, db); } /// <summary> /// 创建一个Subscription /// </summary> /// <param name="db"></param> /// <returns></returns> public IRedisSubscription CreateSubscription(int db) { Func<IRedisClient, IRedisSubscription> fun = (IRedisClient client) => { return client.CreateSubscription(); }; return TryRedisWrite<IRedisSubscription>(fun, db); } #endregion #region 通用的读写方法 /// <summary> /// 通用读取数据方法 /// </summary> /// <typeparam name="F"></typeparam> /// <param name="doRead"></param> /// <returns></returns> private F TryRedisRead<F>(Func<IRedisClient, F> doRead, int db) { using (PooledRedisClientManager prcm = Managers.Instance().GetManagers(db)) { IRedisClient client = null; try { using (client = prcm.GetReadOnlyClient()) { return doRead(client); } } catch (RedisException ex) { if (DateTime.Now > Monitor_RedisStatusDateTime) { string SystemErrorEmailTo = TCConfigManager.GetConfig("SystemErrorEmailTo"); EmailCommom.SendEmail(SystemErrorEmailTo, "", "RedisErr", ex.Message, "", ""); FileLog.AddLog("Redis_TryRedisRead", ex.Message); Monitor_RedisStatusDateTime = DateTime.Now.AddMinutes(30); } return default(F); } finally { if (client != null) { prcm.Dispose(); client.Dispose(); } } } } private static DateTime Monitor_RedisStatusDateTime = DateTime.Now; /// <summary> /// 通用写入数据方法 /// </summary> /// <typeparam name="F"></typeparam> /// <param name="doWrite"></param> /// <returns></returns> private F TryRedisWrite<F>(Func<IRedisClient, F> doWrite, int db) { using (PooledRedisClientManager prcm = Managers.Instance().GetManagers(db)) { IRedisClient client = null; try { using (client = prcm.GetClient()) { return doWrite(client); } } catch (RedisException ex) { if (DateTime.Now > Monitor_RedisStatusDateTime) { string SystemErrorEmailTo = TCConfigManager.GetConfig("SystemErrorEmailTo"); EmailCommom.SendEmail(SystemErrorEmailTo, "", "RedisErr", ex.Message, "", ""); FileLog.AddLog("Redis_TryRedisWrite", ex.Message); Monitor_RedisStatusDateTime = DateTime.Now.AddMinutes(30); } return default(F); } finally { if (client != null) { prcm.Dispose(); client.Dispose(); } } } } #endregion } }
//
https://files.cnblogs.com/files/yyyuguo/Redis.zip