Redis學習手冊5—數據結構之有序集合

有序集合

Redis的有序集合(sorted set)同時具有“有序”和“集合”兩種性質,這種數據結構中的每個元素都由一個成員和一個與成員相關聯的分值組成,其中成員以字符串方式存儲,而分數則以64位雙精度浮點數格式存儲。

下圖展示了有序集合的存儲結構:
在這裏插入圖片描述
與集合一樣,有序集合中的每個成員都是獨一無二的,同一個有序集合中不會出現重複的成員。與此同時,有序集合的成員將按照各自的分值大小進行排序。有序集合的分值除了可以是數字之外,還可以是字符串 **"+inf"**或者 “-inf”,這兩個特殊值分別表示 無窮大無窮小

雖然成員不能重複,但是成員對應的分數卻不受這一限制。

有序集合命令速查表

命令 用法及參數 說明
ZADD ZADD sorted_set [XX | NX] [CH] socre member [score member ...] 添加一個或多個成員
ZREM ZREM sorted_set member [member ...] 移除一個或多個成員
ZSCORE ZSCORE sorted_set member 獲取與給定成員相關聯的分值
ZINCRBY ZINCRBY sorted_set increment member 對指定成員的分值執行加法操作
ZCARD ZCARD sorted_set 獲取有序集合的大小
ZRANK ZRANK sorted_set member 獲取給定成員在有序集合中的升序排名
ZREVRANK ZREVRANK sorted_set member 獲取給定成員在有序集合中的降序排名
ZRANGE ZRANGE sorted_set start end [WITHSCORES] 以升序排列方式獲取指定範圍內的成員
ZREVRANGE ZREVRANGE sorted_set start end [WITHSCORES] 以降序排列方式獲取指定範圍內的成員
ZRANGEBYSCORE ZRANGEBYSCORE sorted_set min max [WITHSCORES] 以升序方式獲取分值介於min和max之間的成員
ZREVRANGEBYSCORE ZREVRANGEBYSCORE sorted_set max min [WITHSCORES] 以降序方式獲取分值介於max和min之間的成員
ZCOUNT ZCOUNT sorted_set min max 獲取指定分值範圍內的成員數量
ZREMRANGEBYRANK ZREMRANGEBYRANK sorted_set start end 從升序排列的有序集合中移除位於指定排名範圍內的成員
ZREMRANGEBYSCORE ZREMRANGEBYSCORE sorted_set min max 從升序有序集合中移除指定分值範圍內的成員
ZUNIONSTORE ZUNIONSTORE destination numbers sorted_set [sorted_set ...] 有序集合的並集運算
ZINSERTSTORE ZINSERTSTORE destination numbers sorted_set [sorted_set ...] 有序集合的交集運算
ZRANGEBYLEX ZRANGEBYLEX sorted_set min max 可以從按字典升序排序的有序集合中返回指定範圍的成員
ZREVRANGEBYLEX ZREVRANGEBYLEX sorted_set max min 可以從按字典降序排序的有序集合中返回指定範圍內的成員
ZLEXCOUNT ZLEXCOUNT sorted_set min max 獲取按字典排序的有序集合指定範圍內的成員數量
ZREMRANGEBYLEX ZREMRANGEBYLEX sorted_set min max 移除按字典排序的有序集合指定範圍內的成員
ZPOPMAX ZPOPMAX sorted_set [count] 移除有序集合中分值最大的N個成員
ZPOPMIN ZPOPMIN sorted_set [count] 移除有序集合中分值最小的N個成員
BZPOPMAX BZPOPMAX sorted_set [sorted_set] timeout ZPOPMAX命令的阻塞版本
BZPOPMIN BZPOPMIN sorted_set [sorted_set ...] timeout ZPOPMIN命令的阻塞版本

命令詳解

ZADD命令

使用ZADD命令可以向有序集合添加一個或多個成員:

ZADD sorted_set socre member [score member ...]

默認情況下,ZADD命令將返回成功添加的新成員數量作爲返回值。

127.0.0.1:6379> ZADD salary 3500 "peter" 4000 "jack" 2000 "tom" 5500 "mary"
(integer) 4

更新已有成員的分值

ZADD命令除了可以向有序集合添加新成員以外,還可以對有序集合中已存在的成員的分值進行更新:在默認情況下,如果用戶在執行ZADD命令時,給定成員已經存在,並且給定的分值和現有成員的分值不相同,那麼ZADD命令將使用給定的新分值去覆蓋現有的舊分值。

127.0.0.1:6379> ZADD salary 5000 "tom"
(integer) 0 -- 因爲這是一次更新操作,沒有添加任何新成員,所以返回0

指定要執行的操作

從Redis 3.0.2版本開始,Redis允許用戶在執行ZADD命令時,通過使用可選的XX選項或者NX選項來顯示地指示命令執行更新操作或者執行添加操作:

ZADD sorted_set [XX | NX] score member [score member ...]

這兩個選項的功能如下:

  • 在給定XX選項的情況下,ZADD命令只會對給定成員當中已存在於有序集合的成員進行更新,而那些不存在於有序集合的成員則會被忽略。
  • 在給定NX選項的情況下,ZADD命令只會把給定成員當中不存在於有序集合的成員添加到有序集合,而存在於有序集合的成員則會被忽略。

返回被修改成員的數量

在默認情況下,ZADD命令會返回添加成員的數量,但是從 Redis 3.0.2版本開始,用戶可以通過給定CH選項,讓ZADD命令返回被修改(changed)成員的數量作爲返回值:

ZADD sorted_set [CH] score number [score number ...]

其中 **“被修改成員”**指的是新添加到有序集合的成員,以及分值被修改的成員。

127.0.0.1:6379> ZADD salary CH 3500 "peter" 4000 "bob" 9000 "david"
(integer) 2

複雜度:O(Mlog(N))O(M*log(N)),其中MM爲給定成員的數量,而NN則爲有序集合的成員數量。
版本要求:不帶任何選項的ZADD命令從 Redis 1.2.0版本開始可用,帶有 NXXXCH等選項的ZADD命令從Redis 3.0.2版本開始可用。Redis 2.4.0以前ZADD命令只允許一次添加一個成員,而Redis 2.4.0及以上版本支持一次添加多個成員。

ZREM命令

使用ZREM命令可以從有序集合中移除一個或多個成員及其關聯的分值:

ZREM sorted_set member [member ...]

成功移除後將返回被移除成員的數量。

127.0.0.1:6379> ZREM salary "peter"
(integer) 1

如果用戶給定的成員不存在,那麼ZREM將自動忽略該成員。

複雜度:O(Mlog(N))O(M*log(N)),其中MM爲給定的成員數量,NN爲有序集合包含的成員數量。
版本要求:ZREM命令從Redis 1.2.0版本開始用,Redis 2.4.0版本及以上支持一次移除多個成員。

ZSCORE命令

通過使用ZSCORE命令,可以獲取與給定成員相關聯的分值:

ZSCORE sorted_set member
127.0.0.1:6379> ZSCORE salary "jack"
"4000"

如果給定的有序集合或成員不存在,則返回空值。

複雜度:O(1)O(1)
版本要求:ZSCORE命令從Redis 1.2.0版本可用。

ZINCRBY命令

通過使用ZINCRBY命令,可以對指定成員的分值執行加法操作:

ZINCRBY sorted_set increment member

執行成功後,返回當前成員對應的分值。

127.0.0.1:6379> ZINCRBY salary 1000 "jack"
"5000"

如果傳入的增量爲負數,則可以實現減法操作:

127.0.0.1:6379> ZINCRBY salary -1000 "peter"
"2000"

如果給定的有序集合或成員不存在,那麼ZINCRBY命令直接把給定的成員添加到有序集合中,並把給定的增量設置爲該成員的分值:

127.0.0.1:6379> ZINCRBY salary 1500 "lily"
"1500"

複雜度:O(log(N))O(log(N)),其中NN爲有序集合包含的成員數量。
版本要求:ZINCRBY命令從Redis 1.2.0版本開始可用。

ZCARD命令

使用ZCARD命令可以獲取有序集合的大小,即有序集合中包含的成員數量:

ZCARD sorted_set
127.0.0.1:6379> ZCARD salary
(integer) 4

複雜度:O(1)O(1)
版本要求:ZCARD命令從Redis 1.2.0版本開始可用。

ZRANK、ZREVRANK命令

通過ZRANK命令和ZREVRANK命令可以獲取指定成員在有序集合中的排名:

ZRANK sorted_set
ZREVRANK sorted_set

其中ZRANK命令返回的是成員的升序排名,即成員在按照分值從小到大進行排序時的排名,而ZREVRANK命令返回的是成員的降序排名,即成員在按照分值的從大到小的排序時的排名。

127.0.0.1:6379> ZRANK salary "peter"
(integer) 0
127.0.0.1:6379> ZRANK salary "tom"
(integer) 3
127.0.0.1:6379> ZREVRANK salary "peter"
(integer) 4

如果給定的有序集合或成員不存在,那麼兩個命令都會返回空值。

複雜度:O(log(N))O(log(N)),其中NN爲有序集合的成員數量。
版本要求:ZRANK命令和ZREVRANK命令從Redis 2.0.0版本開始可用。

ZRANGE、ZREVRANGE命令

使用ZRANGE命令和ZREVRANGE命令,可以以升序或降序的排列方式,從有序集合中獲取指定索引範圍內的成員:

ZRANGE sorted_set start end
ZREVRANGE sorted_set start end

其中ZRANGE命令用於獲取按照分值從小到大升序排列的成員,而ZREVRANGE命令則用於獲取從大到小降序排列的成員。命令中的start索引和end索引指定的是閉區間索引範圍,也就是說包含了兩個索引位置上的成員。

127.0.0.1:6379> ZRANGE salary 0 3
1) "peter"
2) "bob"
3) "jack"
4) "tom"

與之前介紹過的列表命令LRANGE類似,ZRANGE命令和ZREVRANGE命令除了可以接受正數索引,也可以接受負數索引:

127.0.0.1:6379> ZRANGE salary -3 -1
1) "jack"
2) "tom"
3) "mary"

獲取成員及其分值

在默認情況下,ZRANGE命令和ZREVRANGE命令只返回指定索引範圍內的成員,如果用戶想要在獲取這些成員的同時獲取與之關聯的分值,那麼可以在使用WITHSOCRES選項:

ZRANGE sorted_set start end [WITHSCORES]
ZREVRANGE sorted_set start end [WITHSCORES]
127.0.0.1:6379> ZRANGE salary 0 3 WITHSCORES
1) "peter"
2) "3500"
3) "bob"
4) "3800"
5) "jack"
6) "4500"

如果給定的有序集合不存在,那麼將返回一個空列表。

複雜度:O(log(N)+M)O(log(N)+M),其中NN爲有序集合的成員數量,而MM爲命令返回的成員數量。
版本要求:ZRANGE命令和ZREVRANGE命令從Redis 1.2.0版本開始可用。

ZRANGEBYSCORE、ZREVRANGEBYSCORE命令

通過使用ZRANGEBYSCORE命令或者ZREVRANGEBYSCORE命令,可以以升序或降序的方式獲取有序集合中分值介於指定範圍內的成員:

ZRANGEBYSCORE sorted_set min max
ZREVRANGEBYSCORE sorted_set max min

命令的min參數和max參數分別用於指定用戶想要獲取的成員最小分值和最大分值。

注意: ZRANGEBYSCORE命令和ZREVRANGEBYSCORE命令接受的min和max參數的順序正好相反:ZRANGEBYSCORE命令先接受min參數,然後再接受max參數,而ZREVRANGEBYSCORE命令剛好相反。

ZRANGE命令類似,如果想要同時獲取成員對應的分值,則需要使用WITHSCORES選項:

ZRANGEBYSCORE sorted_set min max [WITHSCORES]
ZREVRANGEBYSCORE sorted_set max min [WITHSCORES]

限制命令返回的成員數量

在默認情況下,ZRANGEBYSCORE命令或者ZREVRANGEBYSCORE命令會直接返回給定分值範圍內的所有成員,但是如果範圍內的成員數量較多,或者我們只需要一部分成員,那麼可以使用可選的LIMIT選項來限制命令返回的成員數量:

ZRANGEBYSCORE sored_set min max [WITHSCORES] [LIMIT offset count]
ZREVRANGESCORE sorted_set max min [WITHSCORES] [LIMIT offset count]

LIMIT選項接受offsetcount兩個參數作爲輸入,其中offset參數用於指定命令在返回結果之前需要跳過的成員數量,而count參數用於指示命令最多可以返回的成員數量。

127.0.0.1:6379> ZRANGEBYSCORE salary 3000 5000 LIMIT 0 1
1) "peter"

使用開區間分值範圍

在默認情況下,ZRANGEBYSCORE命令和ZREVRANGEBYSCORE命令接受的分值範圍都是閉區間的,如果想要使用開區間,那麼可以在給定分值範圍時,在分值參數的前面加上一個單括號 “(”,如下所示:

127.0.0.1:6379> ZRANGEBYSCORE salary (3000 (5000 WITHSCORES
1) "bob"
2) "3800"
3) "jack"
4) "4500"

使用無限值作爲範圍

ZRANGEBYSCORE命令和ZREVRANGEBYSCORE命令的min參數和max參數除了可以是普通的分值或帶有 **"("**符號的分值之外,還可以使用特殊值 **"+inf"**或者 -inf,前者用於表示 無窮大,後者表示 無窮小

127.0.0.1:6379> ZRANGEBYSCORE salary -inf (4500 WITHSCORES   -- 獲取小於分值4500的成員及其分值
1) "peter"
2) "3500"
3) "bob"
4) "3800"

複雜度:O(log(N)+M)O(log(N)+M),其中NN爲有序集合包含的成員數量,而MM則爲命令返回的成員數量。
版本要求:ZRANGEBYSCORE命令從Redis 1.0.5版本開始可用,而ZREVRANGEBYSCORE命令從Redis 2.2.0版本開始可用。

ZCOUNT命令

通過使用ZCOUNT命令,用戶可以統計出有序集合中分值介於指定範圍內的成員數量:

ZCOUNT sorted_set min max
127.0.0.1:6379> ZCOUNT salary 3000 5000
(integer) 4

複雜度:O(log(N))O(log(N)),其中NN爲有序集合包含的成員數量。
版本要求:ZCOUNT命令從Redis 2.0.0版本開始可用。

ZREMRANGEBYRANK命令

ZREMRANGEBYRANK命令可以從升序排列的有序集合中移除位於指定排名範圍內的成員,然後返回被移除成員的數量:

ZREMRANGEBYRANK sorted_set start end

與Redis其他範圍命令一樣,該命令的範圍也是閉區間的,也支持負數排名區間。

複雜度:log(N)+M)(log(N)+M),其中NN爲有序集合中的成員數量,而MM爲被移除的成員數量。
版本要求:該命令從Redis 2.0.0版本開始可用。

ZREMRANGEBYSCORE命令

ZREMRANGEBYSCORE命令可以從升序有序集合中移除指定分值範圍內的成員,並返回被移除成員的數量:

ZREMRANGEBYSCORE sorted_set min max

ZREMRANGEBYSCORE命令與ZRANGEBYSCORE命令一樣,默認使用閉區間,也可以支持開區間和無限值。

複雜度:O(log(N)+M)O(log(N)+M),其中NN爲有序集合中的成員數量,而MM爲被移除成員的數量。
版本要求:該命令從Redis 1.2.0版本開始可用。

ZUNIONSTORE、ZINSERTSTORE命令

與集合一樣,Redis也爲有序集合提供了相應的並集運算命令ZUNIONSTORE和交集運算命令ZINSERTSTORE

ZUNIONSTORE destination  numbers sorted_set [sorted_set ...]
ZINSERTSTORE destination numbers sorted_set [sorted_set ...]

其中,命令的numbers參數用於指定參與計算的有序集合數量,之後的一個或多個sorted_set參數用於指定參與計算的有序集合鍵名,計算得出的結果會存儲到destination指定的鍵中。

對於有序集合運算,相同成員的情況下,默認情況下分值相加。

兩個命令都會返回計算結果包含的成員數量。

127.0.0.1:6379> union-result 2 sorted_set1 sorted_set2
(integer) 5

指定聚合函數

Redis爲ZUNIONSTORE命令和ZINSERTSTORE命令提供了可選的AGGREGATE選項,通過這個選項,用戶可以決定使用哪個聚合函數來計算結果有序集合成員的分值:

ZUNIONSTORE destination numbers sorted_set [sorted_set ...] [AGGREGATE SUM|MIN|MAX]
ZINSERTSTORE destination numbers sorted_set [sorted_set ...] [AGGREGATE SUM|MIN|MAX]

AGGREGATE選項的值可以是SUMMIN或者MAX中的一個,作用如下表所示:

聚合函數 作用
SUM 把給定有序集合中所有相同成員的分值都相加起來,它們的和就是該成員在結果有序集合中的分值
MIN 從給定有序集合所有相同成員的分值中選出最小的分值,並把它作爲該成員在結果有序集合中的分值
MAX 從給定有序集合所有相同成員的分值中選出最大的分值,並把它作爲改成員在結果有序集合中的分值

默認情況下,如果未指定聚合函數,則默認使用SUM

設置權重

在默認情況下,ZUNIONSTORE命令和ZINSERTSTORE命令將直接使用成員的分值去計算結果有序集合成員的分值,但是在有需要的情況下,也可以通過可選的WEIGHTS參數爲各個給定有序集合的成員分值設置權重:

ZUNIONSTORE destination numbers sorted_set [sorted_set ...] [WEIGHTS weight [weight ...]]
ZINSERTSTORE destination numbers sorted_set [sorted_set ...] [WEIGHTS weight [weight ...]]

在使用WEIGHTS選項時,用戶需要爲每個給定的有序集合分別設置一個權重,命令會將這個權重與成員的分值相乘,得出成員的新分值,然後執行聚合運算。與此相反,如果用戶在使用WEIGHTS選項時,不想改變某個成員的分值,那麼只需要將那個成員的權重設置爲1即可。

使用集合作爲輸入

ZUNIONSTORE命令和ZINSERTSTORE命令除了可以使用有序集合作爲輸入之外,還可以使用集合作爲輸入:在默認情況下,這兩個命令將把給定的集合看作是所有成員的分值都爲1的有序集合來進行計算。如果有需要,可以使用WEIGHTS選項來改變集合的分值。

複雜度:ZUNIONSTORE命令的複雜度爲O(Nlog(N))O(N*log(N)),其中NN爲所有給定有序集合的成員總數。ZINSERTSTORE命令的複雜度爲O(Nlog(N)M)O(N*log(N)*M),其中NN爲所有給定有序集合中,基數最小的那個有序集合的基數,而MM則是給定的有序集合的數量。
版本要求:兩個命令都是從Redis 2.0.0版本開始可用。

ZRANGEBYLEX、ZREVRANGEBYLEX命令

如果有序集合中的所有成員的分值都相同,這種情況下,之前講述的排序命令如:ZRANGEBYSCOREZCOUNTZREMRANGEBYSCORE等,都將不再適用。

因此,Redis提供了相應的ZRANGEBYLEXZREVRANGEBYLEXZLEXCOUNTZREMRANGEBYLEX命令,這些命令可以分別對字典排序的有序集合執行升序或降序排練範圍獲取操作、統計位於字典序指定範圍內的成員數量、移除字典序指定範圍內的成員等操作。

ZRANGEBYLEX sorted_set min max

其中參數minmax的取值方式如下:

  • 帶有 “[” 符號的值表示在結果中包含與給定值具有同等字典大小的成員。
  • 帶有 “(” 符號的值表示在結果中不包含與給定值具有相同字典大小的成員。
  • 加號 “+” 表示無窮大。
  • 減號 “-” 表示無窮小。
127.0.0.1:6379> ZRANGEBYLEX words [a [b
1) "address"
2) "after"
3) "apple"

ZREVRANGEBYLEX命令的用法與ZRANGEBYLEX命令類似,不同的是參數 minmax正好相反:

ZREVRANGEBYLEX sorted_set max min

同樣的,與有序集合其他範圍命令一樣,ZRANGEBYLEX命令和ZREVRANGEBYLEX命令也可以通過 LIMIT選項來限制返回成員的數量:

ZRANGEBYLEX sorted_set min max [LIMIT offset count]
ZREVRANGEBYLEX sorted_set max min [LIMIT offset count]

複雜度:兩個命令的複雜度都爲 O(log(N)+M)O(log(N)+M),其中NN爲有序集合包含的成員數量,而MM爲命令返回的成員數量。
版本要求:兩個命令從Redis 2.8.9版本開始可用。

ZLEXCOUNT命令

使用ZLEXCOUNT命令可以獲取按字典排序的有序集合中位於指定字典範圍內的成員數量:

ZLEXCOUNT sorted_set min max

其中 minmax參數的用法和ZRANGEBYLEX命令的一樣。

複雜度:O(log(N))O(log(N)),其中NN爲有序集合成員數量。
版本要求:從Redis 2.8.9開始可用。

ZREMRANGEBYLEX命令

使用ZREMRANGEBYLEX命令可以從按字典排序的有序集合中,移除指定字典範圍內的成員:

ZREMRANGEBYLEX sorted_set min max

複雜度:O(log(N)+M)O(log(N)+M),其中NN爲有序集合成員數量,MM爲移除的成員數量。
版本要求:從Redis 2.8.9版本開始可用。

ZPOPMAX、ZPOPMIN命令

ZPOPMAX命令和ZPOPMIN命令是Redis 5.0版本新添加的命令,分別用於移除並返回有序集合中分值最大和最小的N個元素:

ZPOPMAX sorted_set [count]
ZPOPMIN sorted_set [count]

複雜度:O(N)O(N),其中NN爲有序集合的成員數量。
版本要求:從Redis 5.0開始可用。

BZPOPMAX、BZPOPMIN命令

BZPOPMAX命令和BZPOPMIN命令分別是ZPOPMAX命令和ZPOPMIN命令的阻塞版本,這兩個阻塞命令都接受任意多個有序集合和一個秒級精度的超時時限作爲參數:

BZPOPMAX sorted_set [sorted_set ...] timeout
BZPOPMIN sorted_set [sorted_set ...] timeout

從遇到的第一個非空有序集合中彈出指定的元素,如果所給有序集合都爲空,則阻塞執行該命令的客戶端,直到遇到可以彈出的成員,或者達到超時時限。

複雜度:O(N)O(N),其中NN爲有序集合的數量。
版本要求:從Redis 5.0版本開始可用。

上一篇:Redis學習手冊4—數據結構之集合

下一篇:Redis學習手冊6—數據結構之HyperLogLog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章