Redis分散式快取系列(五)- Redis中的ZSet型別
阿新 • • 發佈:2020-11-21
本系列將和大家分享Redis分散式快取,本章主要簡單介紹下Redis中的ZSet型別,以及如何使用Redis解決實時排行榜問題。
Sorted Sets是將 Set 中的元素增加了一個權重引數 score,使得集合中的元素能夠按 score 進行有序排列。
ZSet型別最大的特點就是有序、去重,以及交集、並集的使用。
儲存形式:key--SortList<value>
首先先給大家Show一波Redis中與ZSet型別相關的API:
using System.Collections.Generic; namespace TianYa.Redis.Service { /// <summary> /// Sorted Sets是將 Set 中的元素增加了一個權重引數 score,使得集合中的元素能夠按 score 進行有序排列 /// 1、帶有權重的元素,比如一個遊戲的使用者得分排行榜 /// 2、比較複雜的資料結構,一般用到的場景不算太多 /// </summary> public class RedisZSetService : RedisBase { #region 新增 /// <summary> /// 新增setId/value,預設分數是從1.多*10的9次方以此遞增的,自帶自增效果 /// </summary> public bool AddItemToSortedSet(string setId, string value) { return base._redisClient.AddItemToSortedSet(setId, value); } /// <summary> /// 新增setId/value,並設定value的分數 /// </summary> public bool AddItemToSortedSet(string setId, string value, double score) { return base._redisClient.AddItemToSortedSet(setId, value, score); } /// <summary> /// 為setId新增values集合,values集合中每個value的分數設定為score /// </summary> public bool AddRangeToSortedSet(string setId, List<string> values, double score) { return base._redisClient.AddRangeToSortedSet(setId, values, score); } /// <summary> /// 為setId新增values集合,values集合中每個value的分數設定為score /// </summary> public bool AddRangeToSortedSet(string setId, List<string> values, long score) { return base._redisClient.AddRangeToSortedSet(setId, values, score); } #endregion 新增 #region 獲取 /// <summary> /// 獲取setId的所有集合 /// </summary> public List<string> GetAllItemsFromSortedSet(string setId) { return base._redisClient.GetAllItemsFromSortedSet(setId); } /// <summary> /// 獲取setId的所有集合,倒敘輸出 /// </summary> public List<string> GetAllItemsFromSortedSetDesc(string setId) { return base._redisClient.GetAllItemsFromSortedSetDesc(setId); } /// <summary> /// 獲取集合,帶分數 /// </summary> public IDictionary<string, double> GetAllWithScoresFromSortedSet(string setId) { return base._redisClient.GetAllWithScoresFromSortedSet(setId); } /// <summary> /// 獲取setId集合中值為value的下標值 /// </summary> public long GetItemIndexInSortedSet(string setId, string value) { return base._redisClient.GetItemIndexInSortedSet(setId, value); } /// <summary> /// 倒敘排列獲取setId集合中值為value的下標值 /// </summary> public long GetItemIndexInSortedSetDesc(string setId, string value) { return base._redisClient.GetItemIndexInSortedSetDesc(setId, value); } /// <summary> /// 獲取setId集合中值為value的分數 /// </summary> public double GetItemScoreInSortedSet(string setId, string value) { return base._redisClient.GetItemScoreInSortedSet(setId, value); } /// <summary> /// 獲取setId集合中所有資料的總數 /// </summary> public long GetSortedSetCount(string setId) { return base._redisClient.GetSortedSetCount(setId); } /// <summary> /// setId集合資料從分數為fromScore到分數為toScore的資料總數 /// </summary> public long GetSortedSetCount(string setId, double fromScore, double toScore) { return base._redisClient.GetSortedSetCount(setId, fromScore, toScore); } /// <summary> /// 獲取setId集合從高分到低分排序資料,分數從fromScore到分數為toScore的資料 /// </summary> public List<string> GetRangeFromSortedSetByHighestScore(string setId, double fromScore, double toScore) { return base._redisClient.GetRangeFromSortedSetByHighestScore(setId, fromScore, toScore); } /// <summary> /// 獲取setId集合從低分到高分排序資料,分數從fromScore到分數為toScore的資料 /// </summary> public List<string> GetRangeFromSortedSetByLowestScore(string setId, double fromScore, double toScore) { return base._redisClient.GetRangeFromSortedSetByLowestScore(setId, fromScore, toScore); } /// <summary> /// 獲取setId集合從高分到低分排序資料,分數從fromScore到分數為toScore的資料,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetByHighestScore(string setId, double fromScore, double toScore) { return base._redisClient.GetRangeWithScoresFromSortedSetByHighestScore(setId, fromScore, toScore); } /// <summary> /// 獲取setId集合從低分到高分排序資料,分數從fromScore到分數為toScore的資料,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetByLowestScore(string setId, double fromScore, double toScore) { return base._redisClient.GetRangeWithScoresFromSortedSetByLowestScore(setId, fromScore, toScore); } /// <summary> /// 獲取setId集合資料,下標從fromRank到下標為toRank的資料 /// </summary> public List<string> GetRangeFromSortedSet(string setId, int fromRank, int toRank) { return base._redisClient.GetRangeFromSortedSet(setId, fromRank, toRank); } /// <summary> /// 獲取setId集合倒敘排列資料,下標從fromRank到下標為toRank的資料 /// </summary> public List<string> GetRangeFromSortedSetDesc(string setId, int fromRank, int toRank) { return base._redisClient.GetRangeFromSortedSetDesc(setId, fromRank, toRank); } /// <summary> /// 獲取setId集合資料,下標從fromRank到下標為toRank的資料,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSet(string setId, int fromRank, int toRank) { return base._redisClient.GetRangeWithScoresFromSortedSet(setId, fromRank, toRank); } /// <summary> /// 獲取setId集合倒敘排列資料,下標從fromRank到下標為toRank的資料,帶分數 /// </summary> public IDictionary<string, double> GetRangeWithScoresFromSortedSetDesc(string setId, int fromRank, int toRank) { return base._redisClient.GetRangeWithScoresFromSortedSetDesc(setId, fromRank, toRank); } #endregion 獲取 #region 刪除 /// <summary> /// 刪除setId集合中值為value的資料 /// </summary> public bool RemoveItemFromSortedSet(string setId, string value) { return base._redisClient.RemoveItemFromSortedSet(setId, value); } /// <summary> /// 刪除下標從minRank到maxRank的setId集合資料 /// </summary> public long RemoveRangeFromSortedSet(string setId, int minRank, int maxRank) { return base._redisClient.RemoveRangeFromSortedSet(setId, minRank, maxRank); } /// <summary> /// 刪除分數從fromScore到toScore的setId集合資料 /// </summary> public long RemoveRangeFromSortedSetByScore(string setId, double fromScore, double toScore) { return base._redisClient.RemoveRangeFromSortedSetByScore(setId, fromScore, toScore); } /// <summary> /// 刪除setId集合中分數最大的資料 /// </summary> public string PopItemWithHighestScoreFromSortedSet(string setId) { return base._redisClient.PopItemWithHighestScoreFromSortedSet(setId); } /// <summary> /// 刪除setId集合中分數最小的資料 /// </summary> public string PopItemWithLowestScoreFromSortedSet(string setId) { return base._redisClient.PopItemWithLowestScoreFromSortedSet(setId); } #endregion 刪除 #region 其它 /// <summary> /// 判斷setId集合中是否存在值為value的資料 /// </summary> public bool SortedSetContainsItem(string setId, string value) { return base._redisClient.SortedSetContainsItem(setId, value); } /// <summary> /// 為setId集合值為value的資料,分數加incrementBy,返回相加後的分數 /// </summary> public double IncrementItemInSortedSet(string setId, string value, double incrementBy) { return base._redisClient.IncrementItemInSortedSet(setId, value, incrementBy); } /// <summary> /// 獲取setIds多個集合的交集,並把交集新增到intoSetId集合中,返回交集資料的總數 /// </summary> public long StoreIntersectFromSortedSets(string intoSetId, string[] setIds) { return base._redisClient.StoreIntersectFromSortedSets(intoSetId, setIds); } /// <summary> /// 獲取setIds多個集合的並集,並把並集資料新增到intoSetId集合中,返回並集資料的總數 /// </summary> public long StoreUnionFromSortedSets(string intoSetId, string[] setIds) { return base._redisClient.StoreUnionFromSortedSets(intoSetId, setIds); } #endregion 其它 } }
使用如下:
/// <summary> /// ZSet:有序、去重,以及交集、並集的使用 /// 實時排行榜:例如直播刷禮物 /// </summary> public static void ShowZSet() { using (RedisZSetService service = new RedisZSetService()) { service.FlushAll(); //清理全部資料 //帶預設分數 service.AddItemToSortedSet("advanced", "1"); service.AddItemToSortedSet("advanced", "2"); service.AddItemToSortedSet("advanced", "5"); service.AddItemToSortedSet("advanced", "4"); service.AddItemToSortedSet("advanced", "7"); service.AddItemToSortedSet("advanced", "5"); service.AddItemToSortedSet("advanced", "9"); var result1 = service.GetAllItemsFromSortedSet("advanced"); var result2 = service.GetAllItemsFromSortedSetDesc("advanced"); //自定義分數 service.AddItemToSortedSet("Sort", "張三", 10001); service.AddItemToSortedSet("Sort", "李四", 10002); service.AddItemToSortedSet("Sort", "王五", 10005); service.AddItemToSortedSet("Sort", "趙六", 10003); service.AddItemToSortedSet("Sort", "錢七", 10004); service.AddRangeToSortedSet("Sort", new List<string>() { "老王", "老李", "老孫" }, 11000); var result3 = service.GetAllWithScoresFromSortedSet("Sort"); //交集、並集 } }
執行結果如下所示:
下面我們就來看下如何使用上面的API來解決實時排行榜的問題:
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using TianYa.Redis.Service; namespace MyRedis.Scene { /// <summary> /// 實時排行榜 /// 使用Redis-IncrementItemInSortedSet /// 刷禮物:維度很多,平臺/房間/主播/日/周/月/年 => 排行(資料庫只存刷禮物的流水,不需要存排名什麼的,計算排名交給Redis) /// 多個維度就是多個ZSet,刷禮物的時候儲存資料庫並更新Redis /// 刷禮物時增加Redis分數,就可以實時獲取最新的排行 /// </summary> public class RankManager { /// <summary> /// 模擬直播平臺使用者 /// </summary> private static List<string> _listUser = new List<string>() { "張三","李四","王五","趙六","錢七","周八" }; public static void Show() { using (RedisZSetService service = new RedisZSetService()) { service.FlushAll(); //清理全部資料 //模擬給TianYa刷禮物 Task.Run(() => { while (true) { foreach (var user in _listUser) { Thread.Sleep(100); service.IncrementItemInSortedSet("TianYa", user, new Random().Next(1, 100)); //表示在原來刷禮物的基礎上增加禮物 } Thread.Sleep(10 * 1000); } }); //檢視實時排行榜 Task.Run(() => { while (true) { Thread.Sleep(6 * 1000); Console.WriteLine("*****************當前排行*****************"); int i = 1; foreach (var item in service.GetRangeWithScoresFromSortedSetDesc("TianYa", 0, 9)) //排行前10名 { Console.WriteLine($"第{i++}名 {item.Key} 分數{item.Value}"); } } }); Console.Read(); //不能刪除 } } } }
執行結果如下所示:
至此本文就全部介紹完了,如果覺得對您有所啟發請記得點個贊哦!!!
Demo原始碼:
連結:https://pan.baidu.com/s/1CAqIJ7gupa6gChmu0wh6OA 提取碼:05em
此文由博主精心撰寫轉載請保留此原文連結:https://www.cnblogs.com/xyh9039/p/14008074.html
版權宣告:如有雷同純屬巧合,如有侵權請及時聯絡本人修改,謝謝!!!