# Redis 键空间通知
实时监控 Redis 键和值的变化
Keyspace 通知允许客户端订阅 Pub/Sub 频道,以便接收以某种方式影响 Redis 数据集的事件。
可以接收的事件示例如下:
- 影响给定键的所有命令。
- 所有接受 LPUSH 操作的键。
- 数据库 0 中所有过期的密钥。
注意:Redis Pub/Sub 很火,忘记了,如果您的 Pub/Sub 客户端断开连接,然后重新连接,则在客户端断开连接期间传递的所有事件都将丢失。
# 活动类型
Keyspace 通知是通过为影响 Redis 数据空间的每个操作发送两种不同类型的事件来实现的。例如,针对数据库 DEL 中命名的键的操作将触发两条消息的传递,完全等同于以下两个 命令:mykey``0 PUBLISH
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
第一个通道监听所有针对按键的事件mykey,另一个通道只监听del按键上的操作事件mykey
第一种keyspace在通道中带有前缀的事件称为Key-space 通知,而第二种带有keyevent前缀的事件称为Key-event 通知。
在前面的示例del中,为键生成了一个事件,mykey导致两条消息:
- Key-space 通道接收事件名称作为消息。
- 键事件通道接收键名称作为消息。
可以只启用一种通知,以便只传递我们感兴趣的事件子集。
# 配置
默认情况下,键空间事件通知被禁用,因为虽然不是很明智,但该功能使用了一些 CPU 能力。notify-keyspace-events使用redis.conf 或通过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".
至少K或E应该存在于字符串中,否则无论字符串的其余部分如何,都不会传递任何事件。
例如,要仅启用列表的键空间事件,必须将配置参数设置为Kl,依此类推。
您可以使用该字符串KEA来启用大多数类型的事件。
# 不同命令产生的事件
根据以下列表,不同的命令会生成不同类型的事件。
DELdel为每个已删除的键生成一个事件。RENAME生成两个事件,rename_from源键rename_to事件和目标键事件。MOVE生成两个事件,move_from源键move_to事件和目标键事件。COPY产生一个copy_to事件。MIGRATEdel如果源密钥被删除,则生成一个事件。RESTORE为键生成restore事件。EXPIRE并且它的所有变体(PEXPIRE,EXPIREAT, )在使用正超时(或未来时间戳)调用时都会PEXPIREAT生成一个事件。expire请注意,当过去使用负超时值或时间戳调用这些命令时,会删除键,而只会del生成一个事件。SORT当用于设置新密钥时生成一个sortstore事件。STORE如果结果列表为空,并且STORE使用了该选项,并且已经存在具有该名称的键,则结果是键被删除,因此del在这种情况下会生成一个事件。SET及其所有变体 (SETEX,SETNX,GETSET) 都会生成set事件。但是SETEX也会产生一个expire事件。MSETset为每个键生成一个单独的事件。SETRANGE产生一个setrange事件。INCR,DECR,INCRBY,DECRBY命令都生成incrby事件。INCRBYFLOAT产生一个incrbyfloat事件。APPEND产生一个append事件。LPUSH并LPUSHX生成单个lpush事件,即使在可变参数情况下也是如此。RPUSH并RPUSHX生成单个rpush事件,即使在可变参数情况下也是如此。RPOP产生一个rpop事件。此外,del如果由于弹出列表中的最后一个元素而删除了键,则会生成一个事件。LPOP产生一个lpop事件。此外,del如果由于弹出列表中的最后一个元素而删除了键,则会生成一个事件。LINSERT产生一个linsert事件。LSET产生一个lset事件。LREM生成一个lrem事件,del如果结果列表为空并且删除了键,则生成一个事件。LTRIM生成一个ltrim事件,del如果结果列表为空并且删除了键,则生成一个事件。RPOPLPUSH并BRPOPLPUSH生成一个rpop事件和一个lpush事件。在这两种情况下,订单都是有保证的(lpush事件总是在rpop事件之后交付)。此外,del如果结果列表的长度为零并且密钥被删除,则将生成一个事件。LMOVE并BLMOVE生成lpop/rpop事件(取决于 wherefrom 参数)和lpush/rpush事件(取决于 whereto 参数)。在这两种情况下,订单都是有保证的(lpush/rpush事件将始终在lpop/rpop事件之后交付)。此外,del如果结果列表的长度为零并且密钥被删除,则将生成一个事件。HSET,HSETNX并且HMSET都生成一个hset事件。HINCRBY产生一个hincrby事件。HINCRBYFLOAT产生一个hincrbyfloat事件。HDEL生成单个事件,如果生成的哈希为空并且删除了键,则生成hdel一个附加事件。delSADD生成单个sadd事件,即使在可变参数情况下也是如此。SREM生成单个事件,如果结果集为空且删除键,则生成srem附加事件。delSMOVEsrem为源键生成一个事件,sadd为目标键生成一个事件。SPOP生成一个事件,如果结果集为空并且删除了键,则生成spop一个附加事件。delSINTERSTORE,SUNIONSTORE,分别SDIFFSTORE生成sinterstore,sunionstore,sdiffstore事件。在特殊情况下,结果集为空,并且存储结果的 key 已经存在,del由于 key 被删除,将生成一个事件。ZINCR产生一个zincr事件。ZADDzadd即使添加了多个元素,也会生成单个事件。ZREMzrem即使删除了多个元素,也会生成单个事件。当结果排序集为空并生成键时,会生成一个附加del事件。ZREMBYSCORE生成单个zrembyscore事件。当结果排序集为空并生成键时,会生成一个附加del事件。ZREMBYRANK生成单个zrembyrank事件。当结果排序集为空并生成键时,会生成一个附加del事件。ZDIFFSTORE,ZINTERSTORE并ZUNIONSTORE分别生成zdiffstore,zinterstore和zunionstore事件。在特殊情况下,结果排序集为空,并且存储结果的键已经存在,del因为键被删除,所以会产生一个事件。XADD生成一个事件,当与子命令一起使用时xadd,可能会跟随一个事件。xtrim``MAXLENXDELxdel即使删除了多个条目,也会生成单个事件。XGROUP CREATE产生一个xgroup-create事件。XGROUP CREATECONSUMER产生一个xgroup-createconsumer事件。XGROUP DELCONSUMER产生一个xgroup-delconsumer事件。XGROUP DESTROY产生一个xgroup-destroy事件。XGROUP SETID产生一个xgroup-setid事件。XSETID产生一个xsetid事件。XTRIM产生一个xtrim事件。PERSISTpersist如果与密钥关联的到期时间已成功删除,则生成事件。- 每次由于过期而从数据集中删除与生存时间相关联的密钥时,
expired都会生成一个事件。 - 每次从数据集中逐出一个键以作为
maxmemory策略的结果释放内存时,都会生成一个evicted事件。 - 每次向数据集中添加新键时,
new都会生成一个事件。
重要的是,只有在真正修改了目标键时,所有命令才会生成事件。例如, SREM 从 Set 中删除不存在的元素实际上不会更改键的值,因此不会生成任何事件。
如果对给定命令如何生成事件有疑问,最简单的做法是观察自己:
$ 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 集群的每个节点都会生成有关其自己的键空间子集的事件。但是,与集群中的常规 Pub/Sub 通信不同,事件的通知不会广播到所有节点。换句话说,键空间事件是特定于节点的。这意味着要接收集群的所有键空间事件,客户端需要订阅每个节点。
@历史
>= 6.0:增加了关键未命中事件。>= 7.0``new:添加事件类型
# 反馈
如果您在此页面上发现问题,或有改进建议,请提交请求以合并或打开存储库中的问题。