Redis的有序集合(Sorted Set)使用

624 阅读8分钟

来自文章集合:一文带你搞懂redis使用过程(持续更新中)

有序集合(Sorted Set)

redis的有序集合(Sorted Set)是一个键值对集合,其中的值具有一个可以比较的分数(score)。有序集合的成员是唯一的,但分数可以重复。适用于需要按照某种顺序来存储和查找数据的场景。

场景

  • 排行榜:有序集合常用于实现排行榜功能,例如:根据分数排序用户的积分、排名等信息。
  • 范围查找:由于有序集合中的成员是有序的,可以根据分数分为来查找成员,例如查找一段时间内的活跃用户或热门商品。
  • 任务调度:可以使用有序集合来实现带有时间戳的任务调度,根据时间戳的顺序来执行任务
  • 实现消息排行:可以根据消息的重要程度或者热度来对消息进行排序,使得用户可以快速获取热门或者重要的消息
  • 有序集合的交集和并集运算:有序集合可以进行交集和并集的运算,可以用于实现共同好友、共同兴趣等功能。

用法示例

/*
 向有序集合中插入数据:zadd <key_name> [NX|XX] [CH] [INCR] <score1> <member1> [score2 member2...]
 -  NX:不更新已存在的成员,只添加新成员(有序集合不存在该成员时)
 -  XX:只更新已存在的成员,不添加新成员(有序集合存在该成员时)
 -  CH:参数表示要修改或添加成员的数量,即命令执行后被修改的成员数量(似乎不加也没有区别)
 -  INCR:对指定成员的分数进行递增操作。如果指定了`INCR`参数且成员存在,那么`ZADD`命令将执行的是对成员变量的分数进行递增操作,不存在则插入
*/
127.0.0.1:6379> zadd redis_sort_set_1 11 redis_d 12 redis_f 13 redis_g
(integer) 3
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
1) "redis_d"
2) "11"
3) "redis_f"
4) "12"
5) "redis_g"
6) "13"
//  XX:只更新已存在的成员,不添加新成员(有序集合存在该成员时)
127.0.0.1:6379> zadd redis_sort_set_1 XX 18 redis_d
(integer) 0
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
1) "redis_f"
2) "12"
3) "redis_g"
4) "13"
5) "redis_d"
6) "18"
127.0.0.1:6379> zadd redis_sort_set_1 XX 20 redis_a
(integer) 0
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
1) "redis_f"
2) "12"
3) "redis_g"
4) "13"
5) "redis_d"
6) "18"
//  NX:不更新已存在的成员,只添加新成员(有序集合不存在该成员时)
127.0.0.1:6379> zadd redis_sort_set_1 NX 18 redis_d
(integer) 0
127.0.0.1:6379> zadd redis_sort_set_1 NX 20 redis_a
(integer) 1

//  查询有序集合:ZRANGE <key_name> <start_index> <end_index> [WITHSCORES]
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
1) "redis_f"
2) "12"
3) "redis_g"
4) "13"
5) "redis_d"
6) "18"
7) "redis_a"
8) "20"


//  查询有序集合成员数目:ZCARD <key_name>
127.0.0.1:6379> zcard redis_sort_set_1
(integer) 4


//  查找有序集合指定区间的成员数目:ZCOUNT <key_name> <start_index> <end_index>
127.0.0.1:6379> zcount redis_sort_set_1 11 14
(integer) 2

//  对集合中的成员进行增减(成员不存在则插入):ZINCRBY <key_name> <increment> <member>
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
1) "redis_f"
2) "12"
3) "redis_g"
4) "13"
5) "redis_d"
6) "18"
7) "redis_a"
8) "20"
127.0.0.1:6379> ZINCRBY redis_sort_set_1 4 redis_d
"22"
127.0.0.1:6379> ZINCRBY redis_sort_set_1 3 redis_b
"3"
127.0.0.1:6379> ZINCRBY redis_sort_set_1 -1 redis_b
"2"
127.0.0.1:6379> ZRANGE redis_sort_set_1 0 -1 WITHSCORES
 1) "redis_b"
 2) "2"
 3) "redis_f"
 4) "12"
 5) "redis_g"
 6) "13"
 7) "redis_a"
 8) "20"
 9) "redis_d"
10) "22"


//  在redis集合中基于字典序列的成员范围内统计成员的数目。ZLEXCOUNT <key_name> <min> <max>
127.0.0.1:6379> ZLEXCOUNT final_test - +
(integer) 9
127.0.0.1:6379>  ZADD myzset 0 a 0 b 0 c 0 d 0 e
(integer) 5
127.0.0.1:6379> ZADD myzset 0 f 0 g
(integer) 2
127.0.0.1:6379>  ZLEXCOUNT myzset [b [f
(integer) 5

//  通过字典区间返回有序集合的成员:ZRANGEBYLEX <key_name> 
127.0.0.1:6379> ZRANGEBYLEX final_test - +
1) "Hello"
2) "Wu"
3) "Zhou"
4) "Zheng"
5) "Li"
6) "Wang"
7) "Chen"
8) "Que"
9) "Zhao"
127.0.0.1:6379> ZRANGEBYLEX final_test [A [ZZZZZ
1) "Hello"
2) "Wu"
127.0.0.1:6379> ZRANGEBYLEX final_test [A [zzzzz
1) "Hello"
2) "Wu"
3) "Zhou"
4) "Zheng"
5) "Li"
6) "Wang"
7) "Chen"
8) "Que"
9) "Zhao"

/*  
取指定多个有序集合的交集:ZINTERSTORE <key_name> <key_num> <key_1> [key_x...] [WEIGHTS weight [weight...]] [AGGREGATE SUM|MIN|MAX]
-   AGGREGATE SUM|MIN|MAX
    -   SUM:不指定,默认为SUM,找出指定 有序集合中的交集,并将 交集的数值 进行相加
    -   MIN:找出指定 有序集合中的交集,将 交集中的最小分数 赋给 交集中成员
    -   MAX:找出指定 有序集合中的交集,将 交集中的最大分数 赋给 交集中成员
-   WEIGHTS weight [weight]  weight的数目要和前面的key_num保持一致
    -   将对应key_name中的交集的分数进行倍增,在根据AGGREGATE的设置(默认为相加SUM)计算后赋给交集的分数
*/ 
127.0.0.1:6379> ZADD mid_test 70 "Li"
(integer) 1
127.0.0.1:6379> ZADD mid_test 75 "Wang" 100 "Chen" 150 "Que"
(integer) 3
127.0.0.1:6379> zrange mid_test 0 -1 WITHSCORES
1) "Li"
2) "70"
3) "Wang"
4) "75"
5) "Chen"
6) "100"
7) "Que"
8) "150"
127.0.0.1:6379> ZADD final_test 50 "Li" 70 "Wang" 100 "Chen" 150 "Que" 200 "Zhao"
(integer) 5
127.0.0.1:6379> zrange final_test 0 -1 WITHSCORES
 1) "Li"
 2) "50"
 3) "Wang"
 4) "70"
 5) "Chen"
 6) "100"
 7) "Que"
 8) "150"
 9) "ZHAO"
10) "200"
127.0.0.1:6379> ZINTERSTORE sum_point 2 mid_test final_test
(integer) 4
127.0.0.1:6379> ZRANGE sum_point 0 -1 WITHSCORES
1) "Li"
2) "120"
3) "Wang"
4) "145"
5) "Chen"
6) "200"
7) "Que"
8) "300"
127.0.0.1:6379> ZINTERSTORE min_point 2 mid_test final_test AGGREGATE MIN
(integer) 4
127.0.0.1:6379> ZRANGE min_point 0 -1 WITHSCORES
1) "Li"
2) "50"
3) "Wang"
4) "70"
5) "Chen"
6) "100"
7) "Que"
8) "150"


//  我们来测试一下WEIGHT weight的使用
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> ZADD mid_test 70 "Li" 75 "Wang" 100 "Chen" 150 "Que"
(integer) 4
127.0.0.1:6379> ZADD final_test 50 "Li" 70 "Wang" 100 "Chen" 150 "Que" 200 "Zhao"
(integer) 5
127.0.0.1:6379> ZRANGE mid_test 0 -1 WITHSCORES
1) "Li"
2) "70"
3) "Wang"
4) "75"
5) "Chen"
6) "100"
7) "Que"
8) "150"
127.0.0.1:6379> ZRANGE final_test 0 -1 WITHSCORES
 1) "Li"
 2) "50"
 3) "Wang"
 4) "70"
 5) "Chen"
 6) "100"
 7) "Que"
 8) "150"
 9) "Zhao"
10) "200"
127.0.0.1:6379> ZINTERSTORE weight_test 2 mid_test final_test WEIGHTS 2
(error) ERR syntax error
127.0.0.1:6379> ZINTERSTORE weight_test 2 mid_test final_test WEIGHTS 2 3
(integer) 4
127.0.0.1:6379> ZRANGE weight_test 0 -1 WITHSCORES
1) "Li"
2) "290"
3) "Wang"
4) "360"
5) "Chen"
6) "500"
7) "Que"
8) "750"

/*
取指定多个有序集合的交集:ZUNIONSTORE <key_name> <key_num> <key_1> [key_x...] [WEIGHTS weight [weight...]] [AGGREGATE SUM|MIN|MAX]
参数含义与使用方式同上
*/
127.0.0.1:6379> ZADD mid_test 70 "Li" 75 "Wang" 100 "Chen" 150 "Que"
(integer) 4
127.0.0.1:6379> ZADD final_test 50 "Li" 70 "Wang" 100 "Chen" 150 "Que" 200 "Zhao"
(integer) 5
127.0.0.1:6379> ZUNIONSTORE weight_test 2 mid_test final_test WEIGHTS 2 3
(integer) 5
127.0.0.1:6379> ZRANGE weight_test 0 -1 WITHSCORES
 1) "Li"
 2) "290"
 3) "Wang"
 4) "360"
 5) "Chen"
 6) "500"
 7) "Zhao"
 8) "600"
 9) "Que"
10) "750"

//  查询指定范围内分数:ZRANGEBYSCORE <key_name> <min> <max> [WITHSCORES]
127.0.0.1:6379> ZRANGEBYSCORE final_test 0 50 WITHSCORES
 1) "Hello"
 2) "10"
 3) "Wu"
 4) "20"
 5) "Zhou"
 6) "30"
 7) "Zheng"
 8) "40"
 9) "Li"
10) "50"
127.0.0.1:6379> ZRANGEBYSCORE final_test 0 (50 WITHSCORES
1) "Hello"
2) "10"
3) "Wu"
4) "20"
5) "Zhou"
6) "30"
7) "Zheng"
8) "40"
127.0.0.1:6379> ZRANGEBYSCORE final_test -inf +inf WITHSCORES
 1) "Hello"
 2) "10"
 3) "Wu"
 4) "20"
 5) "Zhou"
 6) "30"
 7) "Zheng"
 8) "40"
 9) "Li"
10) "50"
11) "Wang"
12) "70"
13) "Chen"
14) "100"
15) "Que"
16) "150"
17) "Zhao"
18) "200"
127.0.0.1:6379> ZRANGEBYSCORE final_test -inf 50 WITHSCORES
 1) "Hello"
 2) "10"
 3) "Wu"
 4) "20"
 5) "Zhou"
 6) "30"
 7) "Zheng"
 8) "40"
 9) "Li"
10) "50"
127.0.0.1:6379> ZRANGEBYSCORE final_test -inf 50 WITHSCORES LIMIT 1 3
1) "Wu"
2) "20"
3) "Zhou"
4) "30"
5) "Zheng"
6) "40"

//  查询指定成员在集合中的排名:ZRANK <key_name> <member>
127.0.0.1:6379> ZADD final_redis 10 a 20 b 30 c 40 d 50 f
(integer) 5
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "30"
 7) "d"
 8) "40"
 9) "f"
10) "50"
127.0.0.1:6379> ZRANK final_redis b
(integer) 1
127.0.0.1:6379> ZRANK final_redis c
(integer) 2

//  从集合中删除指定成员:ZREM <key_name> <member> [member...]
127.0.0.1:6379> ZREM final_redis a c f
(integer) 3
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
1) "b"
2) "20"
3) "d"
4) "40"

//  移除有序集合中给定的字典区间的所有成员:ZREMRANGEBYLEX <key_name> <min> <max>
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "d"
 6) "40"
 7) "f"
 8) "50"
 9) "h"
10) "100"
11) "j"
12) "150"
127.0.0.1:6379> ZREMRANGEBYLEX final_redis [a (f
(integer) 3
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
1) "f"
2) "50"
3) "h"
4) "100"
5) "j"
6) "150"

//  移除有序集合中给定的排名区间的所有成员:ZREMRANGEBYRANK <key_name> <min> <max>
127.0.0.1:6379> ZREMRANGEBYRANK final_redis 0 2
(integer) 3
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
(empty list or set)

//  移除有序集合中给定积分区间的所有成员:ZREMRANGEBYSCORE <key_name> <min> <max>
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
 1) "a"
 2) "10"
 3) "b"
 4) "20"
 5) "c"
 6) "39"
 7) "f"
 8) "50"
 9) "h"
10) "100"
11) "j"
12) "150"
127.0.0.1:6379> ZREMRANGEBYSCORE final_redis 0 49
(integer) 3
127.0.0.1:6379> ZRANGE final_redis 0 -1 WITHSCORES
1) "f"
2) "50"
3) "h"
4) "100"
5) "j"
6) "150"

//  以积分倒序的方式查询有序集合,相同积分按字典序的逆序排列:ZREVRANGE <key_name> <min> <max> [WITHSCORES]
27.0.0.1:6379> ZREVRANGE final_redis 0 -1 WITHSCORES
1) "j"
2) "150"
3) "h"
4) "100"
5) "f"
6) "50"

//  查询倒序有序集合中指定成员的排名:ZREVRANK <key_name> <member>
127.0.0.1:6379> ZREVRANK final_redis f
(integer) 2

//  查询有序集合中指定成员的积分:ZSCORE <key_name> <member>
127.0.0.1:6379> ZSCORE final_redis f
"50"