排序
可以通过SORT命令对集合、列表、有序集合进行排序。其中,对有序集合进行排序时是以元素本身为准的(忽略分数)。
127.0.0.1:6379> SADD tag:ruby:posts 2 6 12 26
(integer) 4
127.0.0.1:6379> SORT tag:ruby:posts
1) "2"
2) "6"
3) "12"
4) "26"
127.0.0.1:6379> LPUSH list 4 5 2 3 8
(integer) 5
127.0.0.1:6379> SORT list
1) "2"
2) "3"
3) "4"
4) "5"
5) "8"
127.0.0.1:6379> ZADD zset 50 2 100 3 87 1
(integer) 3
127.0.0.1:6379> SORT zset
1) "1"
2) "2"
3) "3"
还可以给SORT添加ALPHA参数实现字典序排序。
127.0.0.1:6379> LPUSH charlist a b d e c f
(integer) 6
127.0.0.1:6379> SORT charlist
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> SORT charlist ALPHA
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
DESC参数指定按照逆序排序。LIMIT offset count参数用于选取返回结果范围。
127.0.0.1:6379> SORT tag:ruby:posts DESC
1) "26"
2) "12"
3) "6"
4) "2"
127.0.0.1:6379> SORT tag:ruby:posts DESC LIMIT 0 1
1) "26"
127.0.0.1:6379> SORT tag:ruby:posts DESC LIMIT 0 2
1) "26"
2) "12"
BY参数用于选定排序的基准参考值。
127.0.0.1:6379> HSET post:2 time 1000
(integer) 1
127.0.0.1:6379> HSET post:6 time 900
(integer) 1
127.0.0.1:6379> HSET post:12 time 1900
(integer) 1
127.0.0.1:6379> HSET post:26 time 100
(integer) 1
127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC
1) "12"
2) "2"
3) "6"
4) "26"
其中,Redis会自动用SORT后的元素值替换BY参数中的*值。
当BY参数中不包含*值时,排序操作不会进行。
127.0.0.1:6379> LPUSH sortbylist 2 1 3
(integer) 3
127.0.0.1:6379> SET itemscore:1 50
OK
127.0.0.1:6379> SET itemscore:2 100
OK
127.0.0.1:6379> SET itemscore:3 -10
OK
127.0.0.1:6379> SORT sortbylist BY itemscore:* DESC
1) "2"
2) "1"
3) "3"
127.0.0.1:6379> SORT sortbylist BY any
1) "3"
2) "1"
3) "2"
SORT语句中可以增加GET参数,用于替换排序返回的结果。
127.0.0.1:6379> HSET post:2 title redis
(integer) 1
127.0.0.1:6379> HSET post:6 title python
(integer) 1
127.0.0.1:6379> HSET post:12 title linux
(integer) 1
127.0.0.1:6379> HSET post:26 title libuv
(integer) 1
127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title
1) "linux"
2) "redis"
3) "python"
4) "libuv"
SORT语句可以有多个GET参数,将一并返回。原始的SORT返回结果可以用GET #。
127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title GET post:*->time GET #
1) "linux"
2) "1900"
3) "12"
4) "redis"
5) "1000"
6) "2"
7) "python"
8) "900"
9) "6"
10) "libuv"
11) "100"
12) "26"
STORE参数可以将排序后的结果保存到一个键中,保存结果为列表类型。
127.0.0.1:6379> SORT tag:ruby:posts BY post:*->time DESC GET post:*->title GET post:*->time GET # STORE sort.result
(integer) 12
127.0.0.1:6379> LRANGE sort.result 0 -1
1) "linux"
2) "1900"
3) "12"
4) "redis"
5) "1000"
6) "2"
7) "python"
8) "900"
9) "6"
10) "libuv"
11) "100"
12) "26"
消息通知
Redis中,可以通过LPUSH/RPOP操作实现一个简单的消息队列。生产者不断的LPUSH消息到队列中,而消费者则不断的从队列中RPOP消息。
127.0.0.1:6379> LPUSH queue 1 2 3
(integer) 3
127.0.0.1:6379> RPOP queue
1) "queue"
2) "1"
127.0.0.1:6379> RPOP queue
1) "queue"
2) "2"
127.0.0.1:6379> RPOP queue
1) "queue"
2) "3"
Redis还提供了一个BRPOP操作,它有两个参数,一个是键值,一个是超时时间。超时时间填0时,如果队列中是空的,那么BRPOP将一直阻塞知道队列中有值。
127.0.0.1:6379> BRPOP queue 0
# another redis-client begin
127.0.0.1:6379> LPUSH queue 4
# another redis-client end
(integer) 1
1) "queue"
2) "4"
(5.34s)
BRPOP还可以同时接受多个键,任何一个键中有值,那么BRPOP就返回。多个键中均有值,则按照从左到右的优先级返回。
127.0.0.1:6379> BRPOP queue queue2 0
# another redis-client begin
127.0.0.1:6379> LPUSH queue2 5
# another redis-client end
(integer) 1
1) "queue2"
2) "5"
(6.01s)
Redis还提供了发布/订阅模式用于进程间消息传递。
# client A
127.0.0.1:6379> PUBLISH channel.1 hi
(integer) 0
127.0.0.1:6379> SUBSCRIBE channel.1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.1"
3) (integer) 1
# client B
127.0.0.1:6379> PUBLISH channel.1 hello
(integer) 1
# client A
1) "message"
2) "channel.1"
3) "hello"
此外,更复杂一些,可以通过PSUBSCRIBE按照规则订阅,支持通配符匹配。
# client A
127.0.0.1:6379> PSUBSCRIBE channel.?*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel.?*"
3) (integer) 1
# client B
127.0.0.1:6379> PUBLISH channel.10 hello
(integer) 1
127.0.0.1:6379> PUBLISH channel.12 hello
(integer) 1
# client A
1) "pmessage"
2) "channel.?*"
3) "channel.10"
4) "hello"
1) "pmessage"
2) "channel.?*"
3) "channel.12"
4) "hello"
节省空间
下面有一些节省存储空间的小建议:
- 精简键名
- 内部编码优化(由redis自动选择,可以通过 OBJECT ENCODING car查看)
- 当数据量较小时,采用牺牲一定速度的方式来减少内存用量;数据量变大后,则优先保证存取速度;