一. 有序集合概述 Redis 有序集合對象和集合對象一樣也是string類型元素的集合,且不允許重覆的成員。不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。有序集合的成員是唯一的,但分數(score)卻可以重覆。 在前面第9章中講到Re ...
一. 有序集合概述
Redis 有序集合對象和集合對象一樣也是string類型元素的集合,且不允許重覆的成員。不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。有序集合的成員是唯一的,但分數(score)卻可以重覆。
在前面第9章中講到Redis 數據對象對應不同底層的數據結構,對於有序集合對象 編碼可以是ziplist 或者skiplist二種。skiplist編碼的底層數據結構可以參考"redis 系列7 數據結構之跳躍表"。ziplist編碼的壓縮列表結構以後再講。
1.1 ziplist編碼
ziplist編碼的有序集合對象使用壓縮列表作為底層實現,每個集合元素使用兩個緊挨在一起的壓縮列表節點來保存,第一個節點保存元素的成員(member),而第二個元素則保存元素的分值(score)。壓縮列表的集合元素按分值從小到大進行排序,分值較小的元素被放置在靠近表頭的方向,分值較大的元素則被放置在靠近表尾的方向。
下例中,使用zadd命令,創建一個有序集合對象作為price鍵的值。並且該對象使用的編碼是ziplist。
127.0.0.1:6379> zadd price 8.5 apple 5.0 banana (integer) 2 127.0.0.1:6379> object encoding price "ziplist"
1.2 skiplist編碼
skiplist編碼的有序集合對象使用字典和跳躍表作為底層實現,如果一個有序集合包含的元素數量比較多,又或者有序集合中元素的成員是比較長的字元串時,Redis就會使用跳躍表來作為有序集合鍵的底層實現。
下例中,還是使用zadd命令,創建一個有序集合對象作為store鍵的值。並且該對象使用的編碼是skiplist。
127.0.0.1:6379> zadd store 1.0 "long_long_long_long_long_long_long_long_long_long_long_long..." -- 省去了字元,大於64位元組 127.0.0.1:6379> object encoding store "skiplist"
1.3 編碼的轉換
當有序集合可以同時滿足以下兩個條件時,對象使用ziplist編碼:
(1) 有序集合保存的元素數量小於128個。
(2) 有序集合的所有元素成員的長度都小於64位元組。
127.0.0.1:6379> config get zset-max-ziplist-value 1) "zset-max-ziplist-value" 2) "64" 127.0.0.1:6379> config get zset-max-ziplist-entries 1) "zset-max-ziplist-entries" 2) "128"
二. 有序集合對象命令實現
-- Zadd 命令用於將一個或多個成員元素及其分數值加入到有序集當中。返回被成功添加的新成員的數量,不包括那些被更新的、已經存在的成員。 127.0.0.1:6379> zadd price 8.5 apple 5.0 banana (integer) 2 -- Zcard 命令用於計算集合中元素的數量。 127.0.0.1:6379> zcard price (integer) 2 -- Zcount 命令用於計算有序集合中指定分數區間的成員數量 127.0.0.1:6379> zrange price 0 -1 withscores 1) "banana" 2) "5" 3) "pear" 4) "6" 5) "apple" 6) "8.5" 127.0.0.1:6379> zcount price 5.0 7.0 -- 取scores值範圍 (integer) 2 -- Zincrby 命令對有序集合中指定成員的分數加上增量 increment, 可以通過傳遞一個負數值 increment ,讓分數減去相應的值。 127.0.0.1:6379> zrange price 0 -1 withscores 1) "pear" 2) "6" 127.0.0.1:6379> zincrby price 2.5 pear -- 添加2.5元 "8.5" -- Zinterstore 命令計算給定的一個或多個有序集的交集,其中給定 key 的數量必須以 numkeys 參數指定,並將該交集(結果集)儲存到 destination 。結果集中分數值是成員分數值之和。 127.0.0.1:6379> ZADD mid_test 70 "Li Lei" --第一個key mid_test (integer) 1 127.0.0.1:6379> ZADD mid_test 70 "Han Meimei" (integer) 1 127.0.0.1:6379> ZADD fin_test 88 "Li Lei" -- 第二個key fin_test (integer) 1 127.0.0.1:6379> ZADD fin_test 75 "Han Meimei" (integer) 1 127.0.0.1:6379> zinterstore sum_point 2 mid_test fin_test -- sum_point是destination,2是二個key (integer) 2 127.0.0.1:6379> zrange sum_point 0 -1 withscores --分數值之和 1) "Han Meimei" 2) "145" 3) "Li Lei" 4) "158" --Zlexcount 命令在計算有序集合中指定字典區間內成員數量. 127.0.0.1:6379> zadd myzset 1 a 2 b 3 c 4 d 5 e 6 f 7 g (integer) 7 127.0.0.1:6379> zlexcount myzset [c [g --獲取c 到g 的區間數量 (integer) 5 -- Zrange 返回有序集中,指定區間內的成員,其中成員的位置按分數值遞增(從小到大)來排序。 127.0.0.1:6379> zrange price 0 -1 withscores 1) "banana" 2) "5" 3) "pear" 4) "6" 5) "apple" 6) "8.5" -- Zrangebylex 通過字典區間返回有序集合的成員。 127.0.0.1:6379> zadd myzset 1 a 2 b 3 c 4 d 5 e 6 f 7 g (integer) 7 127.0.0.1:6379> zrangebylex myzset [c [g 1) "c" 2) "d" 3) "e" 4) "f" 5) "g" -- Zrangebyscore 返回有序集合中指定分數區間的成員列表。有序集成員按分數值遞增(從小到大)次序排列。更多用法見官方文檔 127.0.0.1:6379> ZADD salary 2500 jack (integer) 1 127.0.0.1:6379> ZADD salary 5000 tom (integer) 1 127.0.0.1:6379> ZADD salary 12000 peter (integer) 1 127.0.0.1:6379> zrangebyscore salary 2000 6000 withscores --返回工資範圍 1) "jack" 2) "2500" 3) "tom" 4) "5000" 127.0.0.1:6379> ZRANGEBYSCORE salary -inf 5000 WITHSCORES --返回工資小於5000範圍 1) "jack" 2) "2500" 3) "tom" 4) "5000" --Zrank 返回有序集中指定成員的排名。其中有序集成員按分數值遞增(從小到大)順序排列。下麵是jack 分值排名0位, peter分值排名2位。 127.0.0.1:6379> zrank salary jack (integer) 0 -- 2500 127.0.0.1:6379> zrank salary peter (integer) 2 -- 12000
-- Zrem 命令用於移除有序集中的一個或多個成員,不存在的成員將被忽略。 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 1) "jack" 2) "2500" 3) "tom" 4) "5000" 5) "peter" 6) "12000" 127.0.0.1:6379> zrem salary jack --移除jack成員成功 (integer) 1 --Zremrangebylex 命令用於移除有序集合中給定的字典區間的所有成員。 127.0.0.1:6379> zrange myzset 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f" 7) "g" 127.0.0.1:6379> zremrangebylex myzset [a [c --移除了a到c的成員數據 (integer) 3 --Zremrangebyrank 命令用於移除有序集中,指定排名(rank)區間內的所有成員. 127.0.0.1:6379> zrange salary 0 -1 1) "tom" 2) "peter" 127.0.0.1:6379> zremrangebyrank salary 0 0 --移除了分值排名為0的成員 (integer) 1 --稱除了tom 成員分值排0, peter分值排1 127.0.0.1:6379> zrange salary 0 -1 1) "peter" -- Zremrangebyscore 命令用於移除有序集中,指定分數(score)區間內的所有成員。 127.0.0.1:6379> zrange salary 0 -1 1) "peter" 127.0.0.1:6379> zremrangebyscore salary 10000 13000 --移除分值的範圍,peter分值為12000 (integer) 1 --Zrevrange 命令返回有序集中,指定區間內的成員,分數值 (從大到小)來排列. 與zrange命令一樣,分值排列相反。 127.0.0.1:6379> zrevrange salary 0 -1 withscores 1) "peter" 2) "12000" 3) "tom" 4) "5000" 5) "jack" 6) "2500" -- Zrevrangebyscore 返回有序集中指定分數區間內的所有的成員。有序集成員按分數值 (從大到小)的次序排列。 127.0.0.1:6379> zrevrangebyscore salary 6000 2000 withscores --返回分值範圍 1) "tom" 2) "5000" 3) "jack" 4) "2500" -- Zrevrank 命令返回有序集中成員的排名。其中有序集成員按分數值(從大到小)排序 127.0.0.1:6379> zrevrank salary tom (integer) 1 --tom工資排名第二 127.0.0.1:6379> zrevrank salary peter (integer) 0 --peter工資排名第一 -- Zscore 命令返回有序集中,成員的分數值。 127.0.0.1:6379> zscore salary peter "12000" --Zunionstore 命令計算給定的一個或多個有序集的並集,其中給定 key 的數量必須以 numkeys 參數指定,並將該並集(結果集)儲存到 destination 。 127.0.0.1:6379> zrange salary 0 -1 withscores --第一個key 1) "jack" 2) "2500" 3) "tom" 4) "5000" 5) "peter" 6) "12000" 127.0.0.1:6379> zrange salary2 0 -1 withscores --第二個key 1) "tom" 2) "500" 3) "jack" 4) "1000" 127.0.0.1:6379> zunionstore salaries 2 salary salary2 --合併到salaries的key中 (integer) 3 127.0.0.1:6379> zrange salaries 0 -1 withscores 1) "jack" 2) "3500" 3) "tom" 4) "5500" 5) "peter" 6) "12000"