Redis對象——有序集合(ZSet)
有序集合類型 (Sorted Set或ZSet) 相比于集合類型多了一個排序屬性 score(分值),對于有序集合 ZSet 來說,每個存儲元素相當于有兩個值組成的,一個是有序結合的元素值,一個是排序值。有序集合保留了集合不能有重複成員的特性(分值可以重複),但不同的是,有序集合中的元素可以排序。
一、内部實作#
有序集合是由 ziplist (壓縮清單) 或 skiplist (跳躍表) 組成的。
當資料比較少時,有序集合使用的是 ziplist 存儲的,有序集合使用 ziplist 格式存儲必須滿足以下兩個條件:
有序集合儲存的元素個數要小于 128 個;
有序集合儲存的所有元素成員的長度都必須小于 64 位元組。
如果不能滿足以上兩個條件中的任意一個,有序集合将會使用 skiplist 結構進行存儲。
有關ziplist 和skiplist 這兩種redis底層資料結構的具體實作可以參考我的另外兩篇文章。
Redis資料結構——壓縮清單
Redis資料結構——跳躍表。
二、常用指令#
Redis清單對象常用指令如下表(點選指令可檢視指令詳細說明)。
指令 說明 時間複雜度
BZPOPMAX key [key ...] timeout 從一個或多個排序集中删除并傳回得分最高的成員,或阻塞,直到其中一個可用為止 O(log(N))
BZPOPMIN key [key ...] timeout 從一個或多個排序集中删除并傳回得分最低的成員,或阻塞,直到其中一個可用為止 O(log(N))
ZADD key [NXXX] [CH] [INCR] score member [score member ...] 添加到有序set的一個或多個成員,或更新的分數,如果它已經存在 O(log(N))
ZCARD key 擷取一個排序的集合中的成員數量 O(1)
ZCOUNT key min max 傳回分數範圍内的成員數量 O(log(N))
ZINCRBY key increment member 增量的一名成員在排序設定的評分 O(log(N))
ZINTERSTORE 相交多個排序集,導緻排序的設定存儲在一個新的關鍵 O(NK)+O(Mlog(M))
ZLEXCOUNT key min max 傳回成員之間的成員數量 O(log(N))
ZPOPMAX key [count] 删除并傳回排序集中得分最高的成員 O(log(N)*M)
ZPOPMIN key [count] 删除并傳回排序集中得分最低的成員 O(log(N)*M)
ZRANGE key start stop [WITHSCORES] 根據指定的index傳回,傳回sorted set的成員清單 O(log(N)+M)
ZRANGEBYLEX key min max [LIMIT offset count] 傳回指定成員區間内的成員,按字典正序排列, 分數必須相同。 O(log(N)+M)
ZREVRANGEBYLEX key max min [LIMIT offset count] 傳回指定成員區間内的成員,按字典倒序排列, 分數必須相同 O(log(N)+M)
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 傳回有序集合中指定分數區間内的成員,分數由低到高排序。 O(log(N)+M)
ZRANK key member 确定在排序集合成員的索引 O(log(N))
ZREM key member [member ...] 從排序的集合中删除一個或多個成員 O(M*log(N))
ZREMRANGEBYLEX key min max 删除名稱按字典由低到高排序成員之間所有成員。 O(log(N)+M)
ZREMRANGEBYRANK key start stop 在排序設定的所有成員在給定的索引中删除 O(log(N)+M)
ZREMRANGEBYSCORE key min max 删除一個排序的設定在給定的分數所有成員 O(log(N)+M)
ZREVRANGE key start stop [WITHSCORES] 在排序的設定傳回的成員範圍,通過索引,下令從分數高到低 O(log(N)+M)
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] 傳回有序集合中指定分數區間内的成員,分數由高到低排序。 O(log(N)+M)
ZREVRANK key member 确定指數在排序集的成員,下令從分數高到低 O(log(N))
ZSCORE key member 擷取成員在排序設定相關的比分 O(1)
ZUNIONSTORE 添加多個排序集和導緻排序的設定存儲在一個新的關鍵 O(N)+O(M log(M))
ZSCAN key cursor [MATCH pattern] [COUNT count] 疊代sorted sets裡面的元素 O(1)
三、使用場景#
3.1 排行榜系統#
有序集合比較典型的使用場景就是排行榜系統。例如學生成績的排名。某視訊(部落格等)網站的使用者點贊、播放排名、電商系統中商品的銷量排名等。我們以部落格點贊為例。
添加使用者贊數
例如小編Tom發表了一篇博文,并且獲得了10個贊。
Copy
zadd user:ranking arcticle1 10
取消使用者贊數
這個時候有一個讀者又覺得Tom寫的不好,又取消了贊,此時需要将文章的贊數從榜單中減去1,可以使用zincrby。
zincrby user:ranking arcticle1 -1
檢視某篇文章的贊數
ZSCORE user:ranking arcticle1
展示擷取贊數最多的十篇文章
此功能使用zrevrange指令實作:
zrevrangebyrank user:ranking 0 9
3.2 電話号碼(姓名)排序#
使用有序集合的ZRANGEBYLEX(點選可檢視該指令詳細說明)或ZREVRANGEBYLEX可以幫助我們實作電話号碼或姓名的排序,我們以ZRANGEBYLEX為例
注意:不要在分數不一緻的SortSet集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因為擷取的結果會不準确。
電話号碼排序
我們可以将電話号碼存儲到SortSet中,然後根據需要來擷取号段:
redis> zadd phone 0 13100111100 0 13110114300 0 13132110901
(integer) 3
redis> zadd phone 0 13200111100 0 13210414300 0 13252110901
redis> zadd phone 0 13300111100 0 13310414300 0 13352110901
擷取所有号碼:
redis> ZRANGEBYLEX phone - +
1) "13100111100"
2) "13110114300"
3) "13132110901"
4) "13200111100"
5) "13210414300"
6) "13252110901"
7) "13300111100"
8) "13310414300"
9) "13352110901"
擷取132号段:
redis> ZRANGEBYLEX phone [132 (133
1) "13200111100"
2) "13210414300"
3) "13252110901"
擷取132、133号段:
redis> ZRANGEBYLEX phone [132 (134
4) "13300111100"
5) "13310414300"
6) "13352110901"
姓名排序
将名稱存儲到SortSet中:
redis> zadd names 0 Toumas 0 Jake 0 Bluetuo 0 Gaodeng 0 Aimini 0 Aidehua
(integer) 6
擷取所有人的名字:
redis> ZRANGEBYLEX names - +
1) "Aidehua"
2) "Aimini"
3) "Bluetuo"
4) "Gaodeng"
5) "Jake"
6) "Toumas"
擷取名字中大寫字母A開頭的所有人:
redis> ZRANGEBYLEX names [A (B
擷取名字中大寫字母C到Z的所有人:
redis> ZRANGEBYLEX names [C [Z
1) "Gaodeng"
2) "Jake"
3) "Toumas"
小結#
本篇文章我們總結了Redis 有序集合對象的内部實作、常用指令以及常用的一些場景,有序集合提供了擷取指定分數和元素範圍查詢、計算成員排名等功能,合理的利用有序集合,能幫助我們在實際開發中解決很多問題。那麼大家在項目中對Redis有序集合對象的使用都有哪些場景呢,歡迎在評論區給我留言和分享,我會第一時間回報!我們共同學習與進步!
參考#
《Redis設計與實作》
《Redis開發與運維》
《Redis官方文檔》
-----END-----#
作者: 老於`
出處:
https://www.cnblogs.com/hunternet/p/12717643.html