1. 有序集集合
Redis 中的有序集合(Sorted Set)类似于集合类型,二都都是字符串的集合,都不允许重复的成员的存在。它们之间的主要区别是有序集合中的每一个成员都会有一个分数(score)与之关联,Redis 通过这个分数来对集合成员按从小到大的顺序排序。
score是Reids 对集合元素排序的一个权重依据,虽然集合元素不可重复,但score是可重复的
Redis 的有序集合类型操作效率非常高,是其它同类数据库所难以实现。在有序集合中添加、删除或更新一个元素的操作速度都非常快,其时间复杂度为集合中成员数量的对数。由于有序集合中的成员在集合中的位置是有序的,所以即使是操作集合中部的成员也会非常高效。
2. 有序集合操作命令及使用
2.1 有序集合添加、修改元素
有序集合使用ZADD命令向已经的有序集合添加新元素,或创建新的有序集合。score是有序集合排序时的权重依据,对于已存在的元素,可以使用ZINCRBY命令修改元素的权重值。
2.1.1 ZADD - 添加元素
ZADD key score member [[score member] [score member] ...]
将一个或多个元素及其score值添加到有序集合key中。如果某个元素member已经存在,则更新其score值,并将其重新插入合适的位置。
score可以是整数或双精度浮点数。
key不存在时,则创建一个新的有序集合并插入指定元素。key存在但不是有序集合时,返回一个错误。
复杂度、返回值:
- 时间复杂度:
O(M*log(N)),N是有序集合的基数,M是要添加的新元素 - 返回值:被成功添加的新元素的数量。
使用示例
# 添加单个元素 redis> ZADD page_rank 10 google.com (integer) 1 # 添加多个元素 redis> ZADD page_rank 9 niefengjun.cn 8 bing.com (integer) 2 redis> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "niefengjun.cn" 4) "9" 5) "google.com" 6) "10" # 添加已存在元素,且 score 值不变 redis> ZADD page_rank 10 google.com (integer) 0 redis> ZRANGE page_rank 0 -1 WITHSCORES # 没有改变 1) "bing.com" 2) "8" 3) "niefengjun.cn" 4) "9" 5) "google.com" 6) "10" # 添加已存在元素,且改变 score 值 redis> ZADD page_rank 6 bing.com (integer) 0 redis> ZRANGE page_rank 0 -1 WITHSCORES # bing.com 元素的 score 值被改变 1) "bing.com" 2) "6" 3) "niefengjun.cn" 4) "9" 5) "google.com" 6) "10"
2.1.2 ZINCRBY - 增加元素权重
ZINCRBY key increment member
为有序集合key的元素member的score增加值increment。increment可以是一个负数,用于减小元素的score值。
key不存在或元素不存在,执行 ZINCRBY key -5 member操作相当于ZADD key increment member
复杂度、返回值:
- 时间复杂度:
O(log(N)) - 返回值:
member新的score值;当key不是有序集合返回一个错误
使用示例
redis> ZSCORE salary tom "2000" redis> ZINCRBY salary 2000 tom "4000"
2.2 有序集合查询
查询有序集合时,可以查询其某一个或多个元素的。查询一个元素,可以通过ZRANK命令查询元素的排名,或使用ZSCORE命令查询元素的权重。而查询多个元素进,可以按正序/倒序、下标区间/权重区间查询元素。
2.2.1 ZCARD - 返回集合基数
ZCARD key
返回有序集合key的基数。
复杂度、返回值:
- 时间复杂度:
O(1) - 返回值:有序集合
key的基数;当集合不存在时,返回0
使用示例
# 添加一个元素 redis > ZADD salary 2000 tom (integer) 1 redis > ZCARD salary (integer) 1 # 再添加一个元素 redis > ZADD salary 5000 jack (integer) 1 redis > ZCARD salary (integer) 2 # 对不存在的有序集合进行 ZCARD 操作 redis > EXISTS non_exists_key (integer) 0 redis > ZCARD non_exists_key (integer) 0
2.2.2 ZRANK - 返回指定元素的排名
ZRANK key member
返回有序集合key中的元素member的排名。元素成员按score值递增,相同score值的成员按字典排序。元素排名从0开始计数。
复杂度、返回值:
- 时间复杂度:
O(log(N)) - 返回值:元素
member的排名;如果key不是有序集合,返回nil
使用示例
# 显示所有成员及其 score 值 redis> ZRANGE salary 0 -1 WITHSCORES 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" # tom 排名第二 redis> ZRANK salary tom (integer) 1
2.2.3 ZSCORE - 返回指元素的权重
ZSCORE key member
返回有序集合key中,元素member的score值。
复杂度、返回值:
- 时间复杂度:
O(1) - 返回值:指定元素的
score值;如果元素不存在或key不存在,则返回nil
使用示例
redis> ZRANGE salary 0 -1 WITHSCORES 1) "tom" 2) "2000" 3) "peter" 4) "3500" 5) "jack" 6) "5000" # 返回值是字符串形式 redis> ZSCORE salary peter "3500"
2.2.4 ZCOUNT - 返回集合两个权重间的元素数
ZCOUNT key min max
返回有序集合key,score值在min和max之间的元素数(包含值为min和max的元素)。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为min和max之间的元素数 - 返回值:有序集合
key的基数;当集合不存在时,返回0
使用示例
# 测试数据 redis> ZRANGE salary 0 -1 WITHSCORES 1) "jack" 2) "2000" 3) "peter" 4) "3500" 5) "tom" 6) "5000" # 计算薪水在 2000-5000 之间的人数 redis> ZCOUNT salary 2000 5000 (integer) 3 # 计算薪水在 3000-5000 之间的人数 redis> ZCOUNT salary 3000 5000 (integer) 2
2.2.5 ZRANGE - 返回指定区间内的元素
ZRANGE key start stop [WITHSCORES]
返回有序集合key指定区间内的元素。元素成员按score值递增,相同score值的成员按字典排序。
start和stop都是从0开始。当使用负数时,表示从集合的末尾开始计数。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为结果集的基数。 - 返回值:指定区间内的成员列表
使用示例
# 显示有序集合所有成员 redis > ZRANGE salary 0 -1 WITHSCORES 1) "jack" 2) "3500" 3) "tom" 4) "5000" 5) "boss" 6) "10086" # 返回有序集下标区间 1 至 2 的成员 redis > ZRANGE salary 1 2 WITHSCORES 1) "tom" 2) "5000" 3) "boss" 4) "10086" # end 超出最大下标时 redis > ZRANGE salary 0 200000 WITHSCORES 1) "jack" 2) "3500" 3) "tom" 4) "5000" 5) "boss" 6) "10086" # 当指定区间超出有序集合范围时 redis > ZRANGE salary 200000 3000000 WITHSCORES (empty list or set)
2.2.6 ZREVRANGE - 倒序返回指定区间内的元素
ZREVRANGE key start stop [WITHSCORES]
返回有序集合key中,指定区间内的成员。score值按倒序(从大到小)顺序排序。
除score按倒序排序外,此命令与ZRANGE命令完全一致。WITHSCORES用于指定是否同时返回元素的score。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为结果集的数量 - 返回值:指定区间的元素
使用示例
# 递增排列 redis> ZRANGE salary 0 -1 WITHSCORES 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" # 递减排列 redis> ZREVRANGE salary 0 -1 WITHSCORES 1) "jack" 2) "5000" 3) "tom" 4) "4000" 5) "peter" 6) "3500"
2.2.7 ZRANGEBYSCORE - 返回指定权重区间内的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集合key指定区间内的元素。元素成员按score值递增,相同score值的成员按字典排序。
可选参数LIMIT用于指定返回元素数量,offset用于指定便移量(类似SQL中的SELECT LIMIT offset, count )。WITHSCORES用于指定是否同时返回score。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为结果集的基数。 - 返回值:指定区间内的成员列表
使用示例
# 测试数据 redis> ZADD salary 2500 jack (integer) 0 redis> ZADD salary 5000 tom (integer) 0 redis> ZADD salary 12000 peter (integer) 0 # 显示整个有序集合 redis> ZRANGEBYSCORE salary -inf +inf 1) "jack" 2) "tom" 3) "peter" # 显示整个有序集合及成员的 score 值 redis> ZRANGEBYSCORE salary -inf +inf WITHSCORES 1) "jack" 2) "2500" 3) "tom" 4) "5000" 5) "peter" 6) "12000" # 工资 <=5000 的成员 redis> ZRANGEBYSCORE salary -inf 5000 WITHSCORES 1) "jack" 2) "2500" 3) "tom" 4) "5000" # 工资大于 5000 小于等于 400000 的成员 redis> ZRANGEBYSCORE salary 5000 400000 1) "peter"
2.2.8 ZREVRANGEBYSCORE - 倒序返回指定权重区间内的元素
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
返回有序集合key中,score值位于max和min(默认包含max和min)区间内的成员。score值按递减(从大到小)顺序排序。
除score按倒序排序外,此命令与ZRANGEBYSCORE命令完全一致。WITHSCORES用于指定是否同时返回元素的score。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为结果集的数量 - 返回值:指定区间的元素
使用示例
redis > ZADD salary 10086 jack (integer) 1 redis > ZADD salary 5000 tom (integer) 1 redis > ZADD salary 7500 peter (integer) 1 redis > ZADD salary 3500 joe (integer) 1 # 倒序返回所有成员 redis > ZREVRANGEBYSCORE salary +inf -inf 1) "jack" 2) "peter" 3) "tom" 4) "joe" # 倒序返回salary于 10000 和 2000 之间的成员 redis > ZREVRANGEBYSCORE salary 10000 2000 1) "peter" 2) "tom" 3) "joe"
2.3 有序集合移除元素
如果需要移除有序集合中的元素,可以使用ZREM移除指定的元素成员。也可以使用ZREMRANGEBYRANK或ZREMRANGEBYSCORE来移除指定下标区间或权重区间内的元素。
2.3.1 ZREM - 移除元素
ZREM key member [member ...]
移除有序集合key中的一个或多个元素member的排名,不存在成员将被忽略。
复杂度、返回值:
- 时间复杂度:
O(M*log(N)),N是有序集合的基数,M为移除元素数量 - 返回值:被成功移除的元素数量;如果
key不是有序集合,会返回一个错误
使用示例
# 测试数据 redis> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "niefengjun.cn" 4) "9" 5) "google.com" 6) "10" # 移除单个元素 redis> ZREM page_rank google.com (integer) 1 redis> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "niefengjun.cn" 4) "9" # 移除多个元素 redis> ZREM page_rank niefengjun.cn bing.com (integer) 2 redis> ZRANGE page_rank 0 -1 WITHSCORES (empty list or set) # 移除不存在元素 redis> ZREM page_rank non-exists-element (integer) 0
2.3.2 ZREMRANGEBYRANK - 移除指定区间内的元素
ZREMRANGEBYRANK key start stop
移除有序集合key中,指定排名(rank)区间内的元素。
start和stop用于指定元素区间,start和stop包含在区间内。start和stop的底数以0开始,也可以使用负数,如-1表示最后一个元素,依次类推。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为移除元素数量 - 返回值:被移除成员的数量
使用示例
# 测试数据 redis> ZADD salary 2000 jack (integer) 1 redis> ZADD salary 5000 tom (integer) 1 redis> ZADD salary 3500 peter (integer) 1 # 移除 0 至 1 区间内的成员 redis> ZREMRANGEBYRANK salary 0 1 (integer) 2 # 有序集只剩下一个成员 redis> ZRANGE salary 0 -1 WITHSCORES 1) "tom" 2) "5000"
2.3.3 ZREMRANGEBYSCORE - 移除指定权重区间内的元素
ZREMRANGEBYSCORE key min max
移除有序集合key中,score值位于min和max(包含min和max)之间的元素。
复杂度、返回值:
- 时间复杂度:
O(log(N)+M),N是有序集合的基数,M为移除元素数量 - 返回值:被移除成员的数量
使用示例
# 有序集合内的所有成员及其 score 值 redis> ZRANGE salary 0 -1 WITHSCORES 1) "tom" 2) "2000" 3) "peter" 4) "3500" 5) "jack" 6) "5000" # 移除所有salary 在 1500 到 3500 内的员工 redis> ZREMRANGEBYSCORE salary 1500 3500 (integer) 2 # 剩余的成员 redis> ZRANGE salary 0 -1 WITHSCORES 1) "jack" 2) "5000"
2.4 交、并集计算
有序集合支持简单的聚合操作,可以使用ZUNIONSTORE命令计算多个有序集合的并集,或使用ZINTERSTORE命令计算多个有序集合的交集。
2.4.1 ZUNIONSTORE - 并集操作
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
计算一或多个有序集合的并集,并将结果存储到destination的score中。
参数
WEIGHTS- 乘法因子,所有有序集合值在传递聚合函数前,都要乘以该因子。默认值为1AGGREGATE- 指定结果集的聚合方式。默认使用SUM(求合)。可选值还有MIN(计算最小值)、MAX(计算最大值)
复杂度、返回值:
- 时间复杂度:
O(N)+O(M log(M)),N为有序集合的总数,M结果集的基数 - 返回值:保存到结果集
destination的基数
使用示例
redis> ZRANGE programmer 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" redis> ZRANGE manager 0 -1 WITHSCORES 1) "herry" 2) "2000" 3) "mary" 4) "3500" 5) "bob" 6) "4000" # 除 programmer 外,其它成员增加 salary redis> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 (integer) 6 redis> ZRANGE salary 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" 7) "herry" 8) "6000" 9) "mary" 10) "10500" 11) "bob" 12) "12000"
2.4.2 ZINTERSTORE - 交集操作
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
计算一或多个有序集合的交集,并将结果存储到destination的score中。
可选参数WEIGHTS、AGGREGATE与ZUNIONSTORE相同。
复杂度、返回值:
- 时间复杂度:
(N*K)+O(M*log(M)),N为指定有序集合中基数最小的有序集,M为指定有序集合的数量,M结果集的基数 - 返回值:保存到结果集
destination的基数
使用示例
redis > ZADD mid_test 70 "Li Lei" (integer) 1 redis > ZADD mid_test 70 "Han Meimei" (integer) 1 redis > ZADD mid_test 99.5 "Tom" (integer) 1 redis > ZADD fin_test 88 "Li Lei" (integer) 1 redis > ZADD fin_test 75 "Han Meimei" (integer) 1 redis > ZADD fin_test 99.5 "Tom" (integer) 1 # 保存交集 redis > ZINTERSTORE sum_point 2 mid_test fin_test (integer) 3 redis > ZRANGE sum_point 0 -1 WITHSCORES 1) "Han Meimei" 2) "145" 3) "Li Lei" 4) "158" 5) "Tom" 6) "199"
