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