下面額代碼類均是經過 ServiceStack.Redis 來對Redis進行各類操做redis
redis 文件配置類數據庫
/// <summary> /// redis配置文件信息 /// 也能夠放到配置文件去 /// </summary> public sealed class RedisConfigInfo { /// <summary> /// 可寫的Redis連接地址 /// format:ip1,ip2 /// /// 默認6379端口 /// </summary> public string WriteServerList = "127.0.0.1:6379"; /// <summary> /// 可讀的Redis連接地址 /// format:ip1,ip2 /// </summary> public string ReadServerList = "127.0.0.1:6379"; /// <summary> /// 最大寫連接數 /// </summary> public int MaxWritePoolSize = 60; /// <summary> /// 最大讀連接數 /// </summary> public int MaxReadPoolSize = 60; /// <summary> /// 本地緩存到期時間,單位:秒 /// </summary> public int LocalCacheTime = 180; /// <summary> /// 自動重啓 /// </summary> public bool AutoStart = true; /// <summary> /// 是否記錄日誌,該設置僅用於排查redis運行時出現的問題, /// 如redis工做正常,請關閉該項 /// </summary> public bool RecordeLog = false; }
redis操做的基類json
/// <summary> /// RedisBase類,是redis操做的基類,繼承自IDisposable接口,主要用於釋放內存 /// </summary> public abstract class RedisBase : IDisposable { public IRedisClient iClient { get; private set; } /// <summary> /// 構造時完成連接的打開 /// </summary> public RedisBase() { iClient = RedisManager.GetClient(); } //public static IRedisClient iClient { get; private set; } //static RedisBase() //{ // iClient = RedisManager.GetClient(); //} private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!this._disposed) { if (disposing) { iClient.Dispose(); iClient = null; } } this._disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Transcation() { using (IRedisTransaction irt = this.iClient.CreateTransaction()) { try { irt.QueueCommand(r => r.Set("key", 20)); irt.QueueCommand(r => r.Increment("key", 1)); irt.Commit(); // 提交事務 } catch (Exception ex) { irt.Rollback(); throw ex; } } } /// <summary> /// 清除所有數據 請當心 /// </summary> public virtual void FlushAll() { iClient.FlushAll(); } /// <summary> /// 保存數據DB文件到硬盤 /// </summary> public void Save() { iClient.Save();//阻塞式save } /// <summary> /// 異步保存數據DB文件到硬盤 /// </summary> public void SaveAsync() { iClient.SaveAsync();//異步save } }
Redis管理中心緩存
/// <summary> /// Redis管理中心 /// </summary> public class RedisManager { /// <summary> /// redis配置文件信息 /// </summary> private static RedisConfigInfo RedisConfigInfo = new RedisConfigInfo(); /// <summary> /// Redis客戶端池化管理 /// </summary> private static PooledRedisClientManager prcManager; /// <summary> /// 靜態構造方法,初始化連接池管理對象 /// </summary> static RedisManager() { CreateManager(); } /// <summary> /// 建立連接池管理對象 /// </summary> private static void CreateManager() { string[] WriteServerConStr = RedisConfigInfo.WriteServerList.Split(','); string[] ReadServerConStr = RedisConfigInfo.ReadServerList.Split(','); prcManager = new PooledRedisClientManager(ReadServerConStr, WriteServerConStr, new RedisClientManagerConfig { MaxWritePoolSize = RedisConfigInfo.MaxWritePoolSize, MaxReadPoolSize = RedisConfigInfo.MaxReadPoolSize, AutoStart = RedisConfigInfo.AutoStart, }); } /// <summary> /// 客戶端緩存操做對象 /// </summary> public static IRedisClient GetClient() { return prcManager.GetClient(); } }
redis 的string類型操做類服務器
/// <summary> /// key-value 鍵值對:value能夠是序列化的數據 /// </summary> public class RedisStringService : RedisBase { #region 賦值 /// <summary> /// 設置key的value /// </summary> public bool Set<T>(string key, T value) { return base.iClient.Set<T>(key, value); } /// <summary> /// 設置key的value並設置過時時間 /// </summary> public bool Set<T>(string key, T value, DateTime dt) { return base.iClient.Set<T>(key, value, dt); } /// <summary> /// 設置key的value並設置過時時間 /// </summary> public bool Set<T>(string key, T value, TimeSpan sp) { return base.iClient.Set<T>(key, value, sp); } /// <summary> /// 設置多個key/value /// </summary> public void Set(Dictionary<string, string> dic) { base.iClient.SetAll(dic); } #endregion #region 追加 /// <summary> /// 在原有key的value值以後追加value,沒有就新增一項 /// </summary> public long Append(string key, string value) { return base.iClient.AppendToValue(key, value); } #endregion #region 獲取值 /// <summary> /// 獲取key的value值 /// </summary> public string Get(string key) { return base.iClient.GetValue(key); } /// <summary> /// 獲取多個key的value值 /// </summary> public List<string> Get(List<string> keys) { return base.iClient.GetValues(keys); } /// <summary> /// 獲取多個key的value值 /// </summary> public List<T> Get<T>(List<string> keys) { return base.iClient.GetValues<T>(keys); } #endregion #region 獲取舊值賦上新值 /// <summary> /// 獲取舊值賦上新值 /// </summary> public string GetAndSetValue(string key, string value) { return base.iClient.GetAndSetValue(key, value); } #endregion #region 輔助方法 /// <summary> /// 獲取值的長度 /// </summary> public long GetLength(string key) { return base.iClient.GetStringCount(key); } /// <summary> /// 自增1,返回自增後的值 /// </summary> public long Incr(string key) { return base.iClient.IncrementValue(key); } /// <summary> /// 自增count,返回自增後的值 /// </summary> public long IncrBy(string key, int count) { return base.iClient.IncrementValueBy(key, count); } /// <summary> /// 自減1,返回自減後的值 /// </summary> public long Decr(string key) { return base.iClient.DecrementValue(key); } /// <summary> /// 自減count ,返回自減後的值 /// </summary> /// <param name="key"></param> /// <param name="count"></param> /// <returns></returns> public long DecrBy(string key, int count) { return base.iClient.DecrementValueBy(key, count); } #endregion }
使用數據結構
using (RedisStringService service = new RedisStringService()) { service.Set<string>("student1", "夢的翅膀"); Console.WriteLine(service.Get("student1")); service.Append("student1", "20180802"); Console.WriteLine(service.Get("student1")); Console.WriteLine(service.GetAndSetValue("student1", "程序錯誤")); Console.WriteLine(service.Get("student1")); service.Set<string>("student2", "王", DateTime.Now.AddSeconds(5)); Thread.Sleep(5100); Console.WriteLine(service.Get("student2")); service.Set<int>("Age", 32); Console.WriteLine(service.Incr("Age")); Console.WriteLine(service.IncrBy("Age", 3)); Console.WriteLine(service.Decr("Age")); Console.WriteLine(service.DecrBy("Age", 3)); }
超賣多線程
/// <summary> /// 超賣:訂單數超過商品 /// ///數據庫:秒殺的時候,10件商品,100我的想買,假定你們一瞬間都來了, ///A 查詢還有沒有--有---1更新 ///B 查詢還有沒有--有---1更新 ///C 查詢還有沒有--有---1更新 ///可能會賣出12 12甚至20件商品 /// /// 微服務也有超賣的問題,異步隊列 /// /// /// Redis原子性操做--保證一個數值只出現一次--防止一個商品賣給多我的 /// /// /// Redis是單線程,程序怎麼又多線程操做Redis呢? 這個是能夠的, /// 打開多個連接,去提交任務,對程序而言,Redis是併發 /// /// 假如redis命令是拼裝的,Decr---1 獲取值 2 程序減1 3 再save結果回去 /// 程序多線程併發一下, A線程 1 2 3 初始值是10 /// B線程 1 2 3 結果是9,減了2次可是結果是9 /// /// 組合命令,Decr Redis線程直接完成當前值-1並返回結果,原子性操做 /// 程序多線程併發一下,A線程 123 初始值10 /// B線程 123 /// C線程 123 獲得3個結果,9/8/7 /// /// 假如庫存只有1個(數據庫),三我的同時來下單,一檢測>0,都會成功--超賣 /// 三我的同時來,lock/開啓事務 /// 只有一我的能去檢測>0 -1 save /// 而後第二我的來,==0 返回失敗 /// 而後第三我的來,==0 返回失敗 /// 由於這個等因而數據庫單線程了,其餘都要阻塞,各類超時 /// -1的時候除了操做庫存,還得增長訂單,等支付。。 /// 10個商品秒殺,一次只能進一個? 違背了業務 /// /// 因此用上了Redis,一方面保證絕對不會超賣, /// 另外一方面沒有效率影響,數據庫是能夠爲成功的人併發的 /// 還有撤單的時候增長庫存,能夠繼續秒殺, /// 限制秒殺的庫存是放在redis,不是數據庫,不會形成數據的不一致性 /// /// Redis可以攔截無效的請求,若是沒有這一層,全部的請求壓力都到數據庫 /// /// 緩存擊穿/穿透---緩存down掉,請求所有到數據庫 /// 緩存預熱功能---緩存重啓,數據丟失,多了一個初始化緩存數據動做(寫代碼去把數據讀出來放入緩存)
模擬超賣現象併發
public class OversellField { private static bool IsGoOn = true;//秒殺活動是否結束 private static int Stock = 0; public static void Show() { Stock = 10; for (int i = 0; i < 5000; i++) { int k = i; Task.Run(() =>//每一個線程就是一個用戶請求 { if (IsGoOn) { long index = Stock;//-1而且返回 去數據庫查一下當前的庫存 Thread.Sleep(100); if (index >= 1) { Stock = Stock - 1;//更新庫存 Console.WriteLine($"{k.ToString("000")}秒殺成功,秒殺商品索引爲{index}"); //能夠分隊列,去數據庫操做 } else { if (IsGoOn) { IsGoOn = false; } Console.WriteLine($"{k.ToString("000")}秒殺失敗,秒殺商品索引爲{index}"); } } else { Console.WriteLine($"{k.ToString("000")}秒殺中止......"); } }); } Console.Read(); } }
利用redis解決超賣問題dom
public class OversellTest { private static bool IsGoOn = true;//秒殺活動是否結束 public static void Show() { using (RedisStringService service = new RedisStringService()) { service.Set<int>("Stock", 10);//是庫存 } for (int i = 0; i < 5000; i++) { int k = i; Task.Run(() =>//每一個線程就是一個用戶請求 { using (RedisStringService service = new RedisStringService()) { if (IsGoOn) { long index = service.Decr("Stock");//-1而且返回 if (index >= 0) { Console.WriteLine($"{k.ToString("000")}秒殺成功,秒殺商品索引爲{index}"); //service.Incr("Stock");//+1 //能夠分隊列,去數據庫操做 } else { if (IsGoOn) { IsGoOn = false; } Console.WriteLine($"{k.ToString("000")}秒殺失敗,秒殺商品索引爲{index}"); } } else { Console.WriteLine($"{k.ToString("000")}秒殺中止......"); } } }); } Console.Read(); } }
redis 的Hash類型操做類異步
/// <summary> /// Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段 /// string的話要麼是 001:序列化整個實體 /// 要麼是 001_name: 001_pwd: 多個key-value /// Hash的話,一個hashid-{key:value;key:value;key:value;} /// 能夠一次性查找實體,也能夠單個,還能夠單個修改 /// </summary> public class RedisHashService : RedisBase { #region 添加 /// <summary> /// 向hashid集合中添加key/value /// </summary> public bool SetEntryInHash(string hashid, string key, string value) { return base.iClient.SetEntryInHash(hashid, key, value); } /// <summary> /// 若是hashid集合中存在key/value則不添加返回false, /// 若是不存在在添加key/value,返回true /// </summary> public bool SetEntryInHashIfNotExists(string hashid, string key, string value) { return base.iClient.SetEntryInHashIfNotExists(hashid, key, value); } /// <summary> /// 存儲對象T t到hash集合中 /// 須要包含Id,而後用Id獲取 /// </summary> public void StoreAsHash<T>(T t) { base.iClient.StoreAsHash<T>(t); } #endregion #region 獲取 /// <summary> /// 獲取對象T中ID爲id的數據。 /// </summary> public T GetFromHash<T>(object id) { return base.iClient.GetFromHash<T>(id); } /// <summary> /// 獲取全部hashid數據集的key/value數據集合 /// </summary> public Dictionary<string, string> GetAllEntriesFromHash(string hashid) { return base.iClient.GetAllEntriesFromHash(hashid); } /// <summary> /// 獲取hashid數據集中的數據總數 /// </summary> public long GetHashCount(string hashid) { return base.iClient.GetHashCount(hashid); } /// <summary> /// 獲取hashid數據集中全部key的集合 /// </summary> public List<string> GetHashKeys(string hashid) { return base.iClient.GetHashKeys(hashid); } /// <summary> /// 獲取hashid數據集中的全部value集合 /// </summary> public List<string> GetHashValues(string hashid) { return base.iClient.GetHashValues(hashid); } /// <summary> /// 獲取hashid數據集中,key的value數據 /// </summary> public string GetValueFromHash(string hashid, string key) { return base.iClient.GetValueFromHash(hashid, key); } /// <summary> /// 獲取hashid數據集中,多個keys的value集合 /// </summary> public List<string> GetValuesFromHash(string hashid, string[] keys) { return base.iClient.GetValuesFromHash(hashid, keys); } #endregion #region 刪除 /// <summary> /// 刪除hashid數據集中的key數據 /// </summary> public bool RemoveEntryFromHash(string hashid, string key) { return base.iClient.RemoveEntryFromHash(hashid, key); } #endregion #region 其它 /// <summary> /// 判斷hashid數據集中是否存在key的數據 /// </summary> public bool HashContainsEntry(string hashid, string key) { return base.iClient.HashContainsEntry(hashid, key); } /// <summary> /// 給hashid數據集key的value加countby,返回相加後的數據 /// </summary> public double IncrementValueInHash(string hashid, string key, double countBy) { return base.iClient.IncrementValueInHash(hashid, key, countBy); } #endregion }
使用
Console.WriteLine("*****************************************"); { using (RedisHashService service = new RedisHashService()) { service.SetEntryInHash("student", "id", "123456"); service.SetEntryInHash("student", "name", "張xx"); service.SetEntryInHash("student", "remark", "高級班的學員"); var keys = service.GetHashKeys("student"); var values = service.GetHashValues("student"); var keyValues = service.GetAllEntriesFromHash("student"); Console.WriteLine(service.GetValueFromHash("student", "id")); service.SetEntryInHashIfNotExists("student", "name", "太子爺"); service.SetEntryInHashIfNotExists("student", "description", "高級班的學員2"); Console.WriteLine(service.GetValueFromHash("student", "name")); Console.WriteLine(service.GetValueFromHash("student", "description")); service.RemoveEntryFromHash("student", "description"); Console.WriteLine(service.GetValueFromHash("student", "description")); } }
redis 的Set類型操做類
/// <summary> /// Set:用哈希表來保持字符串的惟一性,沒有前後順序,存儲一些集合性的數據 /// 1.共同好友、二度好友 /// 2.利用惟一性,能夠統計訪問網站的全部獨立 IP /// </summary> public class RedisSetService : RedisBase { #region 添加 /// <summary> /// key集合中添加value值 /// </summary> public void Add(string key, string value) { base.iClient.AddItemToSet(key, value); } /// <summary> /// key集合中添加list集合 /// </summary> public void Add(string key, List<string> list) { base.iClient.AddRangeToSet(key, list); } #endregion #region 獲取 /// <summary> /// 隨機獲取key集合中的一個值 /// </summary> public string GetRandomItemFromSet(string key) { return base.iClient.GetRandomItemFromSet(key); } /// <summary> /// 獲取key集合值的數量 /// </summary> public long GetCount(string key) { return base.iClient.GetSetCount(key); } /// <summary> /// 獲取全部key集合的值 /// </summary> public HashSet<string> GetAllItemsFromSet(string key) { return base.iClient.GetAllItemsFromSet(key); } #endregion #region 刪除 /// <summary> /// 隨機刪除key集合中的一個值 /// </summary> public string RandomRemoveItemFromSet(string key) { return base.iClient.PopItemFromSet(key); } /// <summary> /// 刪除key集合中的value /// </summary> public void RemoveItemFromSet(string key, string value) { base.iClient.RemoveItemFromSet(key, value); } #endregion #region 其它 /// <summary> /// 從fromkey集合中移除值爲value的值,並把value添加到tokey集合中 /// </summary> public void MoveBetweenSets(string fromkey, string tokey, string value) { base.iClient.MoveBetweenSets(fromkey, tokey, value); } /// <summary> /// 返回keys多個集合中的並集,返還hashset /// </summary> public HashSet<string> GetUnionFromSets(params string[] keys) { return base.iClient.GetUnionFromSets(keys); } /// <summary> /// 返回keys多個集合中的交集,返還hashset /// </summary> public HashSet<string> GetIntersectFromSets(params string[] keys) { return base.iClient.GetIntersectFromSets(keys); } /// <summary> /// 返回keys多個集合中的差集,返還hashset /// </summary> /// <param name="fromKey">原集合</param> /// <param name="keys">其餘集合</param> /// <returns>出如今原集合,但不包含在其餘集合</returns> public HashSet<string> GetDifferencesFromSet(string fromKey, params string[] keys) { return base.iClient.GetDifferencesFromSet(fromKey,keys); } /// <summary> /// keys多個集合中的並集,放入newkey集合中 /// </summary> public void StoreUnionFromSets(string newkey, string[] keys) { base.iClient.StoreUnionFromSets(newkey, keys); } /// <summary> /// 把fromkey集合中的數據與keys集合中的數據對比,fromkey集合中不存在keys集合中,則把這些不存在的數據放入newkey集合中 /// </summary> public void StoreDifferencesFromSet(string newkey, string fromkey, string[] keys) { base.iClient.StoreDifferencesFromSet(newkey, fromkey, keys); } #endregion }
使用
Console.WriteLine("*****************************************"); { using (RedisSetService service = new RedisSetService()) { service.FlushAll();//清理所有數據 service.Add("advanced", "111"); service.Add("advanced", "112"); service.Add("advanced", "114"); service.Add("advanced", "114"); service.Add("advanced", "115"); service.Add("advanced", "115"); service.Add("advanced", "113"); var result = service.GetAllItemsFromSet("advanced"); var random = service.GetRandomItemFromSet("advanced");//隨機獲取 service.GetCount("advanced");//獨立的ip數 service.RemoveItemFromSet("advanced", "114"); { service.Add("begin", "111"); service.Add("begin", "112"); service.Add("begin", "115"); service.Add("end", "111"); service.Add("end", "114"); service.Add("end", "113"); var result1 = service.GetIntersectFromSets("begin", "end"); var result2 = service.GetDifferencesFromSet("begin", "end"); var result3 = service.GetUnionFromSets("begin", "end"); //共同好友 共同關注 } } }
去重驗證
刪除Item驗證
集合的交差並
redis 的zset類型操做類
/// <summary> /// Sorted Sets是將 Set 中的元素增長了一個權重參數 score,使得集合中的元素可以按 score 進行有序排列 /// 1.帶有權重的元素,好比一個遊戲的用戶得分排行榜 /// 2.比較複雜的數據結構,通常用到的場景不算太多 /// </summary> public class RedisZSetService : RedisBase { #region 添加 /// <summary> /// 添加key/value,默認分數是從1.多*10的9次方以此遞增的,自帶自增效果 /// </summary> public bool Add(string key, string value) { return base.iClient.AddItemToSortedSet(key, value); } /// <summary> /// 添加key/value,並設置value的分數 /// </summary> public bool AddItemToSortedSet(string key, string value, double score) { return base.iClient.AddItemToSortedSet(key, value, score); } /// <summary> /// 爲key添加values集合,values集合中每一個value的分數設置爲score /// </summary> public bool AddRangeToSortedSet(string key, List<string> values, double score) { return base.iClient.AddRangeToSortedSet(key, values, score); } /// <summary> /// 爲key添加values集合,values集合中每一個value的分數設置爲score /// </summary> public bool AddRangeToSortedSet(string key, List<string> values, long score) { return base.iClient.AddRangeToSortedSet(key, values, score); } #endregion #region 獲取 /// <summary> /// 獲取key的全部集合 /// </summary> public List<string> GetAll(string key) { return base.iClient.GetAllItemsFromSortedSet(key); } /// <summary> /// 獲取key的全部集合,倒敘輸出 /// </summary> public List<string> GetAllDesc(string key) { return base.iClient.GetAllItemsFromSortedSetDesc(key); } /// <summary> /// 獲取集合,帶分數 /// </summary> public IDictionary<string, double> GetAllWithScoresFromSortedSet(string key) { return base.iClient.GetAllWithScoresFromSortedSet(key); } /// <summary> /// 獲取key爲value的下標值 /// </summary> public long GetItemIndexInSortedSet(string key, string value) { return base.iClient.GetItemIndexInSortedSet(key, value); } /// <summary> /// 倒敘排列獲取key爲value的下標值 /// </summary> public long GetItemIndexInSortedSetDesc(string key, string value) { return base.iClient.GetItemIndexInSortedSetDesc(key, value); } /// <summary> /// 獲取key爲value的分數 /// </summary> public double GetItemScoreInSortedSet(string key, string value) { return base.iClient.GetItemScoreInSortedSet(key, value); } /// <summary> /// 獲取key全部集合的數據總數 /// </summary> public long GetSortedSetCount(string key) { return base.iClient.GetSortedSetCount(key); } /// <summary> /// key集合數據從分數爲fromscore到分數爲toscore的數據總數 /// </summary> public long GetSortedSetCount(string key, double fromScore, double toScore) { return base.iClient.GetSortedSetCount(key, fromScore, toScore); } /// <summary> /// 獲取key集合從高分到低分排序數據,分數從fromscore到分數爲toscore的數據 /// </summary> public List<string> GetRangeFromSortedSetByHighestScore(string key, double fromscore, double toscore) { return base.iClient.GetRangeFromSortedSetByHighestScore(key, fromscore, toscore); } /// <summary> /// 獲取key集合從低分到高分排序數據,分數從fromscore到分數爲toscore的數據 /// </summary> public List<string> GetRangeFromSortedSetByLowestScore(string key, double fromscore, double toscore) { return base.iClient.GetRangeFromSortedSetByLowestScore(key, fromscore, toscore); } /// <summary> /// 獲取key集合從高分到低分排序數據,分數從fromscore到分數爲toscore的數據,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetByHighestScore(string key, double fromscore, double toscore) { return base.iClient.GetRangeWithScoresFromSortedSetByHighestScore(key, fromscore, toscore); } /// <summary> /// 獲取key集合從低分到高分排序數據,分數從fromscore到分數爲toscore的數據,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetByLowestScore(string key, double fromscore, double toscore) { return base.iClient.GetRangeWithScoresFromSortedSetByLowestScore(key, fromscore, toscore); } /// <summary> /// 獲取key集合數據,下標從fromRank到分數爲toRank的數據 /// </summary> public List<string> GetRangeFromSortedSet(string key, int fromRank, int toRank) { return base.iClient.GetRangeFromSortedSet(key, fromRank, toRank); } /// <summary> /// 獲取key集合倒敘排列數據,下標從fromRank到分數爲toRank的數據 /// </summary> public List<string> GetRangeFromSortedSetDesc(string key, int fromRank, int toRank) { return base.iClient.GetRangeFromSortedSetDesc(key, fromRank, toRank); } /// <summary> /// 獲取key集合數據,下標從fromRank到分數爲toRank的數據,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSet(string key, int fromRank, int toRank) { return base.iClient.GetRangeWithScoresFromSortedSet(key, fromRank, toRank); } /// <summary> /// 獲取key集合倒敘排列數據,下標從fromRank到分數爲toRank的數據,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetDesc(string key, int fromRank, int toRank) { return base.iClient.GetRangeWithScoresFromSortedSetDesc(key, fromRank, toRank); } #endregion #region 刪除 /// <summary> /// 刪除key爲value的數據 /// </summary> public bool RemoveItemFromSortedSet(string key, string value) { return base.iClient.RemoveItemFromSortedSet(key, value); } /// <summary> /// 刪除下標從minRank到maxRank的key集合數據 /// </summary> public long RemoveRangeFromSortedSet(string key, int minRank, int maxRank) { return base.iClient.RemoveRangeFromSortedSet(key, minRank, maxRank); } /// <summary> /// 刪除分數從fromscore到toscore的key集合數據 /// </summary> public long RemoveRangeFromSortedSetByScore(string key, double fromscore, double toscore) { return base.iClient.RemoveRangeFromSortedSetByScore(key, fromscore, toscore); } /// <summary> /// 刪除key集合中分數最大的數據 /// </summary> public string PopItemWithHighestScoreFromSortedSet(string key) { return base.iClient.PopItemWithHighestScoreFromSortedSet(key); } /// <summary> /// 刪除key集合中分數最小的數據 /// </summary> public string PopItemWithLowestScoreFromSortedSet(string key) { return base.iClient.PopItemWithLowestScoreFromSortedSet(key); } #endregion #region 其它 /// <summary> /// 判斷key集合中是否存在value數據 /// </summary> public bool SortedSetContainsItem(string key, string value) { return base.iClient.SortedSetContainsItem(key, value); } /// <summary> /// 爲key集合值爲value的數據,分數加scoreby,返回相加後的分數 /// </summary> public double IncrementItemInSortedSet(string key, string value, double scoreBy) { return base.iClient.IncrementItemInSortedSet(key, value, scoreBy); } /// <summary> /// 獲取keys多個集合的交集,並把交集添加的newkey集合中,返回交集數據的總數 /// </summary> public long StoreIntersectFromSortedSets(string newkey, string[] keys) { return base.iClient.StoreIntersectFromSortedSets(newkey, keys); } /// <summary> /// 獲取keys多個集合的並集,並把並集數據添加到newkey集合中,返回並集數據的總數 /// </summary> public long StoreUnionFromSortedSets(string newkey, string[] keys) { return base.iClient.StoreUnionFromSortedSets(newkey, keys); } #endregion }
使用除了排序,其餘與Set同樣
Console.WriteLine("*****************************************"); { using (RedisZSetService service = new RedisZSetService()) { service.FlushAll();//清理所有數據 service.Add("advanced", "1"); service.Add("advanced", "2"); service.Add("advanced", "5"); service.Add("advanced", "4"); service.Add("advanced", "7"); service.Add("advanced", "5"); service.Add("advanced", "9"); var result1 = service.GetAll("advanced"); var result2 = service.GetAllDesc("advanced"); service.AddItemToSortedSet("Sort", "BY", 123234); service.AddItemToSortedSet("Sort", "走本身的路", 123); service.AddItemToSortedSet("Sort", "redboy", 45); service.AddItemToSortedSet("Sort", "大蛤蟆", 7567); service.AddItemToSortedSet("Sort", "路人甲", 9879); service.AddRangeToSortedSet("Sort", new List<string>() { "123", "花生", "加菲貓" }, 3232); var result3 = service.GetAllWithScoresFromSortedSet("Sort"); //交叉並 } }
排序值、及排序結果
場景(實時排行)
/// <summary> /// 實時排行榜:刷個禮物 /// 維度不少,平臺/房間/主播/日/周/月/年 /// A對B 刷個禮物,影響不少 /// 刷禮物只記錄流水,不影響排行,凌晨24點跑任務更新 /// /// 實時排行榜 /// Redis-IncrementItemInSortedSet /// 刷禮物時增長redis分數 /// 就能夠實時獲取最新的排行 /// (多個維度就是多個zSet,刷禮物的時候保存數據庫並更新Redis) /// </summary> public class RankManager { private static List<string> UserList = new List<string>() { "Tenk","花生","Ray","阿莫西林","石昊","ywa" }; public static void Show() { using (RedisZSetService service = new RedisZSetService()) { service.FlushAll();//清理所有數據 Task.Run(() => { while (true) { foreach (var user in UserList) { Thread.Sleep(10); service.IncrementItemInSortedSet("陳一發兒", user, new Random().Next(1, 100));//表示在原來刷禮物的基礎上增長禮物 } Thread.Sleep(20 * 1000); } }); Task.Run(() => { while (true) { Thread.Sleep(12 * 1000); Console.WriteLine("**********當前排行************"); int i = 1; foreach (var item in service.GetAllWithScoresFromSortedSet("陳一發兒")) { Console.WriteLine($"第{i++}名 {item.Key} 分數{item.Value}"); } //foreach (var item in service.GetAllDesc("陳一發兒")) //{ // Console.WriteLine($"第{i++}名 {item}"); //} } }); Console.Read(); } } }
redis 的List類型操做類
/// <summary> /// Redis list的實現爲一個雙向鏈表,便可以支持反向查找和遍歷,更方便操做,不過帶來了部分額外的內存開銷, /// Redis內部的不少實現,包括髮送緩衝隊列等也都是用的這個數據結構。 /// </summary> public class RedisListService : RedisBase { #region 賦值 /// <summary> /// 從左側向list中添加值 /// </summary> public void LPush(string key, string value) { base.iClient.PushItemToList(key, value); } /// <summary> /// 從左側向list中添加值,並設置過時時間 /// </summary> public void LPush(string key, string value, DateTime dt) { base.iClient.PushItemToList(key, value); base.iClient.ExpireEntryAt(key, dt); } /// <summary> /// 從左側向list中添加值,設置過時時間 /// </summary> public void LPush(string key, string value, TimeSpan sp) { base.iClient.PushItemToList(key, value); base.iClient.ExpireEntryIn(key, sp); } /// <summary> /// 從右側向list中添加值 /// </summary> public void RPush(string key, string value) { base.iClient.PrependItemToList(key, value); } /// <summary> /// 從右側向list中添加值,並設置過時時間 /// </summary> public void RPush(string key, string value, DateTime dt) { base.iClient.PrependItemToList(key, value); base.iClient.ExpireEntryAt(key, dt); } /// <summary> /// 從右側向list中添加值,並設置過時時間 /// </summary> public void RPush(string key, string value, TimeSpan sp) { base.iClient.PrependItemToList(key, value); base.iClient.ExpireEntryIn(key, sp); } /// <summary> /// 添加key/value /// </summary> public void Add(string key, string value) { base.iClient.AddItemToList(key, value); } /// <summary> /// 添加key/value ,並設置過時時間 /// </summary> public void Add(string key, string value, DateTime dt) { base.iClient.AddItemToList(key, value); base.iClient.ExpireEntryAt(key, dt); } /// <summary> /// 添加key/value。並添加過時時間 /// </summary> public void Add(string key, string value, TimeSpan sp) { base.iClient.AddItemToList(key, value); base.iClient.ExpireEntryIn(key, sp); } /// <summary> /// 爲key添加多個值 /// </summary> public void Add(string key, List<string> values) { base.iClient.AddRangeToList(key, values); } /// <summary> /// 爲key添加多個值,並設置過時時間 /// </summary> public void Add(string key, List<string> values, DateTime dt) { base.iClient.AddRangeToList(key, values); base.iClient.ExpireEntryAt(key, dt); } /// <summary> /// 爲key添加多個值,並設置過時時間 /// </summary> public void Add(string key, List<string> values, TimeSpan sp) { base.iClient.AddRangeToList(key, values); base.iClient.ExpireEntryIn(key, sp); } #endregion #region 獲取值 /// <summary> /// 獲取list中key包含的數據數量 /// </summary> public long Count(string key) { return base.iClient.GetListCount(key); } /// <summary> /// 獲取key包含的全部數據集合 /// </summary> public List<string> Get(string key) { return base.iClient.GetAllItemsFromList(key); } /// <summary> /// 獲取key中下標爲star到end的值集合 /// </summary> public List<string> Get(string key, int star, int end) { return base.iClient.GetRangeFromList(key, star, end); } #endregion #region 阻塞命令 /// <summary> /// 阻塞命令:從list爲key的尾部移除一個值,並返回移除的值,阻塞時間爲sp /// </summary> public string BlockingPopItemFromList(string key, TimeSpan? sp) { return base.iClient.BlockingPopItemFromList(key, sp); } /// <summary> /// 阻塞命令:從多個list中尾部移除一個值,並返回移除的值&key,阻塞時間爲sp /// </summary> public ItemRef BlockingPopItemFromLists(string[] keys, TimeSpan? sp) { return base.iClient.BlockingPopItemFromLists(keys, sp); } /// <summary> /// 阻塞命令:從list中keys的尾部移除一個值,並返回移除的值,阻塞時間爲sp /// </summary> public string BlockingDequeueItemFromList(string key, TimeSpan? sp) { return base.iClient.BlockingDequeueItemFromList(key, sp); } /// <summary> /// 阻塞命令:從多個list中尾部移除一個值,並返回移除的值&key,阻塞時間爲sp /// </summary> public ItemRef BlockingDequeueItemFromLists(string[] keys, TimeSpan? sp) { return base.iClient.BlockingDequeueItemFromLists(keys, sp); } /// <summary> /// 阻塞命令:從list中一個fromkey的尾部移除一個值,添加到另一個tokey的頭部,並返回移除的值,阻塞時間爲sp /// </summary> public string BlockingPopAndPushItemBetweenLists(string fromkey, string tokey, TimeSpan? sp) { return base.iClient.BlockingPopAndPushItemBetweenLists(fromkey, tokey, sp); } #endregion #region 刪除 /// <summary> /// 從尾部移除數據,返回移除的數據 /// </summary> public string PopItemFromList(string key) { var sa = base.iClient.CreateSubscription(); return base.iClient.PopItemFromList(key); } /// <summary> /// 從尾部移除數據,返回移除的數據 /// </summary> public string DequeueItemFromList(string key) { return base.iClient.DequeueItemFromList(key); } /// <summary> /// 移除list中,key/value,與參數相同的值,並返回移除的數量 /// </summary> public long RemoveItemFromList(string key, string value) { return base.iClient.RemoveItemFromList(key, value); } /// <summary> /// 從list的尾部移除一個數據,返回移除的數據 /// </summary> public string RemoveEndFromList(string key) { return base.iClient.RemoveEndFromList(key); } /// <summary> /// 從list的頭部移除一個數據,返回移除的值 /// </summary> public string RemoveStartFromList(string key) { return base.iClient.RemoveStartFromList(key); } #endregion #region 其它 /// <summary> /// 從一個list的尾部移除一個數據,添加到另一個list的頭部,並返回移動的值 /// </summary> public string PopAndPushItemBetweenLists(string fromKey, string toKey) { return base.iClient.PopAndPushItemBetweenLists(fromKey, toKey); } public void TrimList(string key, int start, int end) { base.iClient.TrimList(key, start, end); } #endregion #region 發佈訂閱 public void Publish(string channel, string message) { base.iClient.PublishMessage(channel, message); } public void Subscribe(string channel, Action<string, string, IRedisSubscription> actionOnMessage) { var subscription = base.iClient.CreateSubscription(); subscription.OnSubscribe = c => { Console.WriteLine($"訂閱頻道{c}"); Console.WriteLine(); }; //取消訂閱 subscription.OnUnSubscribe = c => { Console.WriteLine($"取消訂閱 {c}"); Console.WriteLine(); }; subscription.OnMessage += (c, s) => { actionOnMessage(c, s, subscription); }; Console.WriteLine($"開始啓動監聽 {channel}"); subscription.SubscribeToChannels(channel); //blocking } public void UnSubscribeFromChannels(string channel) { var subscription = base.iClient.CreateSubscription(); subscription.UnSubscribeFromChannels(channel); } #endregion }
使用
Console.WriteLine("*****************************************"); { using (RedisListService service = new RedisListService()) { service.FlushAll(); service.Add("article", "eleven1234"); service.Add("article", "kevin"); service.Add("article", "大叔"); service.Add("article", "C卡"); service.Add("article", "觸不到的線"); service.Add("article", "程序錯誤"); var result1 = service.Get("article"); var result2 = service.Get("article", 0, 3); }
後進先出(棧的效果)
service.FlushAll(); service.Add("article", "eleven1234"); service.Add("article", "kevin"); service.Add("article", "大叔"); service.Add("article", "C卡"); service.Add("article", "觸不到的線"); service.Add("article", "程序錯誤"); for (int i = 0; i < 5; i++) { Console.WriteLine(service.PopItemFromList("article")); var result1 = service.Get("article"); }
i=0 時
i=1時
i=2時
先進先出(隊列的效果)
// 隊列:生產者消費者模型 service.FlushAll(); service.RPush("article", "eleven1234"); service.RPush("article", "kevin"); service.RPush("article", "大叔"); service.RPush("article", "C卡"); service.RPush("article", "觸不到的線"); service.RPush("article", "程序錯誤"); for (int i = 0; i < 5; i++) { Console.WriteLine(service.PopItemFromList("article")); var result1 = service.Get("article"); } //分佈式緩存,多服務器均可以訪問到,多個生產者,多個消費者,任何產品只被消費一次
i=0時
i=1時
i=2時
生產者
using (RedisListService service = new RedisListService()) { List<string> stringList = new List<string>(); for (int i = 0; i < 10; i++) { stringList.Add(string.Format($"放入任務{i}")); } service.Add("test", "這是一個學生Add1"); service.Add("test", "這是一個學生Add2"); service.Add("test", "這是一個學生Add3"); service.LPush("test", "這是一個學生LPush1"); service.LPush("test", "這是一個學生LPush2"); service.LPush("test", "這是一個學生LPush3"); service.LPush("test", "這是一個學生LPush4"); service.LPush("test", "這是一個學生LPush5"); service.LPush("test", "這是一個學生LPush6"); service.RPush("test", "這是一個學生RPush1"); service.RPush("test", "這是一個學生RPush2"); service.RPush("test", "這是一個學生RPush3"); service.RPush("test", "這是一個學生RPush4"); service.RPush("test", "這是一個學生RPush5"); service.RPush("test", "這是一個學生RPush6"); service.Add("task", stringList); Console.WriteLine(service.Count("test")); Console.WriteLine(service.Count("task")); var list = service.Get("test"); list = service.Get("task", 2, 4); Action act = new Action(() => { while (true) { Console.WriteLine("************請輸入數據**************"); string testTask = Console.ReadLine(); service.LPush("test", testTask); } }); act.EndInvoke(act.BeginInvoke(null, null)); }
消費者
public class ServiceStackProcessor { public static void Show() { string path = AppDomain.CurrentDomain.BaseDirectory; string tag = path.Split('/', '\\').Last(s => !string.IsNullOrEmpty(s)); Console.WriteLine($"這裏是 {tag} 啓動了。。"); using (RedisListService service = new RedisListService()) { Action act = new Action(() => { while (true) { var result = service.BlockingPopItemFromLists(new string[] { "test", "task" }, TimeSpan.FromHours(3)); Thread.Sleep(100); Console.WriteLine($"這裏是 {tag} 隊列獲取的消息 {result.Id} {result.Item}"); } }); act.EndInvoke(act.BeginInvoke(null, null)); } } }
能夠 一個生產者對應多個消費者,也能夠一個消費者對應多個生產者,多對多也能夠
下面是 一個生產者對應多個消費者的效果圖
發佈訂閱
發佈訂閱:觀察者,一個數據源,多個接受者,只要訂閱了就能夠收到的,能被多個數據源共享
#region 發佈訂閱:觀察者,一個數據源,多個接受者,只要訂閱了就能夠收到的,能被多個數據源共享 Task.Run(() => { using (RedisListService service = new RedisListService()) { //訂閱頻道 service.Subscribe("Eleven", (c, message, iRedisSubscription) => { Console.WriteLine($"註冊{1}{c}:{message},Dosomething else"); if (message.Equals("exit")) iRedisSubscription.UnSubscribeFromChannels("Eleven");//取消訂閱頻道 });//blocking } }); Task.Run(() => { using (RedisListService service = new RedisListService()) { //訂閱頻道 service.Subscribe("Eleven", (c, message, iRedisSubscription) => { Console.WriteLine($"註冊{2}{c}:{message},Dosomething else"); if (message.Equals("exit")) iRedisSubscription.UnSubscribeFromChannels("Eleven");//取消訂閱頻道 });//blocking } }); Task.Run(() => { using (RedisListService service = new RedisListService()) { //訂閱頻道 service.Subscribe("Twelve", (c, message, iRedisSubscription) => { Console.WriteLine($"註冊{3}{c}:{message},Dosomething else"); if (message.Equals("exit")) iRedisSubscription.UnSubscribeFromChannels("Twelve");//取消訂閱頻道 });//blocking } }); using (RedisListService service = new RedisListService()) { Thread.Sleep(1000); //頻道發佈消息 service.Publish("Eleven", "Eleven123"); service.Publish("Eleven", "Eleven234"); service.Publish("Eleven", "Eleven345"); service.Publish("Eleven", "Eleven456"); //頻道發佈消息 service.Publish("Twelve", "Twelve123"); service.Publish("Twelve", "Twelve234"); service.Publish("Twelve", "Twelve345"); service.Publish("Twelve", "Twelve456"); Console.WriteLine("**********************************************"); //頻道發佈 封號退出消息 service.Publish("Eleven", "exit"); service.Publish("Eleven", "123Eleven"); service.Publish("Eleven", "234Eleven"); service.Publish("Eleven", "345Eleven"); service.Publish("Eleven", "456Eleven"); //頻道發佈 封號退出消息 service.Publish("Twelve", "exit"); service.Publish("Twelve", "123Twelve"); service.Publish("Twelve", "234Twelve"); service.Publish("Twelve", "345Twelve"); service.Publish("Twelve", "456Twelve"); } #endregion
-----------------------------------------------------------------------------------------------------------------
下面額代碼類均是經過 StackExchange.Redis 來對Redis進行各類操做
Redis操做方法基礎類
/// <summary> /// Redis操做方法基礎類 /// </summary> public abstract class RedisBase : IDisposable { #region 屬性字段 /// <summary> /// 網站Redis 系統自定義Key前綴 /// </summary> protected string CustomKey = RedisManager.RedisSysCustomKey; /// <summary> /// 網站Redis 連接字符串 /// </summary> protected readonly ConnectionMultiplexer _conn; /// <summary> /// Redis操做對象 /// </summary> protected readonly IDatabase redis = null; #endregion #region 構造函數 /// <summary> /// 初始化Redis操做方法基礎類 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> protected RedisBase(int? dbNum = null) { _conn = RedisManager.Instance; if (_conn != null) { redis = _conn.GetDatabase(dbNum ?? RedisManager.RedisDataBaseIndex); } else { throw new ArgumentNullException("Redis鏈接初始化失敗"); } } private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!this._disposed) { if (disposing) { _conn.Dispose(); } } this._disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion 構造函數 #region 外部調用靜態方法 /// <summary> /// 獲取Redis的String數據類型操做輔助方法類 /// </summary> /// <returns></returns> public static RedisStringService StringService => new RedisStringService(); /// <summary> /// 獲取Redis的Hash數據類型操做輔助方法類 /// </summary> /// <returns></returns> public static RedisHashService HashService => new RedisHashService(); /// <summary> /// 獲取Redis的List數據類型操做輔助方法類 /// </summary> /// <returns></returns> public static RedisListService ListService => new RedisListService(); /// <summary> /// 獲取Redis的Set無序集合數據類型操做輔助方法類 /// </summary> /// <returns></returns> public static RedisSetService SetService => new RedisSetService(); /// <summary> /// 獲取Redis的SortedSet(ZSet)有序集合數據類型操做輔助方法類 /// </summary> /// <returns></returns> public static RedisSortedSetService SortedSetService => new RedisSortedSetService(); #endregion #region 公共操做方法 #region 不建議公開這些方法,若是項目中用不到,建議註釋或者刪除 /// <summary> /// 獲取Redis事務對象 /// </summary> /// <returns></returns> public ITransaction CreateTransaction() => redis.CreateTransaction(); /// <summary> /// 獲取Redis服務和經常使用操做對象 /// </summary> /// <returns></returns> public IDatabase GetDatabase() => redis; /// <summary> /// 獲取Redis服務 /// </summary> /// <param name="hostAndPort"></param> /// <returns></returns> public IServer GetServer(string hostAndPort) => _conn.GetServer(hostAndPort); /// <summary> /// 執行Redis事務 /// </summary> /// <param name="act"></param> /// <returns></returns> public bool RedisTransaction(Action<ITransaction> act) { var tran = redis.CreateTransaction(); act.Invoke(tran); bool committed = tran.Execute(); return committed; } /// <summary> /// Redis鎖 /// </summary> /// <param name="act"></param> /// <param name="ts">鎖住時間</param> public void RedisLockTake(Action act, TimeSpan ts) { RedisValue token = Environment.MachineName; string lockKey = "lock_LockTake"; if (redis.LockTake(lockKey, token, ts)) { try { act(); } finally { redis.LockRelease(lockKey, token); } } } #endregion 其餘 #region 經常使用Key操做 /// <summary> /// 設置前綴 /// </summary> /// <param name="customKey"></param> public void SetSysCustomKey(string customKey) => CustomKey = customKey; /// <summary> /// 組合緩存Key名稱 /// </summary> /// <param name="oldKey"></param> /// <returns></returns> public string AddSysCustomKey(string oldKey) => $"{CustomKey}_{oldKey}"; #region 同步方法 /// <summary> /// 刪除單個key /// </summary> /// <param name="key">要刪除的key</param> /// <returns>是否刪除成功</returns> public bool KeyDelete(string key) { key = AddSysCustomKey(key); return redis.KeyDelete(key); } /// <summary> /// 刪除多個key /// </summary> /// <param name="keys">要刪除的key集合</param> /// <returns>成功刪除的個數</returns> public long KeyDelete(params string[] keys) { RedisKey[] newKeys = keys.Select(o => (RedisKey)AddSysCustomKey(o)).ToArray(); return redis.KeyDelete(newKeys); } /// <summary> /// 清空當前DataBase中全部Key /// </summary> public void KeyFulsh() { //直接執行清除命令 redis.Execute("FLUSHDB"); } /// <summary> /// 判斷key是否存在 /// </summary> /// <param name="key">要判斷的key</param> /// <returns></returns> public bool KeyExists(string key) { key = AddSysCustomKey(key); return redis.KeyExists(key); } /// <summary> /// 從新命名key /// </summary> /// <param name="key">就的redis key</param> /// <param name="newKey">新的redis key</param> /// <returns></returns> public bool KeyRename(string key, string newKey) { key = AddSysCustomKey(key); newKey = AddSysCustomKey(newKey); return redis.KeyRename(key, newKey); } /// <summary> /// 設置Key的過時時間 /// </summary> /// <param name="key">redis key</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public bool KeyExpire(string key, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); return redis.KeyExpire(key, expiry); } #endregion #region 異步方法 /// <summary> /// 刪除單個key /// </summary> /// <param name="key">要刪除的key</param> /// <returns>是否刪除成功</returns> public async Task<bool> KeyDeleteAsync(string key) { key = AddSysCustomKey(key); return await redis.KeyDeleteAsync(key); } /// <summary> /// 刪除多個key /// </summary> /// <param name="keys">要刪除的key集合</param> /// <returns>成功刪除的個數</returns> public async Task<long> KeyDeleteAsync(params string[] keys) { RedisKey[] newKeys = keys.Select(o => (RedisKey)AddSysCustomKey(o)).ToArray(); return await redis.KeyDeleteAsync(newKeys); } /// <summary> /// 清空當前DataBase中全部Key /// </summary> public async Task KeyFulshAsync() { //直接執行清除命令 await redis.ExecuteAsync("FLUSHDB"); } /// <summary> /// 判斷key是否存在 /// </summary> /// <param name="key">要判斷的key</param> /// <returns></returns> public async Task<bool> KeyExistsAsync(string key) { key = AddSysCustomKey(key); return await redis.KeyExistsAsync(key); } /// <summary> /// 從新命名key /// </summary> /// <param name="key">就的redis key</param> /// <param name="newKey">新的redis key</param> /// <returns></returns> public async Task<bool> KeyRenameAsync(string key, string newKey) { key = AddSysCustomKey(key); newKey = AddSysCustomKey(newKey); return await redis.KeyRenameAsync(key, newKey); } /// <summary> /// 設置Key的過時時間 /// </summary> /// <param name="key">redis key</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public async Task<bool> KeyExpireAsync(string key, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); return await redis.KeyExpireAsync(key, expiry); } #endregion #endregion #endregion #region 輔助方法 /// <summary> /// 將對象轉換成string字符串 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <returns></returns> protected string ConvertJson<T>(T value) { string result = value is string ? value.ToString() : JsonConvert.SerializeObject(value, Formatting.None); return result; } /// <summary> /// 將值反系列化成對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="value"></param> /// <returns></returns> protected T ConvertObj<T>(RedisValue value) { return value.IsNullOrEmpty ? default(T) : JsonConvert.DeserializeObject<T>(value); } /// <summary> /// 將值反系列化成對象集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="values"></param> /// <returns></returns> protected List<T> ConvetList<T>(RedisValue[] values) { List<T> result = new List<T>(); foreach (var item in values) { var model = ConvertObj<T>(item); result.Add(model); } return result; } /// <summary> /// 將string類型的Key轉換成 <see cref="RedisKey"/> 型的Key /// </summary> /// <param name="redisKeys"></param> /// <returns></returns> protected RedisKey[] ConvertRedisKeys(List<string> redisKeys) => redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray(); /// <summary> /// 將string類型的Key轉換成 <see cref="RedisKey"/> 型的Key /// </summary> /// <param name="redisKeys"></param> /// <returns></returns> protected RedisKey[] ConvertRedisKeys(params string[] redisKeys) => redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray(); /// <summary> /// 將string類型的Key轉換成 <see cref="RedisKey"/> 型的Key,並添加前綴字符串 /// </summary> /// <param name="redisKeys"></param> /// <returns></returns> protected RedisKey[] ConvertRedisKeysAddSysCustomKey(params string[] redisKeys) => redisKeys.Select(redisKey => (RedisKey)AddSysCustomKey(redisKey)).ToArray(); /// <summary> /// 將值集合轉換成RedisValue集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="redisValues"></param> /// <returns></returns> protected RedisValue[] ConvertRedisValue<T>(params T[] redisValues) => redisValues.Select(o => (RedisValue)ConvertJson<T>(o)).ToArray(); #endregion 輔助方法 }
Redis基本信息初始化輔助類
/// <summary> /// Redis基本信息初始化輔助類 /// </summary> internal class RedisManager { //private static LogHelper log = LogHelper.LogInterface<RedisManager>(); private static readonly object Locker = new object(); private static ConnectionMultiplexer _instance; private static readonly ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string, ConnectionMultiplexer>(); /// <summary> /// Redis保存的Key前綴,會自動添加到指定的Key名稱前 /// </summary> internal static readonly string RedisSysCustomKey = ConfigurationManager.AppSettings["RedisSysCustomKey"]; /// <summary> /// 當前鏈接的Redis中的DataBase索引,默認0-16,能夠在service.conf配置,最高64 /// </summary> internal static readonly int RedisDataBaseIndex = int.Parse(ConfigurationManager.AppSettings["RedisDataBaseIndex"]); /// <summary> /// 當前鏈接的Redis中鏈接字符串,格式爲:127.0.0.1:6379,allowadmin=true,passowrd=pwd /// </summary> internal static readonly string RedisHostConnection = ConfigurationManager.AppSettings["RedisHostConnection"]; /// <summary> /// 單例獲取 /// </summary> public static ConnectionMultiplexer Instance { get { if (_instance == null) { lock (Locker) { if (_instance == null || !_instance.IsConnected) { _instance = GetManager(); } } } return _instance; } } /// <summary> /// 緩存獲取 /// </summary> /// <param name="connectionString"></param> /// <returns></returns> public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString) { if (!ConnectionCache.ContainsKey(connectionString)) { ConnectionCache[connectionString] = GetManager(connectionString); } return ConnectionCache[connectionString]; } /// <summary> /// 內部方法,獲取Redis鏈接 /// </summary> /// <param name="connectionString"></param> /// <returns></returns> private static ConnectionMultiplexer GetManager(string connectionString = null) { connectionString = connectionString ?? RedisHostConnection; var connect = ConnectionMultiplexer.Connect(connectionString); //註冊以下事件 connect.ConnectionFailed += MuxerConnectionFailed; connect.ConnectionRestored += MuxerConnectionRestored; connect.ErrorMessage += MuxerErrorMessage; connect.ConfigurationChanged += MuxerConfigurationChanged; connect.HashSlotMoved += MuxerHashSlotMoved; connect.InternalError += MuxerInternalError; return connect; } #region 事件 /// <summary> /// 配置更改時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e) { //log.InfoAsync($"Configuration changed: {e.EndPoint}"); } /// <summary> /// 發生錯誤時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e) { //log.InfoAsync($"ErrorMessage: {e.Message}"); } /// <summary> /// 從新創建鏈接以前的錯誤 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e) { //log.InfoAsync($"ConnectionRestored: {e.EndPoint}"); } /// <summary> /// 鏈接失敗 , 若是從新鏈接成功你將不會收到這個通知 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e) { //log.InfoAsync($"從新鏈接:Endpoint failed: {e.EndPoint}, {e.FailureType} , {(e.Exception == null ? "" : e.Exception.Message)}"); } /// <summary> /// 更改集羣 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e) { //log.InfoAsync($"HashSlotMoved:NewEndPoint{e.NewEndPoint}, OldEndPoint{e.OldEndPoint}"); } /// <summary> /// redis類庫錯誤 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerInternalError(object sender, InternalErrorEventArgs e) { //log.InfoAsync($"InternalError:Message{ e.Exception.Message}"); } #endregion 事件 }
redis 的string類型操做類
/// <summary> /// key-value 鍵值對:value能夠是序列化的數據 /// </summary> public class RedisStringService : RedisBase { #region 構造函數 /// <summary> /// 初始化Redis的String數據結構操做 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> public RedisStringService(int? dbNum = null) : base(dbNum) { } #endregion #region 同步方法 /// <summary> /// 添加單個key value /// </summary> /// <param name="key">Redis Key</param> /// <param name="value">保存的值</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public bool StringSet(string key, string value, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); return base.redis.StringSet(key, value, expiry); } /// <summary> /// 添加多個key/value /// </summary> /// <param name="valueList">key/value集合</param> /// <returns></returns> public bool StringSet(Dictionary<string, string> valueList) { var newkeyValues = valueList.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToArray(); return base.redis.StringSet(newkeyValues); } /// <summary> /// 保存一個對象 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="key">保存的Key名稱</param> /// <param name="value">對象實體</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public bool StringSet<T>(string key, T value, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); string jsonValue = ConvertJson(value); return base.redis.StringSet(key, jsonValue, expiry); } /// <summary> /// 在原有key的value值以後追加value /// </summary> /// <param name="key">追加的Key名稱</param> /// <param name="value">追加的值</param> /// <returns></returns> public long StringAppend(string key, string value) { key = AddSysCustomKey(key); return base.redis.StringAppend(key, value); } /// <summary> /// 獲取單個key的值 /// </summary> /// <param name="key">要讀取的Key名稱</param> /// <returns></returns> public string StringGet(string key) { key = AddSysCustomKey(key); return base.redis.StringGet(key); } /// <summary> /// 獲取多個key的value值 /// </summary> /// <param name="keys">要獲取值的Key集合</param> /// <returns></returns> public List<string> StringGet(params string[] keys) { var newKeys = ConvertRedisKeysAddSysCustomKey(keys); var values = base.redis.StringGet(newKeys); return values.Select(o => o.ToString()).ToList(); } /// <summary> /// 獲取單個key的value值 /// </summary> /// <typeparam name="T">返回數據類型</typeparam> /// <param name="key">要獲取值的Key集合</param> /// <returns></returns> public T StringGet<T>(string key) { key = AddSysCustomKey(key); var values = base.redis.StringGet(key); return ConvertObj<T>(values); } /// <summary> /// 獲取多個key的value值 /// </summary> /// <typeparam name="T">返回數據類型</typeparam> /// <param name="keys">要獲取值的Key集合</param> /// <returns></returns> public List<T> StringGet<T>(params string[] keys) { var newKeys = ConvertRedisKeysAddSysCustomKey(keys); var values = base.redis.StringGet(newKeys); return ConvetList<T>(values); } /// <summary> /// 獲取舊值賦上新值 /// </summary> /// <param name="key">Key名稱</param> /// <param name="value">新值</param> /// <returns></returns> public string StringGetSet(string key, string value) { key = AddSysCustomKey(key); return base.redis.StringGetSet(key, value); } /// <summary> /// 獲取舊值賦上新值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">新值</param> /// <returns></returns> public T StringGetSet<T>(string key, T value) { key = AddSysCustomKey(key); string jsonValue = ConvertJson(value); var oValue = base.redis.StringGetSet(key, jsonValue); return ConvertObj<T>(oValue); } /// <summary> /// 獲取值的長度 /// </summary> /// <param name="key">Key名稱</param> /// <returns></returns> public long StringGetLength(string key) { key = AddSysCustomKey(key); return base.redis.StringLength(key); } /// <summary> /// 數字增加val,返回自增後的值 /// </summary> /// <param name="key"></param> /// <param name="val">能夠爲負</param> /// <returns>增加後的值</returns> public double StringIncrement(string key, double val = 1) { key = AddSysCustomKey(key); return base.redis.StringIncrement(key, val); } /// <summary> /// 數字減小val,返回自減小的值 /// </summary> /// <param name="key"></param> /// <param name="val">能夠爲負</param> /// <returns>減小後的值</returns> public double StringDecrement(string key, double val = 1) { key = AddSysCustomKey(key); return base.redis.StringDecrement(key, val); } #endregion #region 異步方法 /// <summary> /// 異步方法 保存單個key value /// </summary> /// <param name="key">Redis Key</param> /// <param name="value">保存的值</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); return await base.redis.StringSetAsync(key, value, expiry); } /// <summary> /// 異步方法 添加多個key/value /// </summary> /// <param name="valueList">key/value集合</param> /// <returns></returns> public async Task<bool> StringSetAsync(Dictionary<string, string> valueList) { var newkeyValues = valueList.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToArray(); return await base.redis.StringSetAsync(newkeyValues); } /// <summary> /// 異步方法 保存一個對象 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="key">保存的Key名稱</param> /// <param name="obj">對象實體</param> /// <param name="expiry">過時時間</param> /// <returns></returns> public async Task<bool> StringSetAsync<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?)) { key = AddSysCustomKey(key); string jsonValue = ConvertJson(obj); return await base.redis.StringSetAsync(key, jsonValue, expiry); } /// <summary> /// 異步方法 在原有key的value值以後追加value /// </summary> /// <param name="key">追加的Key名稱</param> /// <param name="value">追加的值</param> /// <returns></returns> public async Task<long> StringAppendAsync(string key, string value) { key = AddSysCustomKey(key); return await base.redis.StringAppendAsync(key, value); } /// <summary> /// 異步方法 獲取單個key的值 /// </summary> /// <param name="key">要讀取的Key名稱</param> /// <returns></returns> public async Task<string> StringGetAsync(string key) { key = AddSysCustomKey(key); return await base.redis.StringGetAsync(key); } /// <summary> /// 異步方法 獲取多個key的value值 /// </summary> /// <param name="keys">要獲取值的Key集合</param> /// <returns></returns> public async Task<List<string>> StringGetAsync(params string[] keys) { var newKeys = ConvertRedisKeysAddSysCustomKey(keys); var values = await base.redis.StringGetAsync(newKeys); return values.Select(o => o.ToString()).ToList(); } /// <summary> /// 異步方法 獲取單個key的value值 /// </summary> /// <typeparam name="T">返回數據類型</typeparam> /// <param name="key">要獲取值的Key集合</param> /// <returns></returns> public async Task<T> StringGetAsync<T>(string key) { key = AddSysCustomKey(key); var values = await base.redis.StringGetAsync(key); return ConvertObj<T>(values); } /// <summary> /// 異步方法 獲取多個key的value值 /// </summary> /// <typeparam name="T">返回數據類型</typeparam> /// <param name="keys">要獲取值的Key集合</param> /// <returns></returns> public async Task<List<T>> StringGetAsync<T>(params string[] keys) { var newKeys = ConvertRedisKeysAddSysCustomKey(keys); var values = await base.redis.StringGetAsync(newKeys); return ConvetList<T>(values); } /// <summary> /// 異步方法 獲取舊值賦上新值 /// </summary> /// <param name="key">Key名稱</param> /// <param name="value">新值</param> /// <returns></returns> public async Task<string> StringGetSetAsync(string key, string value) { key = AddSysCustomKey(key); return await base.redis.StringGetSetAsync(key, value); } /// <summary> /// 異步方法 獲取舊值賦上新值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">新值</param> /// <returns></returns> public async Task<T> StringGetSetAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jsonValue = ConvertJson(value); var oValue = await base.redis.StringGetSetAsync(key, jsonValue); return ConvertObj<T>(oValue); } /// <summary> /// 異步方法 獲取值的長度 /// </summary> /// <param name="key">Key名稱</param> /// <returns></returns> public async Task<long> StringGetLengthAsync(string key) { key = AddSysCustomKey(key); return await base.redis.StringLengthAsync(key); } /// <summary> /// 異步方法 數字增加val,返回自增後的值 /// </summary> /// <param name="key"></param> /// <param name="val">能夠爲負</param> /// <returns>增加後的值</returns> public async Task<double> StringIncrementAsync(string key, double val = 1) { key = AddSysCustomKey(key); return await base.redis.StringIncrementAsync(key, val); } /// <summary> /// 異步方法 數字減小val,返回自減小的值 /// </summary> /// <param name="key"></param> /// <param name="val">能夠爲負</param> /// <returns>減小後的值</returns> public async Task<double> StringDecrementAsync(string key, double val = 1) { key = AddSysCustomKey(key); return await base.redis.StringDecrementAsync(key, val); } #endregion }
使用
Console.WriteLine("*****************************************"); { //key value 都是string 假如是個對象呢?序列化一下 //假如要修改某一個屬性的值 讀--反序列化--修改--序列化 memcached using (RedisStringService service = new RedisStringService()) { service.KeyFulsh(); service.StringSet("RedisStringService_key1", "RedisStringService_value1"); Console.WriteLine(service.StringGet("RedisStringService_key1")); Console.WriteLine(service.StringGetSet("RedisStringService_key1", "RedisStringService_value2")); Console.WriteLine(service.StringGet("RedisStringService_key1")); service.StringAppend("RedisStringService_key1", "Append"); Console.WriteLine(service.StringGet("RedisStringService_key1")); service.StringSet("RedisStringService_key1", "RedisStringService_value", new TimeSpan(0, 0, 0, 5)); Console.WriteLine(service.StringGet("RedisStringService_key1")); Thread.Sleep(5000); Console.WriteLine(service.StringGet("RedisStringService_key1")); } }
redis 的Hash類型操做類
/// <summary> /// Hash:相似dictionary,經過索引快速定位到指定元素的,耗時均等,跟string的區別在於不用反序列化,直接修改某個字段 /// string的話要麼是 001:序列化整個實體 /// 要麼是 001_name: 001_pwd: 多個key-value /// Hash的話,一個hashid-{key:value;key:value;key:value;} /// 能夠一次性查找實體,也能夠單個,還能夠單個修改 /// </summary> public class RedisHashService : RedisBase { #region 構造函數 /// <summary> /// 初始化Redis的Hash數據結構操做 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> public RedisHashService(int? dbNum = null) : base(dbNum) { } #endregion #region 同步方法 /// <summary> /// 判斷某個數據是否已經被緩存 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public bool HashExists(string key, string dataKey) { key = AddSysCustomKey(key); return base.redis.HashExists(key, dataKey); } /// <summary> /// 存儲數據到hash表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="t"></param> /// <returns></returns> public bool HashSet<T>(string key, string dataKey, T t) { key = AddSysCustomKey(key); string json = ConvertJson(t); return base.redis.HashSet(key, dataKey, json); } /// <summary> /// 移除hash中的某值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public bool HashDelete(string key, string dataKey) { key = AddSysCustomKey(key); return base.redis.HashDelete(key, dataKey); } /// <summary> /// 移除hash中的多個值 /// </summary> /// <param name="key"></param> /// <param name="dataKeys"></param> /// <returns></returns> public long HashDelete(string key, params string[] dataKeys) { key = AddSysCustomKey(key); var newValues = dataKeys.Select(o => (RedisValue)o).ToArray(); return base.redis.HashDelete(key, newValues); } /// <summary> /// 從hash表獲取數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public T HashGet<T>(string key, string dataKey) { key = AddSysCustomKey(key); string value = base.redis.HashGet(key, dataKey); return ConvertObj<T>(value); } /// <summary> /// 數字增加val,返回自增後的值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="val">能夠爲負</param> /// <returns>增加後的值</returns> public double HashIncrement(string key, string dataKey, double val = 1) { key = AddSysCustomKey(key); return base.redis.HashIncrement(key, dataKey, val); } /// <summary> /// 數字減小val,返回自減小的值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="val">能夠爲負</param> /// <returns>減小後的值</returns> public double HashDecrement(string key, string dataKey, double val = 1) { key = AddSysCustomKey(key); return base.redis.HashDecrement(key, dataKey, val); } /// <summary> /// 獲取hashkey全部key名稱 /// </summary> /// <param name="key"></param> /// <returns></returns> public string[] HashKeys(string key) { key = AddSysCustomKey(key); RedisValue[] values = base.redis.HashKeys(key); return values.Select(o=>o.ToString()).ToArray(); } /// <summary> /// 獲取hashkey全部key與值,必須保證Key內的全部數據類型一致 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public Dictionary<string, T> HashGetAll<T>(string key) { key = AddSysCustomKey(key); var query = base.redis.HashGetAll(key); Dictionary<string, T> dic = new Dictionary<string, T>(); foreach (var item in query) { dic.Add(item.Name, ConvertObj<T>(item.Value)); } return dic; } #endregion 同步方法 #region 異步方法 /// <summary> /// 異步方法 判斷某個數據是否已經被緩存 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public async Task<bool> HashExistsAsync(string key, string dataKey) { key = AddSysCustomKey(key); return await base.redis.HashExistsAsync(key, dataKey); } /// <summary> /// 異步方法 存儲數據到hash表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="t"></param> /// <returns></returns> public async Task<bool> HashSetAsync<T>(string key, string dataKey, T t) { key = AddSysCustomKey(key); string json = ConvertJson(t); return await base.redis.HashSetAsync(key, dataKey, json); } /// <summary> /// 異步方法 移除hash中的某值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public async Task<bool> HashDeleteAsync(string key, string dataKey) { key = AddSysCustomKey(key); return await base.redis.HashDeleteAsync(key, dataKey); } /// <summary> /// 異步方法 移除hash中的多個值 /// </summary> /// <param name="key"></param> /// <param name="dataKeys"></param> /// <returns></returns> public async Task<long> HashDeleteAsync(string key, params string[] dataKeys) { key = AddSysCustomKey(key); var newValues = dataKeys.Select(o => (RedisValue)o).ToArray(); return await base.redis.HashDeleteAsync(key, newValues); } /// <summary> /// 異步方法 從hash表獲取數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="dataKey"></param> /// <returns></returns> public async Task<T> HashGetAsync<T>(string key, string dataKey) { key = AddSysCustomKey(key); string value = await base.redis.HashGetAsync(key, dataKey); return ConvertObj<T>(value); } /// <summary> /// 異步方法 數字增加val,返回自增後的值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="val">能夠爲負</param> /// <returns>增加後的值</returns> public async Task<double> HashIncrementAsync(string key, string dataKey, double val = 1) { key = AddSysCustomKey(key); return await base.redis.HashIncrementAsync(key, dataKey, val); } /// <summary> /// 異步方法 數字減小val,返回自減小的值 /// </summary> /// <param name="key"></param> /// <param name="dataKey"></param> /// <param name="val">能夠爲負</param> /// <returns>減小後的值</returns> public async Task<double> HashDecrementAsync(string key, string dataKey, double val = 1) { key = AddSysCustomKey(key); return await base.redis.HashDecrementAsync(key, dataKey, val); } /// <summary> /// 異步方法 獲取hashkey全部key名稱 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<string[]> HashKeysAsync(string key) { key = AddSysCustomKey(key); RedisValue[] values = await base.redis.HashKeysAsync(key); return values.Select(o => o.ToString()).ToArray(); } /// <summary> /// 獲取hashkey全部key與值,必須保證Key內的全部數據類型一致 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<Dictionary<string, T>> HashGetAllAsync<T>(string key) { key = AddSysCustomKey(key); var query = await base.redis.HashGetAllAsync(key); Dictionary<string, T> dic = new Dictionary<string, T>(); foreach (var item in query) { dic.Add(item.Name, ConvertObj<T>(item.Value)); } return dic; } #endregion 異步方法 }
redis 的Set類型操做類
/// <summary> /// Set:用哈希表來保持字符串的惟一性,沒有前後順序,存儲一些集合性的數據 /// 1.共同好友、二度好友 /// 2.利用惟一性,能夠統計訪問網站的全部獨立 IP /// </summary> public class RedisSetService : RedisBase { #region 構造函數 /// <summary> /// 初始化Redis的Set無序數據結構操做 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> public RedisSetService(int? dbNum = null) : base(dbNum) { } #endregion #region 同步方法 /// <summary> /// 在Key集合中添加一個value值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">值</param> /// <returns></returns> public bool SetAdd<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return base.redis.SetAdd(key, jValue); } /// <summary> /// 在Key集合中添加多個value值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">值列表</param> /// <returns></returns> public long SetAdd<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return base.redis.SetAdd(key, valueList); } /// <summary> /// 獲取key集合值的數量 /// </summary> /// <param name="key"></param> /// <returns></returns> public long SetLength(string key) { key = AddSysCustomKey(key); return base.redis.SetLength(key); } /// <summary> /// 判斷Key集合中是否包含指定的值 /// </summary> /// <typeparam name="T">值類型</typeparam> /// <param name="key"></param> /// <param name="value">要判斷是值</param> /// <returns></returns> public bool SetContains<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return base.redis.SetContains(key, jValue); } /// <summary> /// 隨機獲取key集合中的一個值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key"></param> /// <returns></returns> public T SetRandomMember<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.SetRandomMember(key); return ConvertObj<T>(rValue); } /// <summary> /// 獲取key全部值的集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public List<T> SetMembers<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.SetMembers(key); return ConvetList<T>(rValue); } /// <summary> /// 刪除key集合中指定的value /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long SetRemove<T>(string key, params T[] value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value); return base.redis.SetRemove(key, valueList); } /// <summary> /// 隨機刪除key集合中的一個值,並返回該值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T SetPop<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.SetPop(key); return ConvertObj<T>(rValue); } /// <summary> /// 獲取幾個集合的並集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public List<T> SetCombineUnion<T>(params string[] keys) { return _SetCombine<T>(SetOperation.Union, keys); } /// <summary> /// 獲取幾個集合的交集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public List<T> SetCombineIntersect<T>(params string[] keys) { return _SetCombine<T>(SetOperation.Intersect, keys); } /// <summary> /// 獲取幾個集合的差集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public List<T> SetCombineDifference<T>(params string[] keys) { return _SetCombine<T>(SetOperation.Difference, keys); } /// <summary> /// 獲取幾個集合的並集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public long SetCombineUnionAndStore(string destination, params string[] keys) { return _SetCombineAndStore(SetOperation.Union, destination, keys); } /// <summary> /// 獲取幾個集合的交集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public long SetCombineIntersectAndStore(string destination, params string[] keys) { return _SetCombineAndStore(SetOperation.Intersect, destination, keys); } /// <summary> /// 獲取幾個集合的差集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public long SetCombineDifferenceAndStore(string destination, params string[] keys) { return _SetCombineAndStore(SetOperation.Difference, destination, keys); } #endregion #region 異步方法 /// <summary> /// 在Key集合中添加一個value值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">值</param> /// <returns></returns> public async Task<bool> SetAddAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return await base.redis.SetAddAsync(key, jValue); } /// <summary> /// 在Key集合中添加多個value值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key">Key名稱</param> /// <param name="value">值列表</param> /// <returns></returns> public async Task<long> SetAddAsync<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return await base.redis.SetAddAsync(key, valueList); } /// <summary> /// 獲取key集合值的數量 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<long> SetLengthAsync(string key) { key = AddSysCustomKey(key); return await base.redis.SetLengthAsync(key); } /// <summary> /// 判斷Key集合中是否包含指定的值 /// </summary> /// <typeparam name="T">值類型</typeparam> /// <param name="key"></param> /// <param name="value">要判斷是值</param> /// <returns></returns> public async Task<bool> SetContainsAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return await base.redis.SetContainsAsync(key, jValue); } /// <summary> /// 隨機獲取key集合中的一個值 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<T> SetRandomMemberAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.SetRandomMemberAsync(key); return ConvertObj<T>(rValue); } /// <summary> /// 獲取key全部值的集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<List<T>> SetMembersAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.SetMembersAsync(key); return ConvetList<T>(rValue); } /// <summary> /// 刪除key集合中指定的value /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> SetRemoveAsync<T>(string key, params T[] value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value); return await base.redis.SetRemoveAsync(key, valueList); } /// <summary> /// 隨機刪除key集合中的一個值,並返回該值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<T> SetPopAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.SetPopAsync(key); return ConvertObj<T>(rValue); } /// <summary> /// 獲取幾個集合的並集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<List<T>> SetCombineUnionAsync<T>(params string[] keys) { return await _SetCombineAsync<T>(SetOperation.Union, keys); } /// <summary> /// 獲取幾個集合的交集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<List<T>> SetCombineIntersectAsync<T>(params string[] keys) { return await _SetCombineAsync<T>(SetOperation.Intersect, keys); } /// <summary> /// 獲取幾個集合的差集 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<List<T>> SetCombineDifferenceAsync<T>(params string[] keys) { return await _SetCombineAsync<T>(SetOperation.Difference, keys); } /// <summary> /// 獲取幾個集合的並集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<long> SetCombineUnionAndStoreAsync(string destination, params string[] keys) { return await _SetCombineAndStoreAsync(SetOperation.Union, destination, keys); } /// <summary> /// 獲取幾個集合的交集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<long> SetCombineIntersectAndStoreAsync(string destination, params string[] keys) { return await _SetCombineAndStoreAsync(SetOperation.Intersect, destination, keys); } /// <summary> /// 獲取幾個集合的差集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<long> SetCombineDifferenceAndStoreAsync(string destination, params string[] keys) { return await _SetCombineAndStoreAsync(SetOperation.Difference, destination, keys); } #endregion #region 內部輔助方法 /// <summary> /// 獲取幾個集合的交叉並集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private List<T> _SetCombine<T>(SetOperation operation, params string[] keys) { RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); var rValue = base.redis.SetCombine(operation, keyList); return ConvetList<T>(rValue); } /// <summary> /// 獲取幾個集合的交叉並集合,並保存到一個新Key中 /// </summary> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private long _SetCombineAndStore(SetOperation operation, string destination, params string[] keys) { destination = AddSysCustomKey(destination); RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); return base.redis.SetCombineAndStore(operation, destination, keyList); } /// <summary> /// 獲取幾個集合的交叉並集合 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private async Task<List<T>> _SetCombineAsync<T>(SetOperation operation, params string[] keys) { RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); var rValue = await base.redis.SetCombineAsync(operation, keyList); return ConvetList<T>(rValue); } /// <summary> /// 獲取幾個集合的交叉並集合,並保存到一個新Key中 /// </summary> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private async Task<long> _SetCombineAndStoreAsync(SetOperation operation, string destination, params string[] keys) { destination = AddSysCustomKey(destination); RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); return await base.redis.SetCombineAndStoreAsync(operation, destination, keyList); } #endregion }
redis 的zset類型操做類
/// <summary> /// Sorted Sets是將 Set 中的元素增長了一個權重參數 score,使得集合中的元素可以按 score 進行有序排列 /// 1.帶有權重的元素,好比一個遊戲的用戶得分排行榜 /// 2.比較複雜的數據結構,通常用到的場景不算太多 /// </summary> public class RedisSortedSetService : RedisBase { #region 構造函數 /// <summary> /// 初始化Redis的SortedSet有序數據結構操做 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> public RedisSortedSetService(int? dbNum = null) : base(dbNum) { } #endregion #region 同步方法 /// <summary> /// 添加一個值到Key /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="score">排序分數,爲空將獲取集合中最大score加1</param> /// <returns></returns> public bool SortedSetAdd<T>(string key, T value, double? score = null) { key = AddSysCustomKey(key); double scoreNum = score ?? _GetScore(key); return base.redis.SortedSetAdd(key, ConvertJson<T>(value), scoreNum); } /// <summary> /// 添加一個集合到Key /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="score">排序分數,爲空將獲取集合中最大score加1</param> /// <returns></returns> public long SortedSetAdd<T>(string key, List<T> value, double? score = null) { key = AddSysCustomKey(key); double scoreNum = score ?? _GetScore(key); SortedSetEntry[] rValue = value.Select(o => new SortedSetEntry(ConvertJson<T>(o), scoreNum++)).ToArray(); return base.redis.SortedSetAdd(key, rValue); } /// <summary> /// 獲取集合中的數量 /// </summary> /// <param name="key"></param> /// <returns></returns> public long SortedSetLength(string key) { key = AddSysCustomKey(key); return redis.SortedSetLength(key); } /// <summary> /// 獲取指定起始值到結束值的集合數量 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public long SortedSetLengthByValue<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); return redis.SortedSetLengthByValue(key, sValue, eValue); } /// <summary> /// 獲取指定Key的排序Score值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public double? SortedSetScore<T>(string key, T value) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return redis.SortedSetScore(key, rValue); } /// <summary> /// 獲取指定Key中最小Score值 /// </summary> /// <param name="key"></param> /// <returns></returns> public double SortedSetMinScore(string key) { key = AddSysCustomKey(key); double dValue = 0; var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0, 0, Order.Ascending).FirstOrDefault(); dValue = rValue != null ? rValue.Score : 0; return dValue; } /// <summary> /// 獲取指定Key中最大Score值 /// </summary> /// <param name="key"></param> /// <returns></returns> public double SortedSetMaxScore(string key) { key = AddSysCustomKey(key); double dValue = 0; var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0, 0, Order.Descending).FirstOrDefault(); dValue = rValue != null ? rValue.Score : 0; return dValue; } /// <summary> /// 刪除Key中指定的值 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public long SortedSetRemove<T>(string key, params T[] value) { key = AddSysCustomKey(key); var rValue = ConvertRedisValue<T>(value); return base.redis.SortedSetRemove(key, rValue); } /// <summary> /// 刪除指定起始值到結束值的數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public long SortedSetRemoveRangeByValue<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); return base.redis.SortedSetRemoveRangeByValue(key, sValue, eValue); } /// <summary> /// 刪除 從 start 開始的 stop 條數據 /// </summary> /// <param name="key"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <returns></returns> public long SortedSetRemoveRangeByRank(string key, long start, long stop) { key = AddSysCustomKey(key); return base.redis.SortedSetRemoveRangeByRank(key, start, stop); } /// <summary> /// 根據排序分數Score,刪除從 start 開始的 stop 條數據 /// </summary> /// <param name="key"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <returns></returns> public long SortedSetRemoveRangeByScore(string key, double start, double stop) { key = AddSysCustomKey(key); return base.redis.SortedSetRemoveRangeByScore(key, start, stop); } /// <summary> /// 獲取從 start 開始的 stop 條數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public List<T> SortedSetRangeByRank<T>(string key, long start = 0, long stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = base.redis.SortedSetRangeByRank(key, start, stop, orderBy); return ConvetList<T>(rValue); } /// <summary> /// 獲取從 start 開始的 stop 條數據包含Score,返回數據格式:Key=值,Value = Score /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public Dictionary<T, double> SortedSetRangeByRankWithScores<T>(string key, long start = 0, long stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = base.redis.SortedSetRangeByRankWithScores(key, start, stop, orderBy); Dictionary<T, double> dicList = new Dictionary<T, double>(); foreach (var item in rValue) { dicList.Add(ConvertObj<T>(item.Element), item.Score); } return dicList; } /// <summary> /// 根據Score排序 獲取從 start 開始的 stop 條數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public List<T> SortedSetRangeByScore<T>(string key, double start = 0, double stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = base.redis.SortedSetRangeByScore(key, start, stop, Exclude.None, orderBy); return ConvetList<T>(rValue); } /// <summary> /// 根據Score排序 獲取從 start 開始的 stop 條數據包含Score,返回數據格式:Key=值,Value = Score /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public Dictionary<T, double> SortedSetRangeByScoreWithScores<T>(string key, double start = 0, double stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = base.redis.SortedSetRangeByScoreWithScores(key, start, stop, Exclude.None, orderBy); Dictionary<T, double> dicList = new Dictionary<T, double>(); foreach (var item in rValue) { dicList.Add(ConvertObj<T>(item.Element), item.Score); } return dicList; } /// <summary> /// 獲取指定起始值到結束值的數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public List<T> SortedSetRangeByValue<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); var rValue = base.redis.SortedSetRangeByValue(key, sValue, eValue); return ConvetList<T>(rValue); } /// <summary> /// 獲取幾個集合的並集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public long SortedSetCombineUnionAndStore(string destination, params string[] keys) { return _SortedSetCombineAndStore(SetOperation.Union, destination, keys); } /// <summary> /// 獲取幾個集合的交集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public long SortedSetCombineIntersectAndStore(string destination, params string[] keys) { return _SortedSetCombineAndStore(SetOperation.Intersect, destination, keys); } //交集彷佛並不支持 ///// <summary> ///// 獲取幾個集合的差集,並保存到一個新Key中 ///// </summary> ///// <param name="destination">保存的新Key名稱</param> ///// <param name="keys">要操做的Key集合</param> ///// <returns></returns> //public long SortedSetCombineDifferenceAndStore(string destination, params string[] keys) //{ // return _SortedSetCombineAndStore(SetOperation.Difference, destination, keys); //} /// <summary> /// 修改指定Key和值的Scores在原值上減去scores,並返回最終Scores /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="scores"></param> /// <returns></returns> public double SortedSetDecrement<T>(string key, T value, double scores) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return redis.SortedSetDecrement(key, rValue, scores); } /// <summary> /// 修改指定Key和值的Scores在原值上增長scores,並返回最終Scores /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="scores"></param> /// <returns></returns> public double SortedSetIncrement<T>(string key, T value, double scores) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return redis.SortedSetIncrement(key, rValue, scores); } #endregion #region 異步方法 /// <summary> /// 添加一個值到Key /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="score">排序分數,爲空將獲取集合中最大score加1</param> /// <returns></returns> public async Task<bool> SortedSetAddAsync<T>(string key, T value, double? score = null) { key = AddSysCustomKey(key); double scoreNum = score ?? _GetScore(key); return await base.redis.SortedSetAddAsync(key, ConvertJson<T>(value), scoreNum); } /// <summary> /// 添加一個集合到Key /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="score">排序分數,爲空將獲取集合中最大score加1</param> /// <returns></returns> public async Task<long> SortedSetAddAsync<T>(string key, List<T> value, double? score = null) { key = AddSysCustomKey(key); double scoreNum = score ?? _GetScore(key); SortedSetEntry[] rValue = value.Select(o => new SortedSetEntry(ConvertJson<T>(o), scoreNum++)).ToArray(); return await base.redis.SortedSetAddAsync(key, rValue); } /// <summary> /// 獲取集合中的數量 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<long> SortedSetLengthAsync(string key) { key = AddSysCustomKey(key); return await redis.SortedSetLengthAsync(key); } /// <summary> /// 獲取指定起始值到結束值的集合數量 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public async Task<long> SortedSetLengthByValueAsync<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); return await redis.SortedSetLengthByValueAsync(key, sValue, eValue); } /// <summary> /// 獲取指定Key的排序Score值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<double?> SortedSetScoreAsync<T>(string key, T value) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return await redis.SortedSetScoreAsync(key, rValue); } /// <summary> /// 獲取指定Key中最小Score值 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<double> SortedSetMinScoreAsync(string key) { key = AddSysCustomKey(key); double dValue = 0; var rValue = (await base.redis.SortedSetRangeByRankWithScoresAsync(key, 0, 0, Order.Ascending)).FirstOrDefault(); dValue = rValue != null ? rValue.Score : 0; return dValue; } /// <summary> /// 獲取指定Key中最大Score值 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<double> SortedSetMaxScoreAsync(string key) { key = AddSysCustomKey(key); double dValue = 0; var rValue = (await base.redis.SortedSetRangeByRankWithScoresAsync(key, 0, 0, Order.Descending)).FirstOrDefault(); dValue = rValue != null ? rValue.Score : 0; return dValue; } /// <summary> /// 刪除Key中指定的值 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public async Task<long> SortedSetRemoveAsync<T>(string key, params T[] value) { key = AddSysCustomKey(key); var rValue = ConvertRedisValue<T>(value); return await base.redis.SortedSetRemoveAsync(key, rValue); } /// <summary> /// 刪除指定起始值到結束值的數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public async Task<long> SortedSetRemoveRangeByValueAsync<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); return await base.redis.SortedSetRemoveRangeByValueAsync(key, sValue, eValue); } /// <summary> /// 刪除 從 start 開始的 stop 條數據 /// </summary> /// <param name="key"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <returns></returns> public async Task<long> SortedSetRemoveRangeByRankAsync(string key, long start, long stop) { key = AddSysCustomKey(key); return await base.redis.SortedSetRemoveRangeByRankAsync(key, start, stop); } /// <summary> /// 根據排序分數Score,刪除從 start 開始的 stop 條數據 /// </summary> /// <param name="key"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <returns></returns> public async Task<long> SortedSetRemoveRangeByScoreAsync(string key, double start, double stop) { key = AddSysCustomKey(key); return await base.redis.SortedSetRemoveRangeByScoreAsync(key, start, stop); } /// <summary> /// 獲取從 start 開始的 stop 條數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public async Task<List<T>> SortedSetRangeByRankAsync<T>(string key, long start = 0, long stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = await base.redis.SortedSetRangeByRankAsync(key, start, stop, orderBy); return ConvetList<T>(rValue); } /// <summary> /// 獲取從 start 開始的 stop 條數據包含Score,返回數據格式:Key=值,Value = Score /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public async Task<Dictionary<T, double>> SortedSetRangeByRankWithScoresAsync<T>(string key, long start = 0, long stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = await base.redis.SortedSetRangeByRankWithScoresAsync(key, start, stop, orderBy); Dictionary<T, double> dicList = new Dictionary<T, double>(); foreach (var item in rValue) { dicList.Add(ConvertObj<T>(item.Element), item.Score); } return dicList; } /// <summary> /// 根據Score排序 獲取從 start 開始的 stop 條數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public async Task<List<T>> SortedSetRangeByScoreAsync<T>(string key, double start = 0, double stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = await base.redis.SortedSetRangeByScoreAsync(key, start, stop, Exclude.None, orderBy); return ConvetList<T>(rValue); } /// <summary> /// 根據Score排序 獲取從 start 開始的 stop 條數據包含Score,返回數據格式:Key=值,Value = Score /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="start">起始數</param> /// <param name="stop">-1表示到結束,0爲1條</param> /// <param name="desc">是否按降序排列</param> /// <returns></returns> public async Task<Dictionary<T, double>> SortedSetRangeByScoreWithScoresAsync<T>(string key, double start = 0, double stop = -1, bool desc = false) { key = AddSysCustomKey(key); Order orderBy = desc ? Order.Descending : Order.Ascending; var rValue = await base.redis.SortedSetRangeByScoreWithScoresAsync(key, start, stop, Exclude.None, orderBy); Dictionary<T, double> dicList = new Dictionary<T, double>(); foreach (var item in rValue) { dicList.Add(ConvertObj<T>(item.Element), item.Score); } return dicList; } /// <summary> /// 獲取指定起始值到結束值的數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="startValue">起始值</param> /// <param name="endValue">結束值</param> /// <returns></returns> public async Task<List<T>> SortedSetRangeByValueAsync<T>(string key, T startValue, T endValue) { key = AddSysCustomKey(key); var sValue = ConvertJson<T>(startValue); var eValue = ConvertJson<T>(endValue); var rValue = await base.redis.SortedSetRangeByValueAsync(key, sValue, eValue); return ConvetList<T>(rValue); } /// <summary> /// 獲取幾個集合的並集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<long> SortedSetCombineUnionAndStoreAsync(string destination, params string[] keys) { return await _SortedSetCombineAndStoreAsync(SetOperation.Union, destination, keys); } /// <summary> /// 獲取幾個集合的交集,並保存到一個新Key中 /// </summary> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> public async Task<long> SortedSetCombineIntersectAndStoreAsync(string destination, params string[] keys) { return await _SortedSetCombineAndStoreAsync(SetOperation.Intersect, destination, keys); } ///// <summary> ///// 獲取幾個集合的差集,並保存到一個新Key中 ///// </summary> ///// <param name="destination">保存的新Key名稱</param> ///// <param name="keys">要操做的Key集合</param> ///// <returns></returns> //public async Task<long> SortedSetCombineDifferenceAndStoreAsync(string destination, params string[] keys) //{ // return await _SortedSetCombineAndStoreAsync(SetOperation.Difference, destination, keys); //} /// <summary> /// 修改指定Key和值的Scores在原值上減去scores,並返回最終Scores /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="scores"></param> /// <returns></returns> public async Task<double> SortedSetDecrementAsync<T>(string key, T value, double scores) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return await base.redis.SortedSetDecrementAsync(key, rValue, scores); } /// <summary> /// 修改指定Key和值的Scores在原值上增長scores,並返回最終Scores /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="scores"></param> /// <returns></returns> public async Task<double> SortedSetIncrementAsync<T>(string key, T value, double scores) { key = AddSysCustomKey(key); var rValue = ConvertJson<T>(value); return await base.redis.SortedSetIncrementAsync(key, rValue, scores); } #endregion #region 內部輔助方法 /// <summary> /// 獲取指定Key中最大Score值, /// </summary> /// <param name="key">key名稱,注意要先添加上Key前綴</param> /// <returns></returns> private double _GetScore(string key) { double dValue = 0; var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0, 0, Order.Descending).FirstOrDefault(); dValue = rValue != null ? rValue.Score : 0; return dValue + 1; } /// <summary> /// 獲取幾個集合的交叉並集合,並保存到一個新Key中 /// </summary> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private long _SortedSetCombineAndStore(SetOperation operation, string destination, params string[] keys) { #region 查看源碼,彷佛並不支持Difference //RedisCommand command; //if (operation != SetOperation.Union) //{ // if (operation != SetOperation.Intersect) // { // throw new ArgumentOutOfRangeException("operation"); // } // command = RedisCommand.ZINTERSTORE; //} //else //{ // command = RedisCommand.ZUNIONSTORE; //} #endregion destination = AddSysCustomKey(destination); RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); var rValue = base.redis.SortedSetCombineAndStore(operation, destination, keyList); return rValue; } /// <summary> /// 獲取幾個集合的交叉並集合,並保存到一個新Key中 /// </summary> /// <param name="operation">Union:並集 Intersect:交集 Difference:差集 詳見 <see cref="SetOperation"/></param> /// <param name="destination">保存的新Key名稱</param> /// <param name="keys">要操做的Key集合</param> /// <returns></returns> private async Task<long> _SortedSetCombineAndStoreAsync(SetOperation operation, string destination, params string[] keys) { destination = AddSysCustomKey(destination); RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys); var rValue = await base.redis.SortedSetCombineAndStoreAsync(operation, destination, keyList); return rValue; } #endregion }
redis 的List類型操做類
/// <summary> /// Redis list的實現爲一個雙向鏈表,便可以支持反向查找和遍歷,更方便操做,不過帶來了部分額外的內存開銷, /// Redis內部的不少實現,包括髮送緩衝隊列等也都是用的這個數據結構。 /// 通常是左進右出或者右進左出 /// </summary> public class RedisListService : RedisBase { #region 構造函數 /// <summary> /// 初始化Redis的List數據結構操做 /// </summary> /// <param name="dbNum">操做的數據庫索引0-64(須要在conf文件中配置)</param> public RedisListService(int? dbNum = null) : base(dbNum) { } #endregion #region 同步方法 /// <summary> /// 從左側向list中添加一個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long ListLeftPush<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return base.redis.ListLeftPush(key, jValue); } /// <summary> /// 從左側向list中添加多個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long ListLeftPush<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return base.redis.ListLeftPush(key, valueList); } /// <summary> /// 從右側向list中添加一個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long ListRightPush<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return base.redis.ListRightPush(key, jValue); } /// <summary> /// 從右側向list中添加多個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long ListRightPush<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return base.redis.ListRightPush(key, valueList); } /// <summary> /// 從左側向list中取出一個值並從list中刪除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T ListLeftPop<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.ListLeftPop(key); return base.ConvertObj<T>(rValue); } /// <summary> /// 從右側向list中取出一個值並從list中刪除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T ListRightPop<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.ListRightPop(key); return base.ConvertObj<T>(rValue); } /// <summary> /// 從key的List中右側取出一個值,並從左側添加到destination集合中,且返回該數據對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">要取出數據的List名稱</param> /// <param name="destination">要添加到的List名稱</param> /// <returns></returns> public T ListRightPopLeftPush<T>(string key, string destination) { key = AddSysCustomKey(key); destination = AddSysCustomKey(destination); var rValue = base.redis.ListRightPopLeftPush(key, destination); return base.ConvertObj<T>(rValue); } /// <summary> /// 在key的List指定值pivot以後插入value,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pivot">索引值</param> /// <param name="value">要插入的值</param> /// <returns></returns> public long ListInsertAfter<T>(string key, T pivot, T value) { key = AddSysCustomKey(key); string pValue = ConvertJson(pivot); string jValue = ConvertJson(value); return base.redis.ListInsertAfter(key, pValue, jValue); } /// <summary> /// 在key的List指定值pivot以前插入value,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pivot">索引值</param> /// <param name="value">要插入的值</param> /// <returns></returns> public long ListInsertBefore<T>(string key, T pivot, T value) { key = AddSysCustomKey(key); string pValue = ConvertJson(pivot); string jValue = ConvertJson(value); return base.redis.ListInsertBefore(key, pValue, jValue); } /// <summary> /// 從key的list中取出全部數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public List<T> ListRange<T>(string key) { key = AddSysCustomKey(key); var rValue = base.redis.ListRange(key); return base.ConvetList<T>(rValue); } /// <summary> /// 從key的List獲取指定索引的值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="index"></param> /// <returns></returns> public T ListGetByIndex<T>(string key, long index) { key = AddSysCustomKey(key); var rValue = base.redis.ListGetByIndex(key, index); return base.ConvertObj<T>(rValue); } /// <summary> /// 獲取key的list中數據個數 /// </summary> /// <param name="key"></param> /// <returns></returns> public long ListLength(string key) { key = AddSysCustomKey(key); return base.redis.ListLength(key); } /// <summary> /// 從key的List中移除指定的值,返回刪除個數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long ListRemove<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return base.redis.ListRemove(key, jValue); } #endregion #region 異步方法 /// <summary> /// 從左側向list中添加一個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> ListLeftPushAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return await base.redis.ListLeftPushAsync(key, jValue); } /// <summary> /// 從左側向list中添加多個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> ListLeftPushAsync<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return await base.redis.ListLeftPushAsync(key, valueList); } /// <summary> /// 從右側向list中添加一個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> ListRightPushAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return await base.redis.ListRightPushAsync(key, jValue); } /// <summary> /// 從右側向list中添加多個值,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> ListRightPushAsync<T>(string key, List<T> value) { key = AddSysCustomKey(key); RedisValue[] valueList = base.ConvertRedisValue(value.ToArray()); return await base.redis.ListRightPushAsync(key, valueList); } /// <summary> /// 從左側向list中取出一個值並從list中刪除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<T> ListLeftPopAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.ListLeftPopAsync(key); return base.ConvertObj<T>(rValue); } /// <summary> /// 從右側向list中取出一個值並從list中刪除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<T> ListRightPopAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.ListRightPopAsync(key); return base.ConvertObj<T>(rValue); } /// <summary> /// 從key的List中右側取出一個值,並從左側添加到destination集合中,且返回該數據對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">要取出數據的List名稱</param> /// <param name="destination">要添加到的List名稱</param> /// <returns></returns> public async Task<T> ListRightPopLeftPushAsync<T>(string key, string destination) { key = AddSysCustomKey(key); destination = AddSysCustomKey(destination); var rValue = await base.redis.ListRightPopLeftPushAsync(key, destination); return base.ConvertObj<T>(rValue); } /// <summary> /// 在key的List指定值pivot以後插入value,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pivot">索引值</param> /// <param name="value">要插入的值</param> /// <returns></returns> public async Task<long> ListInsertAfterAsync<T>(string key, T pivot, T value) { key = AddSysCustomKey(key); string pValue = ConvertJson(pivot); string jValue = ConvertJson(value); return await base.redis.ListInsertAfterAsync(key, pValue, jValue); } /// <summary> /// 在key的List指定值pivot以前插入value,返回集合總數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="pivot">索引值</param> /// <param name="value">要插入的值</param> /// <returns></returns> public async Task<long> ListInsertBeforeAsync<T>(string key, T pivot, T value) { key = AddSysCustomKey(key); string pValue = ConvertJson(pivot); string jValue = ConvertJson(value); return await base.redis.ListInsertBeforeAsync(key, pValue, jValue); } /// <summary> /// 從key的list中取出全部數據 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public async Task<List<T>> ListRangeAsync<T>(string key) { key = AddSysCustomKey(key); var rValue = await base.redis.ListRangeAsync(key); return base.ConvetList<T>(rValue); } /// <summary> /// 從key的List獲取指定索引的值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="index"></param> /// <returns></returns> public async Task<T> ListGetByIndexAsync<T>(string key, long index) { key = AddSysCustomKey(key); var rValue = await base.redis.ListGetByIndexAsync(key, index); return base.ConvertObj<T>(rValue); } /// <summary> /// 獲取key的list中數據個數 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<long> ListLengthAsync(string key) { key = AddSysCustomKey(key); return await base.redis.ListLengthAsync(key); } /// <summary> /// 從key的List中移除指定的值,返回刪除個數 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public async Task<long> ListRemoveAsync<T>(string key, T value) { key = AddSysCustomKey(key); string jValue = ConvertJson(value); return await base.redis.ListRemoveAsync(key, jValue); } #endregion }
使用
Console.WriteLine("*****************************************"); { using (RedisListService service = new RedisListService()) { service.KeyFulsh(); List<string> stringList = new List<string>(); for (int i = 0; i < 10; i++) { stringList.Add(string.Format($"放入任務{i}")); } service.ListLeftPush("test", "這是一個學生1"); service.ListLeftPush("test", "這是一個學生2"); service.ListLeftPush("test", "這是一個學生3"); service.ListLeftPush("test", "這是一個學生4"); service.ListLeftPush("test", "這是一個學生5"); service.ListLeftPush("test", "這是一個學生6"); service.ListLeftPush("task", stringList); Console.WriteLine(service.ListLength("test")); Console.WriteLine(service.ListLength("task")); var list = service.ListRange<string>("test"); Action act = new Action(() => { while (true) { Console.WriteLine("************請輸入數據**************"); string testTask = Console.ReadLine(); service.ListLeftPush("test", testTask); } }); act.EndInvoke(act.BeginInvoke(null, null)); } }