接上章:Redis入门指南 --day004
实现缓存
- 具体的设置方法为:修改配置文件的maxmemory参数,限制Redis最大可用内存大小(单位是字节),当超出了这个限制时Redis会依据maxmemory-policy参数指定的策略来删除不需要的键直到Redis占用的内存小于指定内存。
- maxmemory-policy支持的规则如表4-1所示。其中的LRU (Least Recently Used)算法即“最近最少使用”,其认为最近最少使用的键在未来一段时间内也不会被用到,即当需要空间时这些键是可以被删除的。
排序 sort
127.0.0.1:6379> lpush list1 2 5 12 9 4 8
(integer) 6
127.0.0.1:6379> lraNGE list1 0 -1
1) "8"
2) "4"
3) "9"
4) "12"
5) "5"
6) "2"
127.0.0.1:6379> sort list1
1) "2"
2) "4"
3) "5"
4) "8"
5) "9"
6) "12"
# 在对有序集合类型排序时会忽略元素的分数,只针对元素自身的值进行排序。
127.0.0.1:6379> zadd myzset 100 1 88 2 32 10 85 8 73 4
(integer) 5
127.0.0.1:6379> sort myzset
1) "1"
2) "2"
3) "4"
4) "8"
5) "10"
# 非数字排序 添加 alpha 关键字
127.0.0.1:6379> lpush list2 b g h s e
(integer) 5
127.0.0.1:6379> sort list2
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> sort list2 alpha
1) "b"
2) "e"
3) "g"
4) "h"
5) "s"
# sort 还支持分页 和数据库一样
127.0.0.1:6379> sort list1
1) "2"
2) "4"
3) "5"
4) "8"
5) "9"
6) "12"
127.0.0.1:6379> sort list1 limit 2 2
1) "5"
2) "8"
BY参数的语法为BY参考键。其中参考键可以是字符串类型键或者是散列类型键的某个字段(表示为键名>字段名)。如果提供了BY 参数,SORT 命令将不再依据元素自身的直进行排序,而是对每个元素使用元素的值替换参考键中的第一个“*”并获取其值,然后依据该值对元素排序。就像这样:
127.0.0.1:6379> lpush list3 3 1 2
(integer) 3
127.0.0.1:6379> set iscore:1 50
OK
127.0.0.1:6379> set iscore:2 100
OK
127.0.0.1:6379> set iscore:3 80
OK
127.0.0.1:6379> sort list3 by iscore:* desc
1) "2"
2) "3"
3) "1"
# 示例中元素"4"的参考键iscore:4的值和元素"3"的参考键iscore:3的值都是80,所以 sORT命令会
# 再比较"4"和"3"元素本身的大小来决定二者的顺序。
127.0.0.1:6379> lpush list3 4
(integer) 4
127.0.0.1:6379> set iscore:4 80
OK
127.0.0.1:6379> sort list3 by iscore:* desc
1) "2"
2) "4"
3) "3"
4) "1"
# 当参考键不存在时 默认为0
127.0.0.1:6379> lpush list3 5
(integer) 5
127.0.0.1:6379> sort list3 by iscore:* desc
1) "2"
2) "4"
3) "3"
4) "1"
5) "5"
开发中使用SORT命令时需要注意以下几点。
(1)尽可能减少待排序键中元素的数量(使N尽可能小)。
(2)使用LIMIT参数只获取需要的数据(使M尽可能小)。
(3)如果要排序的数据数量较大,尽可能使用STORE参数将结果缓存。
store 参数 将结果缓存
任务队列
- 说到队列很自然就能想到Redis的列表类型,使用LPUSH和RPOP命令实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断地使用RPOP命令从该键中取出任务即可。
- 当任务队列中没有任务时消费者每秒都会调用一次RPOP命令查看是否有新任务。如果可以实现一旦有新任务加入任务队列就通知消费者就好了。其实借助 BRPOP命令就可以实现这样的需求。BRPOP命令和RPOP命令相似,唯一的区别是当列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新元素加入。
- BRPOP命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间仍然没有获得新元素的话就会返回nil。上例中超时时间为"0",表示不限制等待的时间,即如果没有新元素加入列表就会永远阻塞下去。
- 当获得一个元素后 BRPOP命令返回两个值,分别是键名和元素值。为了测试 BRPOP命令,我们可以打开两个 redis-cli 实例
- BRPOP key [key…] timeout
# 打开客户端 A 输入指令 则会一直等下去 阻塞
127.0.0.1:6379> brpop myqueue 0
# 另外打开一个新的客户端 B
127.0.0.1:6379> lpush myqueue 1
(integer) 1
127.0.0.1:6379> llen myqueue
(integer) 0
# A 客户端会立马返回数据 且数据已被取走
127.0.0.1:6379> brpop myqueue 0
1) "myqueue"
2) "1"
(66.99s)
优先级队列
# 我们现在 B 客户端插入 数据
127.0.0.1:6379> lpush mq1 11
(integer) 1
127.0.0.1:6379> lpush mq2 12
(integer) 1
127.0.0.1:6379> lpush mq3 13
(integer) 1
# 然后再在A 客户端 执行命令 只返回 mq1 的数据 我们可以利用这个特性 将 优先处理的队列放在 第一位
127.0.0.1:6379> brpop mq1 mq2 mq3 0
1) "mq1"
2) "11"
发布/ 订阅
PUBLISH channel messag 发布消息
SUBSCRIBE channel 订阅频道
UNSUBSCRIBE [channel] 取消订阅 如果没有 channel 参数 则代表取消全部
# 客户端A 订阅频道 ch1 返回值 subscribe 表示订阅成功的反馈信息。第二个值是订阅成功的频道名称,
# 第三个值是当前客户端订阅的频道数量。
127.0.0.1:6379> subscribe ch1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ch1"
3) (integer) 1
# 客户端 B 发布消息
127.0.0.1:6379> publish ch1 hello
(integer) 1
# 客户端 A 接收到消息
127.0.0.1:6379> subscribe ch1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ch1"
3) (integer) 1
1) "message"
2) "ch1"
3) "hello"
127.0.0.1:6379> unsubscribe ch1
1) "unsubscribe"
2) "ch1"
3) (integer) 0
按照规则订阅
# 订阅 以ch 开头的频道 不包含 ch
127.0.0.1:6379> psubscribe ch?*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ch?*"
3) (integer) 1
# 发布消息
127.0.0.1:6379> publish ch1 1111111
(integer) 1
127.0.0.1:6379> publish ch2 2222222
(integer) 1
127.0.0.1:6379> publish ch 00000
(integer) 0
# 接收到消息
127.0.0.1:6379> psubscribe ch?*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ch?*"
3) (integer) 1
1) "pmessage"
2) "ch?*"
3) "ch1"
4) "1111111"
1) "pmessage"
2) "ch?*"
3) "ch2"
4) "2222222"