Redis 键空间通知

实时监控 Redis 键和值的变化

键空间通知允许客户端订阅 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 事件,产生了两条消息

  • 键空间通道接收的消息是事件的名称。
  • 键事件通道接收的消息是键的名称。

可以只启用一种通知,以便只接收我们感兴趣的事件子集。

配置

默认情况下,键空间事件通知是禁用的,因为尽管不太敏感,但此功能会占用一些 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".

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

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

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

不同命令生成的事件

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

  • APPEND 生成一个 append 事件。
  • COPY 生成一个 copy_to 事件。
  • DEL 为每个被删除的键生成一个 del 事件。
  • EXPIRE 及其所有变体(PEXPIREEXPIREATPEXPIREAT)在使用正超时(或未来时间戳)调用时会生成一个 expire 事件。注意,当这些命令使用负超时值或过去的时间戳调用时,键被删除,并且只生成一个 del 事件。
  • HDEL 生成一个单独的 hdel 事件,如果结果哈希为空且键被移除,则会额外生成一个 del 事件。
  • HEXPIRE 及其所有变体(HEXPIREATHPEXPIREHPEXPIREAT)会生成 hexpire 事件。此外,当字段过期时会生成 hexpired 事件。
  • HINCRBYFLOAT 生成一个 hincrbyfloat 事件。
  • HINCRBY 生成一个 hincrby 事件。
  • HPERSIST 生成一个 hpersist 事件。
  • HSETHSETNXHMSET 都生成一个单独的 hset 事件。
  • INCRBYFLOAT 生成一个 incrbyfloat 事件。
  • INCRDECRINCRBYDECRBY 命令都生成 incrby 事件。
  • LINSERT 生成一个 linsert 事件。
  • LMOVEBLMOVE 生成一个 lpop/rpop 事件(取决于 wherefrom 参数)和一个 lpush/rpush 事件(取决于 whereto 参数)。在这两种情况下,顺序都得到保证(lpush/rpush 事件始终在 lpop/rpop 事件之后传递)。此外,如果结果列表长度为零且键被移除,则会生成一个 del 事件。
  • LPOP 生成一个 lpop 事件。此外,如果键因列表中的最后一个元素被弹出而被移除,则会生成一个 del 事件。
  • LPUSHLPUSHX 生成一个单独的 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 事件。
  • RPOPLPUSHBRPOPLPUSH 生成一个 rpop 事件和一个 lpush 事件。在这两种情况下,顺序都得到保证(lpush 事件始终在 rpop 事件之后传递)。此外,如果结果列表长度为零且键被移除,则会生成一个 del 事件。
  • RPOP 生成一个 rpop 事件。此外,如果键因列表中的最后一个元素被弹出而被移除,则会生成一个 del 事件。
  • RPUSHRPUSHX 生成一个单独的 rpush 事件,即使是可变参数情况。
  • SADD 生成一个单独的 sadd 事件,即使是可变参数情况。
  • SETRANGE 生成一个 setrange 事件。
  • SET 及其所有变体(SETEXSETNXGETSET)会生成 set 事件。然而,SETEX 也会生成一个 expire 事件。
  • SINTERSTORESUNIONSTORESDIFFSTORE 分别生成 sinterstoresunionstoresdiffstore 事件。在特殊情况下,如果结果集合为空,并且存储结果的键已经存在,则会生成一个 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 事件,即使添加了多个元素。
  • ZDIFFSTOREZINTERSTOREZUNIONSTORE 分别生成 zdiffstorezinterstorezunionstore 事件。在特殊情况下,如果结果有序集合为空,并且存储结果的键已经存在,则会生成一个 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 集群的每个节点都生成关于其自身键空间子集的事件。然而,与集群中常规的 Pub/Sub 通信不同,事件通知不会广播到所有节点。换句话说,键空间事件是特定于节点的。这意味着,要接收集群的所有键空间事件,客户端需要订阅每个节点。

@history

  • >= 6.0: 添加了 Key miss 事件。
  • >= 7.0: 添加了事件类型 new
为此页面评分
返回顶部 ↑