Redis 键空间通知
实时监控Redis键和值的变化
Keyspace 通知允许客户端订阅 Pub/Sub 频道,以便接收以某种方式影响 Redis 数据集的事件。
可以接收到的事件示例包括:
- 所有影响给定键的命令。
- 所有接收到LPUSH操作的键。
- 数据库中所有键在0号数据库中过期。
注意:Redis Pub/Sub 是即发即弃的;也就是说,如果你的 Pub/Sub 客户端断开连接,稍后重新连接,客户端断开期间传递的所有事件都将丢失。
事件类型
键空间通知通过为每个影响Redis数据空间的操作发送两种不同类型的事件来实现。例如,针对数据库0
中名为mykey
的键的DEL
操作将触发两条消息的传递,完全等同于以下两条PUBLISH
命令:
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
第一个频道监听所有针对键mykey
的事件,而另一个频道仅监听键mykey
上的del
操作事件。
第一种事件,在通道中带有keyspace
前缀的称为
键空间通知,而第二种,带有keyevent
前缀的,
称为键事件通知。
在前面的例子中,为键mykey
生成了一个del
事件,导致了两条消息:
- Key-space 通道接收事件名称作为消息。
- 键事件通道接收的消息是键的名称。
可以仅启用一种通知类型,以便仅传递我们感兴趣的事件子集。
配置
默认情况下,键空间事件通知是禁用的,因为尽管不是非常敏感,该功能会消耗一些CPU资源。可以通过redis.conf中的notify-keyspace-events
或使用CONFIG SET命令来启用通知。
将参数设置为空字符串将禁用通知。 为了启用该功能,使用一个非空字符串,由多个字符组成,其中每个字符根据下表具有特殊含义:
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
t Stream commands
d Module key type events
x Expired events (events generated every time a key expires)
e Evicted events (events generated when a key is evicted for maxmemory)
m Key miss events (events generated when a key that doesn't exist is accessed)
n New key events (Note: not included in the 'A' class)
A Alias for "g$lshztxed", so that the "AKE" string means all the events except "m" and "n".
字符串中至少应存在K
或E
,否则无论字符串的其余部分如何,都不会传递任何事件。
例如,要仅为列表启用键空间事件,配置参数必须设置为 Kl
,依此类推。
你可以使用字符串 KEA
来启用大多数类型的事件。
不同命令生成的事件
不同的命令根据以下列表生成不同类型的事件。
APPEND
生成一个append
事件。COPY
生成一个copy_to
事件。DEL
为每个删除的键生成一个del
事件。EXPIRE
及其所有变体(PEXPIRE
,EXPIREAT
,PEXPIREAT
)在调用时如果设置了正数的超时时间(或将来的时间戳),则会生成一个expire
事件。请注意,当这些命令使用负数的超时值或过去的时间戳调用时,键将被删除,并且只会生成一个del
事件。HDEL
生成一个单一的hdel
事件,如果生成的哈希为空并且键被移除,则还会生成一个额外的del
事件。HEXPIRE
及其所有变体(HEXPIREAT
,HPEXPIRE
,HPEXPIREAT
)生成hexpire
事件。此外,当字段过期时,会生成hexpired
事件。HINCRBYFLOAT
生成一个hincrbyfloat
事件。HINCRBY
生成一个hincrby
事件。HPERSIST
生成一个hpersist
事件。HSET
,HSETNX
和HMSET
都会生成一个单一的hset
事件。INCRBYFLOAT
生成一个incrbyfloat
事件。INCR
,DECR
,INCRBY
,DECRBY
命令都会生成incrby
事件。LINSERT
生成一个linsert
事件。LMOVE
和BLMOVE
生成一个lpop
/rpop
事件(取决于 wherefrom 参数)和一个lpush
/rpush
事件(取决于 whereto 参数)。在这两种情况下,顺序是保证的(lpush
/rpush
事件总是在lpop
/rpop
事件之后传递)。此外,如果结果列表长度为零并且键被删除,则会生成一个del
事件。LPOP
生成一个lpop
事件。此外,如果由于弹出列表中的最后一个元素而删除了键,则会生成一个del
事件。LPUSH
和LPUSHX
生成一个单一的lpush
事件,即使在可变参数的情况下也是如此。LREM
生成一个lrem
事件,如果结果列表为空并且键被移除,则还会生成一个del
事件。LSET
生成一个lset
事件。LTRIM
生成一个ltrim
事件,如果结果列表为空并且键被删除,则还会生成一个del
事件。MIGRATE
如果源键被移除,则生成一个del
事件。MOVE
生成两个事件,一个是源键的move_from
事件,另一个是目标键的move_to
事件。MSET
为每个键生成一个单独的set
事件。PERSIST
如果与键关联的过期时间已成功删除,则生成一个persist
事件。RENAME
生成两个事件,一个是源键的rename_from
事件,另一个是目标键的rename_to
事件。RESTORE
为键生成一个restore
事件。RPOPLPUSH
和BRPOPLPUSH
生成一个rpop
事件和一个lpush
事件。在这两种情况下,顺序是保证的(lpush
事件总是在rpop
事件之后传递)。此外,如果结果列表长度为零并且键被删除,则会生成一个del
事件。RPOP
生成一个rpop
事件。此外,如果由于弹出列表中的最后一个元素而导致键被删除,则会生成一个del
事件。RPUSH
和RPUSHX
即使在可变参数情况下也会生成单个rpush
事件。SADD
生成一个单一的sadd
事件,即使在可变参数的情况下也是如此。SETRANGE
生成一个setrange
事件。SET
及其所有变体(SETEX
,SETNX
,GETSET
)会生成set
事件。然而SETEX
还会生成一个expire
事件。SINTERSTORE
,SUNIONSTORE
,SDIFFSTORE
分别生成sinterstore
,sunionstore
,sdiffstore
事件。在特殊情况下,如果结果集为空,并且存储结果的键已经存在,则会生成一个del
事件,因为该键被移除。SMOVE
为源键生成一个srem
事件,为目标键生成一个sadd
事件。SORT
在使用STORE
设置新键时生成一个sortstore
事件。如果生成的列表为空,并且使用了STORE
选项,并且已经存在一个同名的键,结果是该键被删除,因此在这种情况下会生成一个del
事件。SPOP
生成一个spop
事件,如果结果集为空并且键被移除,则还会生成一个额外的del
事件。SREM
生成一个单一的srem
事件,如果结果集为空并且键被移除,则还会生成一个额外的del
事件。XADD
生成一个xadd
事件,当与MAXLEN
子命令一起使用时,可能会跟随一个xtrim
事件。XDEL
即使删除多个条目,也只会生成一个xdel
事件。XGROUP CREATECONSUMER
生成一个xgroup-createconsumer
事件。XGROUP CREATE
生成一个xgroup-create
事件。XGROUP DELCONSUMER
生成一个xgroup-delconsumer
事件。XGROUP DESTROY
生成一个xgroup-destroy
事件。XGROUP SETID
生成一个xgroup-setid
事件。XSETID
生成一个xsetid
事件。XTRIM
生成一个xtrim
事件。ZADD
即使添加了多个元素,也只会生成一个zadd
事件。ZDIFFSTORE
,ZINTERSTORE
和ZUNIONSTORE
分别生成zdiffstore
,zinterstore
和zunionstore
事件。在特殊情况下,如果生成的排序集合为空,并且存储结果的键已经存在,则会生成一个del
事件,因为该键被移除了。ZINCRBY
生成一个zincr
事件。ZREMRANGEBYRANK
生成一个单一的zrembyrank
事件。当生成的排序集为空并且生成了键时,会生成一个额外的del
事件。ZREMRANGEBYSCORE
生成一个单一的zrembyscore
事件。当生成的排序集为空并且键被生成时,会生成一个额外的del
事件。ZREM
即使删除多个元素也只会生成一个zrem
事件。当生成的排序集为空并且键被生成时,会额外生成一个del
事件。- 每次一个带有生存时间的键因为过期而从数据集中被移除时,都会生成一个
expired
事件。 - 每次由于
maxmemory
策略从数据集中驱逐一个键以释放内存时,都会生成一个evicted
事件。 - 每次向数据集中添加新键时,都会生成一个
new
事件。
重要 所有命令只有在目标键真正被修改时才会生成事件。例如,SREM
从集合中删除一个不存在的元素实际上不会改变键的值,因此不会生成任何事件。
如果对某个命令如何生成事件有疑问,最简单的做法是观察自己:
$ redis-cli config set notify-keyspace-events KEA
$ redis-cli --csv psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__key*__:*",1
此时在另一个终端使用 redis-cli
向 Redis 服务器发送命令并观察生成的事件:
"pmessage","__key*__:*","__keyspace@0__:foo","set"
"pmessage","__key*__:*","__keyevent@0__:set","foo"
...
过期事件的计时
具有生存时间的键由Redis以两种方式过期:
- 当通过命令访问键时,发现它已过期。
- 通过一个后台系统,该系统在后台逐步查找过期的密钥,以便能够收集那些从未被访问的密钥。
当访问一个键并且被上述系统之一发现已过期时,会生成expired
事件,因此无法保证Redis服务器在键的生存时间达到零值时能够生成expired
事件。
如果没有命令持续针对该键,并且有许多键与TTL相关联,那么在键的生存时间降至零与生成expired
事件之间可能会有显著的延迟。
过期(expired
)事件是在Redis服务器删除键时生成的,而不是在理论上生存时间达到零值时生成的。
集群中的事件
Redis集群的每个节点都会生成关于其自身键空间子集的事件,如上所述。然而,与集群中的常规发布/订阅通信不同,事件通知不会广播到所有节点。换句话说,键空间事件是节点特定的。这意味着要接收集群的所有键空间事件,客户端需要订阅每个节点。
@历史
>= 6.0
: 添加了键缺失事件。>= 7.0
: 事件类型new
已添加