# 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".

至少KE应该存在于字符串中,否则无论字符串的其余部分如何,都不会传递任何事件。

例如,要仅启用列表的键空间事件,必须将配置参数设置为Kl,依此类推。

您可以使用该字符串KEA来启用大多数类型的事件。

# 不同命令产生的事件

根据以下列表,不同的命令会生成不同类型的事件。

  • DEL del为每个已删除的键生成一个事件。
  • RENAME 生成两个事件,rename_from源键rename_to事件和目标键事件。
  • MOVE 生成两个事件,move_from源键move_to事件和目标键事件。
  • COPY 产生一个copy_to事件。
  • MIGRATE del如果源密钥被删除,则生成一个事件。
  • RESTORE 为键生成restore事件。
  • EXPIRE 并且它的所有变体( PEXPIRE, EXPIREAT, )在使用正超时(或未来时间戳)调用时都会 PEXPIREAT 生成一个事件。expire请注意,当过去使用负超时值或时间戳调用这些命令时,会删除键,而只会del生成一个事件。
  • SORT 当用于设置新密钥时生成一个sortstore事件。STORE如果结果列表为空,并且STORE使用了该选项,并且已经存在具有该名称的键,则结果是键被删除,因此del在这种情况下会生成一个事件。
  • SET 及其所有变体 ( SETEX, SETNX, GETSET ) 都会生成set事件。但是 SETEX 也会产生一个expire事件。
  • MSET set为每个键生成一个单独的事件。
  • SETRANGE 产生一个setrange事件。
  • INCR, DECR, INCRBY, DECRBY 命令都生成incrby事件。
  • INCRBYFLOAT 产生一个incrbyfloat事件。
  • APPEND 产生一个append事件。
  • LPUSHLPUSHX 生成单个lpush事件,即使在可变参数情况下也是如此。
  • RPUSHRPUSHX 生成单个rpush事件,即使在可变参数情况下也是如此。
  • RPOP 产生一个rpop事件。此外,del如果由于弹出列表中的最后一个元素而删除了键,则会生成一个事件。
  • LPOP 产生一个lpop事件。此外,del如果由于弹出列表中的最后一个元素而删除了键,则会生成一个事件。
  • LINSERT 产生一个linsert事件。
  • LSET 产生一个lset事件。
  • LREM 生成一个lrem事件,del如果结果列表为空并且删除了键,则生成一个事件。
  • LTRIM 生成一个ltrim事件,del如果结果列表为空并且删除了键,则生成一个事件。
  • RPOPLPUSHBRPOPLPUSH 生成一个rpop事件和一个lpush事件。在这两种情况下,订单都是有保证的(lpush事件总是在rpop事件之后交付)。此外,del如果结果列表的长度为零并且密钥被删除,则将生成一个事件。
  • LMOVEBLMOVE 生成lpop/rpop事件(取决于 wherefrom 参数)和lpush/rpush事件(取决于 whereto 参数)。在这两种情况下,订单都是有保证的(lpush/rpush事件将始终在lpop/rpop事件之后交付)。此外,del如果结果列表的长度为零并且密钥被删除,则将生成一个事件。
  • HSETHSETNX 并且 HMSET 都生成一个hset事件。
  • HINCRBY 产生一个hincrby事件。
  • HINCRBYFLOAT 产生一个hincrbyfloat事件。
  • HDEL 生成单个事件,如果生成的哈希为空并且删除了键,则生成hdel一个附加事件。del
  • SADD 生成单个sadd事件,即使在可变参数情况下也是如此。
  • SREM 生成单个事件,如果结果集为空且删除键,则生成srem附加事件。del
  • SMOVE srem为源键生成一个事件,sadd为目标键生成一个事件。
  • SPOP 生成一个事件,如果结果集为空并且删除了键,则生成spop一个附加事件。del
  • SINTERSTORE, SUNIONSTORE,分别 SDIFFSTORE 生成sinterstore, sunionstore,sdiffstore事件。在特殊情况下,结果集为空,并且存储结果的 key 已经存在,del由于 key 被删除,将生成一个事件。
  • ZINCR产生一个zincr事件。
  • ZADD zadd即使添加了多个元素,也会生成单个事件。
  • ZREM zrem即使删除了多个元素,也会生成单个事件。当结果排序集为空并生成键时,会生成一个附加del事件。
  • ZREMBYSCORE生成单个zrembyscore事件。当结果排序集为空并生成键时,会生成一个附加del事件。
  • ZREMBYRANK生成单个zrembyrank事件。当结果排序集为空并生成键时,会生成一个附加del事件。
  • ZDIFFSTORE, ZINTERSTOREZUNIONSTORE 分别生成zdiffstore,zinterstorezunionstore事件。在特殊情况下,结果排序集为空,并且存储结果的键已经存在,del因为键被删除,所以会产生一个事件。
  • XADD 生成一个事件,当与子命令一起使用时xadd,可能会跟随一个事件。xtrim``MAXLEN
  • XDEL xdel即使删除了多个条目,也会生成单个事件。
  • XGROUP CREATE 产生一个xgroup-create事件。
  • XGROUP CREATECONSUMER 产生一个xgroup-createconsumer事件。
  • XGROUP DELCONSUMER 产生一个xgroup-delconsumer事件。
  • XGROUP DESTROY 产生一个xgroup-destroy事件。
  • XGROUP SETID 产生一个xgroup-setid事件。
  • XSETID 产生一个xsetid事件。
  • XTRIM 产生一个xtrim事件。
  • PERSIST persist如果与密钥关联的到期时间已成功删除,则生成事件。
  • 每次由于过期而从数据集中删除与生存时间相关联的密钥时,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:添加事件类型

# 反馈

如果您在此页面上发现问题,或有改进建议,请提交请求以合并或打开存储库中的问题。

Last Updated: 4/18/2023, 8:45:33 AM