Redis keyspace notifications #
https://redis.io/docs/latest/develop/use/keyspace-notifications/
实时监控 Redis 键和值的变化
键空间通知允许客户端订阅 Pub/Sub 通道(channel),以接收影响Redis
数据的事件。
可以接收到的事件示例包括:
- 所有影响特定键的命令。
- 所有接收到
LPUSH
操作的键。 - 数据库
0
中所有过期的键。
注意:Redis Pub/Sub是“发送即忘”机制;也就是说,如果你的Pub/Sub客户端断开连接并稍后重新连接,那么在客户端断开连接期间传递的所有事件都将丢失。
事件类型 #
键空间通知通过为每个操作发送两种不同类型的事件来实现,这些操作会影响 Redis 数据空间。例如,针对数据库0
中名为mykey
的键执行DEL
操作将触发发送两条消息,完全等同于以下两个PUBLISH
命令:
1PUBLISH __keyspace@0__:mykey del
2PUBLISH __keyevent@0__:del mykey
第一个通道监听所有针对mykey
键的事件,另一个通道只监听针对mykey
键的DEL
操作事件。
第一种类型的事件,通道中带有键空间前缀,称为键空间通知(Key-space notification),而第二种带有键事件前缀的事件,称为键事件通知(Key-event notification)。
在之前的示例中,针对 mykey 键生成了一个 DEL 事件,触发了两条消息的发送:
- 键空间通道接收到的消息是事件的名称。
- 键事件通道接收到的消息是键的名称。
可以只启用一种类型的通知,以便仅传递我们感兴趣的事件子集。
配置 #
默认情况下,键空间事件通知是禁用的,因为虽然该功能不会过度消耗资源,但仍会占用一定的CPU能力。可以通过redis.conf
中的notify-keyspace-events
参数或使用CONFIG SET
来启用通知。
将该参数设置为空字符串将禁用通知。为了启用该功能,需要使用非空字符串,该字符串由多个字符组成,每个字符根据下表具有特殊含义:
1K Keyspace 事件,发布时带有 __keyspace@<db>__ 前缀。
2E Keyevent 事件,发布时带有 __keyevent@<db>__ 前缀。
3g 通用命令(非特定类型的命令),如 DEL、EXPIRE、RENAME 等。
4$ 字符串命令
5l 列表命令
6s 集合命令
7h 哈希命令
8z 排序集合命令
9t 流命令
10d 模块键类型事件
11x 过期事件(每次键过期时生成的事件)
12e 驱逐事件(当一个键因达到最大内存限制被驱逐时生成的事件)
13m 键未命中事件(当访问一个不存在的键时生成的事件)
14n 新键事件(注意:不包含在 'A' 类中)
15A "g$lshztxed" 的别名,表示除 "m" 和 "n" 之外的所有事件。
字符串中至少应包含K
或E
,否则无论字符串其余部分如何,都不会传递任何事件。
例如,要仅启用列表的Key-space
事件,配置参数必须设置为Kl
,依此类推。
可以使用字符串KEA
来启用大多数类型的事件。
由不同命令生成的事件 #
不同的命令根据以下列表生成不同种类的事件:
- APPEND generates an append event.
- COPY generates a copy_to event.
- DEL generates a del event for every deleted key.
- EXPIRE and all its variants (PEXPIRE, EXPIREAT, PEXPIREAT) generate an expire event when called with a positive timeout (or a future timestamp). Note that when these commands are called with a negative timeout value or timestamp in the past, the key is deleted and only a del event is generated instead.
- HDEL generates a single hdel event, and an additional del event if the resulting hash is empty and the key is removed.
- HEXPIRE and all its variants (HEXPIREAT, HPEXPIRE, HPEXPIREAT) generate hexpire events. Furthermore, hexpired events are generated when fields expire.
- HINCRBYFLOAT generates an hincrbyfloat event.
- HINCRBY generates an hincrby event.
- HPERSIST generates an hpersist event.
- HSET, HSETNX and HMSET all generate a single hset event.
- INCRBYFLOAT generates an incrbyfloat events.
- INCR, DECR, INCRBY, DECRBY commands all generate incrby events.
- LINSERT generates an linsert event.
- LMOVE and BLMOVE generate an lpop/rpop event (depending on the wherefrom argument) and an lpush/rpush event (depending on the whereto argument). In both cases the order is guaranteed (the lpush/rpush event will always be delivered after the lpop/rpop event). Additionally a del event will be generated if the resulting list is zero length and the key is removed.
- LPOP generates an lpop event. Additionally a del event is generated if the key is removed because the last element from the list was popped.
- LPUSH and LPUSHX generates a single lpush event, even in the variadic case.
- LREM generates an lrem event, and additionally a del event if the resulting list is empty and the key is removed.
- LSET generates an lset event.
- LTRIM generates an ltrim event, and additionally a del event if the resulting list is empty and the key is removed.
- MIGRATE generates a del event if the source key is removed.
- MOVE generates two events, a move_from event for the source key, and a move_to event for the destination key.
- MSET generates a separate set event for every key.
- PERSIST generates a persist event if the expiry time associated with key has been successfully deleted.
- RENAME generates two events, a rename_from event for the source key, and a rename_to event for the destination key.
- RESTORE generates a restore event for the key.
- RPOPLPUSH and BRPOPLPUSH generate an rpop event and an lpush event. In both cases the order is guaranteed (the lpush event will always be delivered after the rpop event). Additionally a del event will be generated if the resulting list is zero length and the key is removed.
- RPOP generates an rpop event. Additionally a del event is generated if the key is removed because the last element from the list was popped.
- RPUSH and RPUSHX generates a single rpush event, even in the variadic case.
- SADD generates a single sadd event, even in the variadic case.
- SETRANGE generates a setrange event.
- SET and all its variants (SETEX, SETNX,GETSET) generate set events. However SETEX will also generate an expire events.
- SINTERSTORE, SUNIONSTORE, SDIFFSTORE generate sinterstore, sunionstore, sdiffstore events respectively. In the special case the resulting set is empty, and the key where the result is stored already exists, a del event is generated since the key is removed.
- SMOVE generates an srem event for the source key, and an sadd event for the destination key.
- SORT generates a sortstore event when STORE is used to set a new key. If the resulting list is empty, and the STORE option is used, and there was already an existing key with that name, the result is that the key is deleted, so a del event is generated in this condition.
- SPOP generates an spop event, and an additional del event if the resulting set is empty and the key is removed.
- SREM generates a single srem event, and an additional del event if the resulting set is empty and the key is removed.
- XADD generates an xadd event, possibly followed an xtrim event when used with the MAXLEN subcommand.
- XDEL generates a single xdel event even when multiple entries are deleted.
- XGROUP CREATECONSUMER generates an xgroup-createconsumer event.
- XGROUP CREATE generates an xgroup-create event.
- XGROUP DELCONSUMER generates an xgroup-delconsumer event.
- XGROUP DESTROY generates an xgroup-destroy event.
- XGROUP SETID generates an xgroup-setid event.
- XSETID generates an xsetid event.
- XTRIM generates an xtrim event.
- ZADD generates a single zadd event even when multiple elements are added.
- ZDIFFSTORE, ZINTERSTORE and ZUNIONSTORE respectively generate zdiffstore, zinterstore and zunionstore events. In the special case the resulting sorted set is empty, and the key where the result is stored already exists, a del event is generated since the key is removed.
- ZINCRBY generates a zincr event.
- ZREMRANGEBYRANK generates a single zrembyrank event. When the resulting sorted set is empty and the key is generated, an additional del event is generated.
- ZREMRANGEBYSCORE generates a single zrembyscore event. When the resulting sorted set is empty and the key is generated, an additional del event is generated.
- ZREM generates a single zrem event even when multiple elements are deleted. When the resulting sorted set is empty and the key is generated, an additional del event is generated.
- Every time a key with a time to live associated is removed from the data set because it expired, an expired event is generated.
- Every time a key is evicted from the data set in order to free memory as a result of the maxmemory policy, an evicted event is generated.
- Every time a new key is added to the data set, a new event is generated.
重要提示
只有当目标键真正被修改时,所有命令才会生成事件。例如,SREM 从集合中删除一个不存在的元素不会实际改变键的值,因此不会生成事件。
如果对某个命令如何生成事件存在疑问,最简单的方法是自己观察:
1$ redis-cli config set notify-keyspace-events KEA
2$ redis-cli --csv psubscribe '__key*__:*'
3Reading messages... (press Ctrl-C to quit)
4"psubscribe","__key*__:*",1
此时,请在另一个终端中使用 redis-cli 向 Redis 服务器发送命令,并观察生成的事件:
1"pmessage","__key*__:*","__keyspace@0__:foo","set"
2"pmessage","__key*__:*","__keyevent@0__:set","foo"
3...
过期事件的时机 #
Redis 通过两种方式使带有生存时间的键过期:
- 当键被某个命令访问并发现已过期时。
- 通过后台系统在后台增量地查找过期的键,以便能够收集从未被访问的键。
当键被访问并被上述系统之一发现已过期时,会生成expired
事件,因此无法保证 Redis 服务器能够在键的生存时间达到零时准确生成expired
事件。
如果没有命令持续针对该键,且存在大量带有 TTL 的键,那么键的生存时间降至零和生成expired
事件之间可能会有相当大的延迟。
expired
事件是在 Redis 服务器删除键时生成,而非键的生存时间理论上达到零时。
集群中的事件 #
Redis集群中的每个节点都会按照上述方式为其自身的键空间子集生成事件。但是,与集群中常规的发布/订阅通信不同,事件通知不会广播到所有节点。换句话说,键空间事件是特定于节点的。这意味着要接收集群的所有键空间事件,客户端需要订阅每个节点。
@历史 #
>= 6.0
:添加了键未命中事件。>= 7.0
:添加了new
事件类型