Redis 集合排序

排序主要针对的是集合操做,即List、Set、ZSet这三种集合。
排序操做主要依赖于以下几个命令
sort、by、get、limitcss

排序使用建议:
(1).对较大数据量进行排序会影响性能
(2).如必须对大数据量排序,建议使用Store参数来缓存结果
(3).尽可能使用limit限制获取的数据量mysql

集合排序

返回或保存给定列表、集合、有序集合 key 中通过排序的元素,默认是升序web

语法:redis

sort key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]

1.通常sort排序

127.0.0.1:6379> lpush intlist 9 0 78 98 2 34 1 8
(integer) 8
127.0.0.1:6379> lrange intlist 0 -1
1) "8"
2) "1"
3) "34"
4) "2"
5) "98"
6) "78"
7) "0"
8) "9"
127.0.0.1:6379> sort intlist    # 升序
1) "0"
2) "1"
3) "2"
4) "8"
5) "9"
6) "34"
7) "78"
8) "98"
127.0.0.1:6379> sort intlist desc   # 降序
1) "98"
2) "78"
3) "34"
4) "9"
5) "8"
6) "2"
7) "1"
8) "0"

2.使用 ALPHA 修饰符对字符串进行排序

127.0.0.1:6379> lpush stringlist “oracle” “mysql” “sqlserver” “redis” “mongodb”
(integer) 5
127.0.0.1:6379> lrange stringlist 0 -1
1) “mongodb”
2) “redis”
3) “sqlserver”
4) “mysql”
5) “oracle”
127.0.0.1:6379> sort stringlist alpha
1) “mongodb”
2) “mysql”
3) “oracle”
4) “redis”
5) “sqlserver”
127.0.0.1:6379> sort stringlist alpha desc
1) “sqlserver”
2) “redis”
3) “oracle”
4) “mysql”
5) “mongodb”sql

3.使用 limit 修饰符限制返回结果

排序以后返回元素的数量能够经过 LIMIT 修饰符进行限制, 修饰符接受 offset 和 count 两个参数:
● offset 指定要跳过的元素数量。
● count 指定跳过 offset 个指定的元素以后,要返回多少个对象。mongodb

127.0.0.1:6379> sort stringlist alpha 
1) "mongodb"
2) "mysql"
3) "oracle"
4) "redis"
5) "sqlserver"
127.0.0.1:6379> sort stringlist alpha limit 1 3
1) "mysql"
2) "oracle"
3) "redis"
127.0.0.1:6379> sort stringlist alpha limit 2 3
1) "oracle"
2) "redis"
3) "sqlserver"

4.使用外部 key 进行排序

可使用外部 key 的数据做为权重,代替默认的直接对比键值的方式来进行排序数据库

假设用户信息表中有以下数据缓存

uid user_name_{udi} user_level_{uid}
1 admin 9999
2 jack 10
3 peter 25
4 mary 70

将上面的数据输入到Redis中oracle

# admin
127.0.0.1:6379> lpush uid 1
(integer) 1
127.0.0.1:6379> set user_name_1 admin
OK
127.0.0.1:6379> set user_level_1 9999
OK

# jack
127.0.0.1:6379> lpush uid 2
(integer) 2
127.0.0.1:6379> set user_name_2 jack
OK
127.0.0.1:6379> set user_level_2 10
OK

# peter
127.0.0.1:6379> lpush uid 3
(integer) 3
127.0.0.1:6379> set user_name_3 peter
OK
127.0.0.1:6379> set user_level_3 25
OK

# tom
127.0.0.1:6379> lpush uid 4
(integer) 1
127.0.0.1:6379> set user_name_4 mary
OK
127.0.0.1:6379> set user_level_4 70
OK
  • by选项

默认状况下sort uid,直接按照uid的值进行排序svg

127.0.0.1:6379> sort uid 
1) "1"
2) "2"
3) "3"
4) "4"

使用by选项,让uid键按照user_level_{uid}的值大小来排序

127.0.0.1:6379> sort uid by user_level_*
1) "2"
2) "3"
3) "4"
4) "1"

user_level_* 是一个占位符, 它先取出 uid 中的值, 而后再用这个值来查找相应的键好比在对 uid 列表进行排序时, 程序就会先取出 uid 的值 1 、 2 、 3 、 4 , 而后使用 user_level_1 、 user_level_2 、 user_level_3 和 user_level_4 的值做为排序 uid 的权重

  • get 选项

使用 GET 选项, 能够根据排序的结果来取出相应的键值
好比:先排序 uid , 再取出键 user_name_{uid} 的值

127.0.0.1:6379> sort uid get user_name_*
1) "admin"
2) "jack"
3) "peter"
4) "mary"
  • 组合使用 by 和 get 选项

经过组合使用 BY 和 GET , 可让排序结果以更直观的方式显示出来
好比:先按 user_level_{uid} 来排序 uid 列表, 再取出相应的 user_name_{uid} 的值

127.0.0.1:6379> sort uid by user_level_* get user_name_*
1) "jack"
2) "peter"
3) "mary"
4) "admin"

能够同时使用多个 GET 选项, 获取多个外部键的值,同时获取user_name_{uid} 和 user_level_{uid}

127.0.0.1:6379> sort uid by user_level_* get user_name_* get user_level_*
1) "jack"
2) "10"
3) "peter"
4) "25"
5) "mary"
6) "70"
7) "admin"
8) "9999"

GET 有一个额外的参数规则,那就是 —— 能够用 # 获取被排序键的值
好比:将 uid 的值、及其相应的 user_level_* 和 user_name_* 都返回

127.0.0.1:6379> sort uid get # get user_level_* get user_name_*
 1) "1"
 2) "9999"
 3) "admin"
 4) "2"
 5) "10"
 6) "jack"
 7) "3"
 8) "25"
 9) "peter"
10) "4"
11) "70"
12) "mary"

5.获取外部键,但不进行排序

经过将一个不存在的键做为参数传给 BY 选项, 可让 SORT 跳过排序操做, 直接返回结果

127.0.0.1:6379> lrange uid 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> sort uid by not-exists-key
1) "4"
2) "3"
3) "2"
4) "1"

上面的用法在单独使用时,没什么实际用处。不过,经过将这种用法和 GET 选项配合, 就能够在不排序的状况下, 获取多个外部键, 至关于执行一个整合的获取操做(相似于 SQL 数据库的 join 关键字)。

好比:在不引发排序的状况下,使用 SORT 、 BY 和 GET 获取多个外部键(user_level_{uid}和user_name_{uid})

127.0.0.1:6379> sort uid by not-exists-key get # get user_level_* get user_name_*
 1) "4"
 2) "70"
 3) "mary"
 4) "3"
 5) "25"
 6) "peter"
 7) "2"
 8) "10"
 9) "jack"
10) "1"
11) "9999"
12) "admin"

6.将哈希表做为 GET 或 BY 的参数

除了字符串键以外, 哈希表也能够做为 GET 或 BY 选项的参数来使用。
仍然使用上述的用户信息表,将用户的名字和级别保存在 user_name_{uid} 和 user_level_{uid} 两个字符串键中(用一个带有 name 域和 level 域的哈希表 user_info_{uid} 来保存用户的名字和级别信息)

127.0.0.1:6379> hmset user_info_1 name admin level 9999
OK
127.0.0.1:6379> hmset user_info_2 name jack level 10
OK
127.0.0.1:6379> hmset user_info_3 name peter level 25
OK
127.0.0.1:6379> hmset user_info_4 name mary level 70
OK

而后, BY 和 GET 选项均可以用 key->field 的格式来获取哈希表中的域的值, 其中 key 表示哈希表键, 而 field 则表示哈希表的域

127.0.0.1:6379> sort uid by user_info_*->level
1) "2"
2) "3"
3) "4"
4) "1"
127.0.0.1:6379> sort uid by user_info_*->level get user_info_*->name
1) "jack"
2) "peter"
3) "mary"
4) "admin"

一样能够同时使用多个 GET 选项, 获取多个外部键的值,同时获取user_name_{uid} 和 user_level_{uid}

127.0.0.1:6379> sort uid by user_info_*->level get user_info_*->level get user_info_*->name
1) "10"
2) "jack"
3) "25"
4) "peter"
5) "70"
6) "mary"
7) "9999"
8) "admin"

默认升序,咱们也能够倒序

127.0.0.1:6379> sort uid desc by user_info_*->level get user_info_*->level get user_info_*->name
1) "9999"
2) "admin"
3) "70"
4) "mary"
5) "25"
6) "peter"
7) "10"
8) "jack"

7.保存排序结果

默认状况下, SORT 操做只是简单地返回排序结果,并不进行任何保存操做。
经过给 STORE 选项指定一个 key 参数,能够将排序结果保存到给定的键上。
若是被指定的 key 已存在,那么原有的值将被排序结果覆盖。

# 测试数据
127.0.0.1:6379> rpush numbers 1 3 5 7 9
(integer) 5
127.0.0.1:6379> rpush numbers 2 4 6 8 10
(integer) 10
127.0.0.1:6379> lrange numbers 0 -1
 1) "1"
 2) "3"
 3) "5"
 4) "7"
 5) "9"
 6) "2"
 7) "4"
 8) "6"
 9) "8"
10) "10"
# 排序并保存排序后的结果
127.0.0.1:6379> sort numbers store sorted-numbers
(integer) 10
127.0.0.1:6379> lrange sorted-numbers 0 -1
 1) "1"
 2) "2"
 3) "3"
 4) "4"
 5) "5"
 6) "6"
 7) "7"
 8) "8"
 9) "9"
10) "10"

能够经过将 SORT 命令的执行结果保存,并用 EXPIRE 为结果设置生存时间,以此来产生一个 SORT 操做的结果缓存。

这样就能够避免对 SORT 操做的频繁调用:只有当结果集过时时,才须要再调用一次 SORT 操做。

另外,为了正确实现这一用法,可能须要加锁以免多个客户端同时进行缓存重建(也就是多个客户端,同一时间进行 SORT 操做,并保存为结果集),具体参见 SETNX 命令。