Redis 密钥空间通知

实时监控 Redis 键和值的更改

Keyspace 通知允许客户端按顺序订阅 Pub/Sub 频道 接收以某种方式影响 Redis 数据集的事件。

可以接收的事件示例包括:

  • 影响给定键的所有命令。
  • 所有接收 LPUSH作的 key。
  • 数据库 0 中过期的所有键。

注意:Redis Pub/Sub 是即发即弃;也就是说,如果您的 Pub/Sub 客户端断开连接, 并在稍后重新连接客户端 disconnected 会丢失。

事件类型

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 通道以消息形式接收事件的名称。
  • Key-event 通道以消息形式接收键的名称。

可以只启用一种通知才能传递 只是我们感兴趣的事件子集。

配置

默认情况下,密钥空间事件通知是禁用的,因为虽然没有 非常明智的该功能使用了一些 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" and "n".

至少KE应存在于字符串中,否则无事件 将传递,而不管字符串的其余部分如何。

例如,要仅为列表启用 Key-space 事件,则配置 parameter 必须设置为Kl等。

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

由不同命令生成的事件

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

  • APPEND生成一个append事件。
  • COPY生成一个copy_to事件。
  • DEL生成一个del事件。
  • EXPIRE及其所有变体 (PEXPIRE,EXPIREAT,PEXPIREAT) 生成一个expireevent 调用时,使用正超时(或将来的时间戳)调用。请注意,当使用过去的负超时值或时间戳调用这些命令时,将删除该键,并且只有delevent 的 EVENT。
  • HDEL生成单个hdel事件和附加的del事件(如果生成的哈希为空并且 key 被删除)。
  • HEXPIRE及其所有变体 (HEXPIREAT,HPEXPIRE,HPEXPIREAT) 生成hexpire事件。此外hexpired当字段过期时生成事件。
  • HINCRBYFLOAT生成一个hincrbyfloat事件。
  • HINCRBY生成一个hincrby事件。
  • HPERSIST生成一个hpersist事件。
  • HSET,HSETNXHMSET都会生成一个hset事件。
  • INCRBYFLOAT生成一个incrbyfloat事件。
  • INCR,DECR,INCRBY,DECRBY命令都生成incrby事件。
  • LINSERT生成一个linsert事件。
  • LMOVEBLMOVE生成一个lpop/rpop事件(取决于 wherefrom 参数)和lpush/rpush事件(取决于 whereto 参数)。在这两种情况下,顺序都是有保证的(lpush/rpush事件将始终在lpop/rpop事件)。此外,一个del如果结果列表的长度为零,并且 key 被删除,则将生成 event 。
  • LPOP生成一个lpop事件。此外,一个delevent 如果由于弹出了列表中的最后一个元素而被删除了键。
  • LPUSHLPUSHX生成单个lpush事件,即使在可变参数情况下也是如此。
  • LREM生成一个lrem事件,此外还有一个del事件(如果结果列表为空且键被删除)。
  • LSET生成一个lset事件。
  • LTRIM生成一个ltrim事件,此外还有一个del事件(如果结果列表为空且键被删除)。
  • MIGRATE生成一个del事件(如果源键已删除)。
  • MOVE生成两个事件,一个move_fromevent 作为源键,并使用move_toevent 作为目标键。
  • MSET生成一个单独的setevent 的 intent 中。
  • PERSIST生成一个persistevent 如果已成功删除与密钥关联的过期时间。
  • RENAME生成两个事件,一个rename_fromevent 作为源键,并使用rename_toevent 作为目标键。
  • RESTORE生成一个restoreevent 的密钥。
  • RPOPLPUSHBRPOPLPUSH生成一个rpopevent 和lpush事件。在这两种情况下,顺序都是有保证的(lpush事件将始终在rpop事件)。此外,一个del如果结果列表的长度为零,并且 key 被删除,则将生成 event 。
  • RPOP生成一个rpop事件。此外,一个delevent 如果由于弹出了列表中的最后一个元素而被删除了键。
  • RPUSHRPUSHX生成单个rpush事件,即使在可变参数情况下也是如此。
  • SADD生成单个sadd事件,即使在可变参数情况下也是如此。
  • SETRANGE生成一个setrange事件。
  • SET及其所有变体 (SETEX,SETNX,GETSET) 生成set事件。然而SETEX还将生成一个expire事件。
  • SINTERSTORE,SUNIONSTORE,SDIFFSTORE生成sinterstore,sunionstore,sdiffstore事件。在特殊情况下,结果集为空,并且存储结果的 key 已经存在,一个del事件,因为密钥被删除。
  • SMOVE生成一个sremevent 作为源键,并使用saddevent 作为目标键。
  • SORT生成一个sortstoreevent 时STORE用于设置新密钥。如果结果列表为空,并且STORE选项,并且已经存在具有该名称的现有键,则结果是该键被删除,因此del事件。
  • SPOP生成一个spop事件和附加的delevent,如果结果集为空且 key 被删除。
  • SREM生成单个srem事件和附加的delevent,如果结果集为空且 key 被删除。
  • XADD生成一个xadd事件,可能在xtrimevent 与MAXLEN子命令。
  • 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,ZINTERSTOREZUNIONSTORE分别生成zdiffstore,zinterstorezunionstore事件。在特殊情况下,结果排序集为空,并且存储结果的键已经存在,一个del事件,因为密钥被删除。
  • ZINCRBY生成一个zincr事件。
  • ZREMRANGEBYRANK生成单个zrembyrank事件。当生成的排序集为空并且生成了键时,附加的del事件。
  • ZREMRANGEBYSCORE生成单个zrembyscore事件。当生成的排序集为空并且生成了键时,附加的del事件。
  • ZREM生成单个zrem事件,即使删除了多个元素也是如此。当生成的排序集为空并且生成了键时,附加的del事件。
  • 每次从数据集中删除具有生存时间关联的键时,都会触发一个expired事件。
  • 每次从数据集中逐出键以释放内存时,由于maxmemorypolicy、evicted事件。
  • 每次将新键添加到数据集时,都会显示一个new事件。

重要 仅当目标键确实被修改时,所有命令才会生成事件。例如,SREM从 Set 中删除不存在的元素实际上不会更改 key 的值,因此不会生成任何事件。

如果对如何为给定命令生成事件有疑问,最简单的 要做的是观察自己:

$ 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 服务器能够生成expiredevent 时,关键生存时间达到零值。

如果没有命令始终以密钥为目标,并且有许多密钥与 TTL 相关联,则密钥生存时间降至零的时间与expired事件。

已过期 (expired) 事件是在 Redis 服务器删除键时生成,而不是在理论生存时间达到零值时生成。

集群中的事件

如上所述,Redis 集群的每个节点都会生成有关其自己的键空间子集的事件。但是,与集群中的常规 Pub/Sub 通信不同,事件的通知不会广播到所有节点。换句话说,键空间事件是特定于节点的。这意味着要接收集群的所有密钥空间事件,客户端需要订阅每个节点。

@history

  • >= 6.0:添加了关键未命中事件。
  • >= 7.0:事件类型new添加