Redis中的zset類型詳解
什么是zset
有序集合zset保留了set集合不能有重復(fù)成員的特點,但與set集合不同的是,zset的每個member都有一個唯一的浮點數(shù)類型的分?jǐn)?shù)score與之關(guān)聯(lián)。依據(jù)每個member的score進(jìn)行排序。結(jié)構(gòu)如下圖所示:
有序集合中的元素是不能重復(fù)的,但分?jǐn)?shù)允許重復(fù)
常用命令
zadd
添加或更新指定元素以及關(guān)聯(lián)的分?jǐn)?shù)到zset中,分?jǐn)?shù)是double類型語法: zadd key [nx|xx] [gt|lt] [ch] [incr] score member [score member...]
- nx:僅用于添加新元素,不能更新已經(jīng)存在的元素
- xx:僅用于更新已經(jīng)存在的元素,不能添加新元素
- gt:greater than 只能更新已經(jīng)存在并且分?jǐn)?shù)比現(xiàn)在的分?jǐn)?shù)高的元素,能正常添加元素
- lt:less than 只能更新已經(jīng)存在并且分?jǐn)?shù)比現(xiàn)在分?jǐn)?shù)低的元素,能正常添加元素
- ch:默認(rèn)情況,zadd返回的是本次添加元素的個數(shù),但指定這個選項后,還會包含本次更新的元素的個數(shù)
- incr:將元素的分?jǐn)?shù)加上指定的分?jǐn)?shù),并且只能指定一個元素和分?jǐn)?shù)
我使用的版本是redis5,在redis5中不支持 gt/lt操作
時間復(fù)雜度:O(logN)
由于zset是有序結(jié)構(gòu),要求新增的元素,要放到合適的位置上即找位置的過程,zset內(nèi)部使用跳表的數(shù)據(jù)結(jié)構(gòu),可以達(dá)到O(logN)
:::dangerzset中的member和score不是鍵值對的關(guān)系,而是“pair”的關(guān)系,可以通過member找到score,也可以通過score找到member:::
zrange
查看zset中元素詳情語法: zrange key start stop
時間復(fù)雜度:O(logN+M)
首先根據(jù)下標(biāo)找到邊界值,找元素O(logN),從start位置開始遍歷到stop位置,O(m)
redis內(nèi)部存儲數(shù)據(jù)是按照二進(jìn)制存儲,所以redis服務(wù)器不負(fù)責(zé)“字符編碼”,因此需要redis客服端支持
添加 withscores
能查看每個元素對應(yīng)分?jǐn)?shù)
zset內(nèi)部默認(rèn)是按照升序的方式來排列的
zrevrange
返回指定區(qū)間元素,分?jǐn)?shù)按降序排列,帶上 withscores
可以將分?jǐn)?shù)加上語法: zrevrange key start stop [withscores]
時間復(fù)雜度:O(logN+M)
zcard
查看一共有幾個元素語法: zcard key
時間復(fù)雜度:O(1)
zcount
根據(jù)給定分?jǐn)?shù)區(qū)間查找有幾個元素語法: zcount key min max
閉區(qū)間時間復(fù)雜度:O(logN)
先根據(jù)min找到對應(yīng)元素,再根據(jù)max找到對應(yīng)元素,而查找元素的時間復(fù)雜度是O(logN),由于zset內(nèi)部記錄每個元素的“次序”,可以直接把max對應(yīng)元素的次序減去min對應(yīng)元素的次序即可,不需要進(jìn)行遍歷。
使用 (
表示開區(qū)間
min和max可以寫成浮點數(shù),浮點數(shù)中inf表示無窮大,-inf表示負(fù)無窮大
zrangebyscore
返回分?jǐn)?shù)在min和max之間的元素語法: zrangebyscore key min max [withscores]
時間復(fù)雜度:O(logN+M)
在redis6以后該命令被廢棄,將功能合并到zrange中
zpopmax
刪除并返回分?jǐn)?shù)最高的count個元素,類似topk問題語法: zpopmax key [count]
時間復(fù)雜度:O(logN*M)
刪除M個元素,查找一個元素時間復(fù)雜度為O(logN)
返回值:返回分?jǐn)?shù)和元素列表
bzpopmax
zpopmax的阻塞版本語法: bzpopmax key [key...] timeout
時間復(fù)雜度:O(logN)返回值:返回元素列表
zpopmin
刪除并返回分?jǐn)?shù)最低的count個元素語法: zpopmin key [count]
時間復(fù)雜度:O(logN*M)返回值:返回分?jǐn)?shù)和元素列表
bzpopmin
zpopmin的阻塞版本語法: bzpopmin key [key...] timeout
時間復(fù)雜度:O(logN)返回值:返回元素列表
zrank
返回指定元素的次序,按升序排語法: zrank key member
時間復(fù)雜度:O(logN)返回值:返回對應(yīng)次序/下標(biāo)
zrevrank
zrank的降序版本語法: zrevrank key member
時間復(fù)雜度:O(logN)返回值:返回對應(yīng)元素次序/下標(biāo)
zscore
返回指定元素的分?jǐn)?shù)語法: zscore key member
時間復(fù)雜度:O(1)
在前面的命令中根據(jù)member找元素的時間復(fù)雜度都是O(logN),但是這里redis犧牲空間,換取時間做了特定的優(yōu)化
zrem
刪除指定元素語法: zrem key member [member...]
返回值:分?jǐn)?shù)
zremrangebyrank
根據(jù)下標(biāo)表示的范圍進(jìn)行刪除,閉區(qū)間語法: zremrangebyrank key start stop
時間復(fù)雜度:O(logN+M)
查找位置只需一次即可,然后刪除M個元素
返回值:返回刪除的個數(shù)
zremrangebyscore
刪除對應(yīng)的分?jǐn)?shù)范圍內(nèi)的元素語法: zremrangebyscore key min max
時間復(fù)雜度:O(logN+M)返回值:返回刪除個數(shù)
zincrby
修改元素的分?jǐn)?shù),并保持整個有序集合仍然是升序的語法: zincrby key increment member
時間復(fù)雜度:O(logN)返回值:增加后元素的分?jǐn)?shù)
zinterstore
將給定有序集合中元素的交集并保持到目標(biāo)有序集合中語法: zinterstore destination numkeys key [key...] [weights weight [weight ...]] [aggregate <sum|min|max>]
- destination:把結(jié)果存儲到這個key
- numkeys:整數(shù),描述后續(xù)有幾個key參與交集運行
- weights: 權(quán)重,有序集合帶有分?jǐn)?shù),此處指定的權(quán)重,相當(dāng)于一個系數(shù),會乘于當(dāng)前的分?jǐn)?shù)
- aggregate:求并集時相同的元素的分?jǐn)?shù)是相加/取最小/取最大,默認(rèn)是相加
時間復(fù)雜度:O(NK)+O(Mlog(M)) -> O(M*logM)
N:輸入若干個有序集合中,元素最少的個數(shù)
K:有幾個有序集合
M:最終有序集合的元素個數(shù)
k一般不會太大,可以看作1,N和M接近,同一個數(shù)量級。
所以O(shè)(NK)+O(Mlog(M))->O(M)+O(Mlog(M))-> O(MlogM)
c:300.5+102=35
a:100.5+202=45
zunionstore
將給定有序集合中元素的并集并保存進(jìn)目標(biāo)有序集合中語法: zunionstore destination numkeys key [key...] [weights weight [weight...]][aggregate <sum|min|max>]
用法和 zinterstore
一致
內(nèi)部編碼
如果有序集合中的元素個數(shù)較少,或者各個元素體積較小使用 ziplist
來存儲,如果當(dāng)前元素個數(shù)比較多,或者各個元素體積非常大使用 skiplist
存儲
應(yīng)用場景
最關(guān)鍵的應(yīng)用場景就是排行榜系統(tǒng),例如微博熱搜,游戲天梯排行,成績排行
1.游戲天梯排汗
使用zset將玩家信息和對應(yīng)分?jǐn)?shù)存入即可,就會自動生成一個排行榜,可以使用
zrevrange
取出前幾名玩家。當(dāng)分?jǐn)?shù)發(fā)生改變,可以使用zincrby
修改分?jǐn)?shù),排行順序能自動調(diào)整。
2.微博熱搜
微博熱搜需要考慮到瀏覽量,點贊量,轉(zhuǎn)發(fā)量,評論量等,需要使用權(quán)重
weights
,此時可以使用zinterstore/zunionstore
按照加權(quán)的方式處理??梢詫⒚總€維度的數(shù)值放到有序集合中,member
就是微博id,score
就是各個維度的數(shù)值。通過zinterstore/zunionstore
把上述有序集合按照約定的權(quán)重,進(jìn)行集合間運算即可。
到此這篇關(guān)于Redis的zset類型的文章就介紹到這了,更多相關(guān)Redis zset類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Redis在SpringBoot工程中的綜合應(yīng)用
這篇文章主要介紹了Redis在SpringBoot工程中的綜合應(yīng)用,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10Redis fork進(jìn)程分配不到內(nèi)存解決方案
這篇文章主要介紹了Redis fork進(jìn)程分配不到內(nèi)存解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11Redis超詳細(xì)講解高可用主從復(fù)制基礎(chǔ)與哨兵模式方案
Redis因為其高性能和易用性在我們后端的服務(wù)中發(fā)揮了巨大的作用,并且很多重要功能的實現(xiàn)都會依賴redis,本篇我們來了解Redis高可用主從復(fù)制與哨兵模式2022-04-04關(guān)于Redis?bigkeys命令會阻塞問題的解決
這篇文章主要介紹了關(guān)于Redis?bigkeys命令會阻塞問題的解決,今天分享一次Redis引發(fā)的線上事故,避免再次踩雷,實現(xiàn)快速入門,需要的朋友可以參考下2023-03-03SpringBoot整合Redis實現(xiàn)序列化存儲Java對象的操作方法
這篇文章主要介紹了SpringBoot整合Redis實現(xiàn)序列化存儲Java對象,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03