天天看點

Redis對象——有序集合(ZSet)

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

繼續閱讀