redis中zSet實現(xiàn)排行榜的使用示例
一.寫在前面
最近做完直播的基礎(chǔ)功能后,又多了很多相關(guān)的需求,其中有一個就是直播間分享榜單的功能,顧名思義就是:分享本直播間并成功拉用戶進(jìn)來的數(shù)量做一個排行。比如我分享了這個直播間,別人通過我分享的直播間鏈接點進(jìn)來,那么這個人就是我邀請來的,我總共邀請了10個人,你總共邀請了6個人,他總共邀請了11個人。實時排名就是他>我>你。
簡單介紹了一下功能,其實就是個根據(jù)某個權(quán)重值做排行榜的功能。
二.介紹redis的zset
這里就不說具體的zset實現(xiàn)了(我太菜,不敢放肆,等我牛逼了我再寫zset實現(xiàn),估計n年后 ),總之為了速度和穩(wěn)定性以及持久化,redis肯定是最合適的,而且redis又有zSet這種數(shù)據(jù)結(jié)構(gòu),那不用zSet豈不是浪費嘛。
首先簡單說一下zSet:
- Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復(fù)的成員。
- 不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
- 有序集合的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。(這么專業(yè)的話我肯定是說不出來的,當(dāng)然是網(wǎng)上找的啦)
命令 | 描述 |
---|---|
ZADD key score1 member1 [score2 member2] | 向有序集合添加一個或多個成員,或者更新已存在成員的分?jǐn)?shù) |
ZCARD key | 獲取有序集合的成員數(shù) |
ZCOUNT key min max | 計算在有序集合中指定區(qū)間分?jǐn)?shù)的成員數(shù) |
ZINCRBY key increment member | 有序集合中對指定成員的分?jǐn)?shù)加上增量 increment |
ZINTERSTORE destination numkeys key [key …] | 計算給定的一個或多個有序集的交集并將結(jié)果集存儲在新的有序集合 key 中 |
ZLEXCOUNT key min max | 在有序集合中計算指定字典區(qū)間內(nèi)成員數(shù)量 |
ZRANGE key start stop [WITHSCORES] | 通過索引區(qū)間返回有序集合成指定區(qū)間內(nèi)的成員 |
ZRANGEBYLEX key min max [LIMIT offset count] | 通過字典區(qū)間返回有序集合的成員 |
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] | 通過分?jǐn)?shù)返回有序集合指定區(qū)間內(nèi)的成員 |
ZRANK key member | 返回有序集合中指定成員的索引 |
ZREM key member [member …] | 移除有序集合中的一個或多個成員 |
ZREMRANGEBYLEX key min max | 移除有序集合中給定的字典區(qū)間的所有成員 |
ZREMRANGEBYRANK key start stop | 移除有序集合中給定的排名區(qū)間的所有成員 |
ZREMRANGEBYSCORE key min max | 移除有序集合中給定的分?jǐn)?shù)區(qū)間的所有成員 |
ZREVRANGE key start stop [WITHSCORES] | 返回有序集中指定區(qū)間內(nèi)的成員,通過索引,分?jǐn)?shù)從高到底 |
ZREVRANGEBYSCORE key max min [WITHSCORES] | 返回有序集中指定分?jǐn)?shù)區(qū)間內(nèi)的成員,分?jǐn)?shù)從高到低排序 |
ZREVRANK key member | 返回有序集合中指定成員的排名,有序集成員按分?jǐn)?shù)值遞減(從大到小)排序 |
ZSCORE key member | 返回有序集中,成員的分?jǐn)?shù)值 |
ZUNIONSTORE destination numkeys key [key …] | 計算給定的一個或多個有序集的并集,并存儲在新的 key 中 |
ZSCAN key cursor [MATCH pattern] [COUNT count] | 迭代有序集合中的元素(包括元素成員和元素分值) |
上面就是redis的zset相關(guān)的命令,項目中實際是不會這么寫的,我們使用的RedisTemplate進(jìn)行的redis操作
三.實現(xiàn)方式
介紹完zset,然后說一下功能實現(xiàn)思路,其實很簡單。。。。。就是往zset里面塞數(shù)據(jù)
stringRedisTemplate.opsForZSet().incrementScore(key, member, incrementScore);
上面代碼,其實就是reids命令的:ZINCRBY key increment member,描述:有序集合中對指定成員的分?jǐn)?shù)加上增量 increment,比如你要給某個直播間做排行榜,key就是直播間相關(guān)的key,member就是邀請人的標(biāo)識(一般就是userId),incrementScore就是這個人邀請的人數(shù)自增量(這是我的業(yè)務(wù)的說法,具體大家根據(jù)自己需求理解,融會貫通哈,比如微博熱搜排序,key就可以是小時榜/天榜/月榜,member是某一條熱搜詞條,incrementScore就是這個詞條熱度增量/權(quán)重增量) ,我覺得你們肯定理解我為啥直接用incrementScore,而不是add,所以把自增量直接塞進(jìn)去redis-zset就完事了,有人通過邀請進(jìn)來了你就往進(jìn)塞一次,因為這個命令是incrementScore也就是自增類型的,所以你也不用擔(dān)心剛開始的時候是否存在這個key(并發(fā)問題),如果調(diào)用incrementScore的時候這個key已經(jīng)存在,那就score自增,如果不存在那就新增這個key,然后把自增量設(shè)置為初始值,天然的線程安全,redis牛逼?。?!
然后根據(jù)我的業(yè)務(wù)來說,我的incrementScore自增量就是1,因為我邀請了1個人就+1,沒啥特殊值,但比如你的業(yè)務(wù)是直播間但消費額排行,那你的incrementScore自增量就是本次消費的金額數(shù),這點應(yīng)該很好理解,這里只說redis操作哈,如果這些數(shù)據(jù)還要落mysql等數(shù)據(jù)庫,那看情況操作就行,比如我們的業(yè)務(wù)還要判斷同一個人點了兩個邀請鏈接,只算第一個的,并且直播結(jié)束還要拉取分享榜前三名發(fā)獎勵,所以存入redis-zset的時候要校驗,最后還要落庫到mysql,但其實mysql很快的哈,又不是那種上千萬的級別,上千萬那你分庫分表也不就完事了,實在不行你發(fā)一條mq消息處理唄,這種業(yè)務(wù),我覺得保證最終一致就行了。
分享榜數(shù)據(jù)和排行問題,zset全部幫我們解決了,我們只需要給里面填入數(shù)據(jù)就行,簡單、高效、實用。
剩下的就是取數(shù)據(jù)了,取數(shù)據(jù)的話也是從zset取排行的有序集合數(shù)據(jù):
stringRedisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
上面這個代碼,首先reverseRangeWithScores 方法的意思是:從大到小從第start+1名開始取值,到第end+1名結(jié)束,并且返回結(jié)果帶分?jǐn)?shù), 簡單來說就是把得分從大到小排序,然后取前end+1名,這個是RedisTemplate的方法,如果是redis操作的話,那命令就是上面表格中的:ZREVRANGEBYSCORE key max min [WITHSCORES],描述:返回有序集中指定分?jǐn)?shù)區(qū)間內(nèi)的成員,分?jǐn)?shù)從高到低排序,這個描述我感覺有點繞哈,但是仔細(xì)理解一下還是能理解的
舉個例子哈,如果你要取排行榜前十名,那么調(diào)用上面方法的參數(shù)就是:
stringRedisTemplate.opsForZSet().reverseRangeWithScores("key", 0, 9);
這個方法就會返回排行榜前十名,這個方法返回結(jié)果是:Set<ZSetOperations.TypedTuple<String>>,一個Set,具體結(jié)構(gòu)其實大概就是個Set<value,score>,直接循環(huán)這個結(jié)果,就拿到了前十名的結(jié)果??吹竭@里還不了解返回結(jié)果數(shù)據(jù)結(jié)構(gòu)的可以去debug一下看看這個數(shù)據(jù)結(jié)構(gòu),立馬就懂哈。循環(huán)這個結(jié)果拿到的就是排好序的<userId,score>,舒服啊,直接再完善一下數(shù)據(jù),比如查一下用戶名啥的,這個看具體業(yè)務(wù)哈,然后返回結(jié)果完事,簡單、高效、又不擔(dān)心線程安全。
好了!?。懲晔展?,zset實現(xiàn)排行榜真的很不錯。本篇主要寫實現(xiàn)思路,具體代碼不能貼給你們看哈,因為是我們的業(yè)務(wù)代碼,我又懶的自己寫一個,所以只說思路,其實也不難,排序和并發(fā)問題redis都做好了,那還要啥自行車。
到此這篇關(guān)于redis中zSet實現(xiàn)排行榜的使用示例的文章就介紹到這了,更多相關(guān)redis zSet 排行榜內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis Cluster集群收縮主從節(jié)點詳細(xì)教程
集群收縮的源端就是要下線的主節(jié)點,目標(biāo)端就是在線的主節(jié)點,這篇文章主要介紹了Redis Cluster集群收縮主從節(jié)點詳細(xì)教程,需要的朋友可以參考下2021-11-11Redis五大基本數(shù)據(jù)類型及對應(yīng)使用場景總結(jié)
Redis有五種基本數(shù)據(jù)類型,分別是字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted?Set),這些基本數(shù)據(jù)類型使得Redis具備了豐富的數(shù)據(jù)結(jié)構(gòu)和功能,適用于各種不同的應(yīng)用場景,本文就給大家詳細(xì)的介紹一下這五大類型2023-08-08Redis全文搜索教程之創(chuàng)建索引并關(guān)聯(lián)源數(shù)據(jù)的教程
RediSearch提供了一種簡單快速的方法對 hash 或者 json 類型數(shù)據(jù)的任何字段建立二級索引,然后就可以對被索引的 hash 或者 json 類型數(shù)據(jù)字段進(jìn)行搜索和聚合操作,這篇文章主要介紹了Redis全文搜索教程之創(chuàng)建索引并關(guān)聯(lián)源數(shù)據(jù),需要的朋友可以參考下2023-12-12Redis所實現(xiàn)的Reactor模型設(shè)計方案
這篇文章主要介紹了Redis所實現(xiàn)的Reactor模型,本文將帶領(lǐng)讀者從源碼的角度來查看redis關(guān)于reactor模型的設(shè)計,需要的朋友可以參考下2024-06-06