场景
监控key的操作(set、del、expire......)
监听key的过期,自动触发事件
方案
在 Redis 的 2.8.0 版本之后,其推出了一个新的特性——键空间消息(Redis Keyspace Notifications),它配合 2.0.0 版本之后的 SUBSCRIBE 或 PSUBSCRIBE 就能完成监控key操作和监听key过期。
(1)Publish / Subscribe
Redis 在 2.0.0 之后推出了 Pub / Sub 的指令,大致就是说一边给 Redis 的特定频道发送消息,另一边从 Redis 的特定频道取值——形成了一个简易的消息队列。
(2)Psubscribe 命令
Redis Psubscribe 命令订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等)。 news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类。
(3)Redis Keyspace Notifications
在 Redis 里面有一些事件,比如键到期、键被删除等。然后可以配置一些参数,来让 Redis 一旦触发这些事件的时候就往特定的 Channel 推一条消息。
Redis Keyspace Notifications有2种类型的消息:
Keyspace events:键空间频道的订阅者将接收到 key和 被执行的事件的名字
__keyspace@0__:mykey expire
Keyevent events:键事件频道的订阅者将接收到 被执行事件的键的名字和key
__keyevent@0__:expire mykey
Keyevent events 和 Keyevent events 最大的不同,Keyevent events 能主动接收到 key 过期消息
例如:
127.0.0.1:6379> expire mykey 5 Keyspace events 和 Keyevent events 同时收到 expire 操作消息 __keyspace@0__:mykey expire __keyevent@0__:expire mykey 但是在5秒后,只有键事件频道的订阅者,才能自动收到 key 过期事件 __keyevent@0__:expire mykey
配置说明
redis.conf配置文件中有详细说明
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
# K Keyspace events, published with __keyspace@<db>__ prefix.
# E Keyevent events, published with __keyevent@<db>__ prefix.
# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
# $ String commands
# l List commands
# s Set commands
# h Hash commands
# z Sorted set commands
# x Expired events (events generated every time a key expires)
# e Evicted events (events generated when a key is evicted for maxmemory)
# A Alias for g$lshzxe, so that the "AKE" string means all the events.
#
# The "notify-keyspace-events" takes as argument a string that is composed
# of zero or multiple characters. The empty string means that notifications
# are disabled.
#
# Example: to enable list and generic events, from the point of view of the
# event name, use:
#
# notify-keyspace-events Elg
#
# Example 2: to get the stream of the expired keys subscribing to channel
# name __keyevent@0__:expired use:
#
# notify-keyspace-events Ex
#
# By default all notifications are disabled because most users don't need
# this feature and the feature has some overhead. Note that if you don't
# specify at least one of K or E, no events will be delivered.
翻译:
1)notify-keyspace-events选项的参数为空字符串时,表示功能关闭,当参数不是空字符串时,表示功能开启
2)notify-keyspace-events默功能是关闭的
3)如果要使用此功能,必须字符串包含 K 或者 E,否则收不到任何事件消息
4)如果参数为“AKE”,意味着接收所有事件消息
notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知:
字符
发送的通知
K
键空间通知,所有通知以 __keyspace@<db>__ 为前缀
E
键事件通知,所有通知以 __keyevent@<db>__ 为前缀
g
DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知
$
字符串命令的通知
l
列表命令的通知
s
集合命令的通知
h
哈希命令的通知
z
有序集合命令的通知
x
过期事件:每当有过期键被删除时发送
e
驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送
A
参数 g$lshzxe 的别名
举例说明(1)
1)需求
监听key的各种操作
2)启用功能
redis.conf 配置如下内容
notify-keyspace-events "AKE"
3)监听操作 subscribe
同时监听 set、get、del 、 expire 操作
127.0.0.1:6379> subscribe __keyevent@0__:set __keyevent@0__:get __keyevent@0__:del __keyevent@0__:expire
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__keyevent@0__:set"
3) (integer) 1
1) "subscribe"
2) "__keyevent@0__:get"
3) (integer) 2
1) "subscribe"
2) "__keyevent@0__:del"
3) (integer) 3
1) "subscribe"
2) "__keyevent@0__:expire"
3) (integer) 4
4)String类型key操作
127.0.0.1:6379> set chy 111
OK
127.0.0.1:6379> get chy
"111"
127.0.0.1:6379> del chy
(integer) 1
127.0.0.1:6379> set chy 222
OK
127.0.0.1:6379> expire chy 5
(integer) 1
127.0.0.1:6379> get chy
(nil)
5)监听结果
1) "message"
2) "__keyevent@0__:set"
3) "chy"
1) "message"
2) "__keyevent@0__:del"
3) "chy"
1) "message"
2) "__keyevent@0__:set"
3) "chy"
1) "message"
2) "__keyevent@0__:expire"
3) "chy"
6)结论
get 操作监听不到消息,set,del ,expire 如果操作成功可以监听到消息,如果操作失败也监听不到消息
举例说明(2)
1)需求
当具体的key过期时,自动监听到过期消息
2)启用功能
redis.conf 配置如下内容
notify-keyspace-events "AKE"
3)监听操作 subscribe
假设redis key是mykey
127.0.0.1:6379> subscribe __keyspace@0__:mykey
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__keyspace@0__:mykey"
3) (integer) 1
4) key操作
127.0.0.1:6379> set mykey 11
OK
127.0.0.1:6379> expire mykey 10
(integer) 1
5) 监听消息
1) "message"
2) "__keyspace@0__:mykey"
3) "set"
1) "message"
2) "__keyspace@0__:mykey"
3) "expire"
/* 备注10秒以后,底层系统删除key后,自动获取过期消息 */
1) "message"
2) "__keyspace@0__:mykey"
3) "expired"
过期通知的发送时间
Redis使用以下两种方式删除过期的键:
- 当一个键被访问时,程序会对这个键进行检查,如果键已经过期,那么该键将被删除。
- 底层系统会在后台渐进地查找并删除那些过期的键,从而处理那些已经过期、但是不会被访问到的键。
举例说明3
1)需求
订阅所有key的所有操作消息
订阅所有key的自动过期消息
备注:要用到模式匹配(psubscribe)和同时订阅两种消息类型(keyspace和keyevent)
2)启用功能
redis.conf 配置如下内容
notify-keyspace-events "AKE"
3)监听操作 psubscribe
127.0.0.1:6379> psubscribe __key*@0__:*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__key*@0__:*"
3) (integer) 1
4)任意key操作
127.0.0.1:6379> set chy 1111
OK
127.0.0.1:6379> expire chy 10
(integer) 1
127.0.0.1:6379> set mykey 222
OK
127.0.0.1:6379> expire mykey 5
(integer) 1
5) 监听消息
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:chy"
4) "set"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:set"
4) "chy"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:chy"
4) "expire"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:expire"
4) "chy"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:chy"
4) "expired"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:expired"
4) "chy"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:mykey"
4) "set"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:set"
4) "mykey"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:mykey"
4) "expire"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:expire"
4) "mykey"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyspace@0__:mykey"
4) "expired"
1) "pmessage"
2) "__key*@0__:*"
3) "__keyevent@0__:expired"
4) "mykey"