实时监控Redis键和值的变化
Keyspace通知允许客户端订阅Pub/Sub频道,以便以某种方式接收影响Redis数据集的事件。
可以接收的事件示例有:
- 影响给定键的所有命令。
- 所有接受LPUSH操作的键。
- 数据库0中的所有键都将过期。
注意:Redis Pub/Sub是火和忘记,即,如果您的Pub/Sub客户端断开连接,然后重新连接,在客户端断开连接期间交付的所有事件都将丢失。
事件类型
Keyspace通知通过为影响Redis数据空间的每个操作发送两种不同类型的事件来实现。例如,针对数据库0中名为mykey的密钥的DEL操作将触发两条消息的传递,完全等价于以下两个PUBLISH命令:
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
第一个通道侦听针对密钥mykey的所有事件,而另一个通道仅侦听密钥mykey上的删除操作事件
通道中带有keyspace前缀的第一种事件称为Key-space通知,而带有keyevent前缀的第二种事件称为Key-event通知。
在前面的例子中,为密钥mykey生成了del事件,导致两条消息:
- Key-space通道作为消息接收事件的名称。
- key -event通道将键的名称作为消息接收。
为了只交付我们感兴趣的事件子集,可以只启用一种通知。
配置
默认情况下,keyspace事件通知是禁用的,因为虽然不是很合理,但该功能会占用一些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".
字符串中至少应该有K或E,否则无论字符串的其余部分如何,都不会传递任何事件。
例如,要仅为列表启用Key-space事件,必须将配置参数设置为Kl,等等。
您可以使用字符串KEA来启用大多数类型的事件。
不同命令产生的事件
不同的命令会根据下面的列表生成不同类型的事件。
- DEL为每个删除的键生成一个DEL事件。
- RENAME生成两个事件,源键的rename_from事件和目标键的rename_to事件。
- MOVE生成两个事件,源键的move_from事件和目标键的move_to事件。
- COPY生成一个copy_to事件。
- 如果源键被移除,MIGRATE将生成del事件。
- RESTORE为键生成一个恢复事件。
- EXPIRE及其所有变体(PEXPIRE、EXPIREAT、PEXPIREAT)在以正超时(或未来时间戳)调用时生成过期事件。请注意,当使用负超时值或过去的时间戳调用这些命令时,键将被删除,而只生成del事件。
- 当使用STORE设置新键时,SORT生成一个sortstore事件。如果结果列表为空,并且使用了STORE选项,并且已经存在具有该名称的键,则结果是该键被删除,因此在此条件下将生成del事件。
- SET及其所有变体(SETEX, SETNX,GETSET)生成集合事件。但是SETEX也会产生一个过期事件。
- MSET为每个键生成一个单独的set事件。
- SETRANGE生成一个SETRANGE事件。
- INCR、DECR、INCRBY、DECRBY命令都生成INCRBY事件。
- 生成一个INCRBYFLOAT事件。
- 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事件,如果结果散列为空并且键被删除,则生成一个额外的del事件。
- SADD生成单个SADD事件,即使在变进情况下也是如此。
- SREM生成一个SREM事件,如果结果集为空且键被删除,则生成一个额外的del事件。
- SMOVE为源密钥生成srem事件,为目标密钥生成sadd事件。
- SPOP生成一个SPOP事件,如果结果集为空并且键被删除,则生成一个额外的del事件。
- SINTERSTORE、SUNIONSTORE、SDIFFSTORE分别生成SINTERSTORE、SUNIONSTORE、SDIFFSTORE事件。在特殊情况下,结果集为空,而存储结果的键已经存在,则在删除键后生成del事件。
- ZINCR生成ZINCR事件。
- 即使添加了多个元素,ZADD也会生成单个ZADD事件。
- 即使删除了多个元素,ZREM也会生成一个ZREM事件。当结果排序集为空并生成键时,将生成一个额外的del事件。
- ZREMBYSCORE生成一个ZREMBYSCORE事件。当结果排序集为空并生成键时,将生成一个额外的del事件。
- ZREMBYRANK生成一个ZREMBYRANK事件。当结果排序集为空并生成键时,将生成一个额外的del事件。
- ZDIFFSTORE, ZINTERSTORE和ZUNIONSTORE分别生成ZDIFFSTORE, ZINTERSTORE和ZUNIONSTORE事件。在特殊情况下,结果排序集为空,而存储结果的键已经存在,则会生成del事件,因为键被删除了。
- 当与MAXLEN子命令一起使用时,XADD生成一个XADD事件,可能在xtrim事件之后。
- 即使删除了多个条目,XDEL也会生成一个XDEL事件。
- 生成一个XGROUP - CREATE事件。
- 生成一个XGROUP - CREATECONSUMER事件。
- XGROUP DELCONSUMER生成XGROUP - DELCONSUMER事件。
- XGROUP DESTROY生成一个XGROUP - DESTROY事件。
- XGROUP SETID生成XGROUP - SETID事件。
- XSETID生成一个XSETID事件。
- XTRIM生成一个XTRIM事件。
重要 所有命令只在目标键确实被修改时才生成事件。例如,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过期:
- 当通过命令访问密钥并且发现密钥过期时。
- 通过后台系统在后台逐步查找过期的密钥,以便能够收集从未访问过的密钥。
过期事件是在密钥被访问并被上述系统之一发现过期时生成的,因此不能保证Redis服务器能够在密钥存活时间达到零时生成过期事件。
如果没有命令不断地以密钥为目标,并且有许多与TTL相关联的密钥,那么在密钥存活时间降至零和生成过期事件的时间之间可能会有很大的延迟。
基本上,过期事件是在Redis服务器删除密钥时产生的,而不是在理论上的生存时间达到零时产生的。
集群中的事件
Redis集群的每个节点都生成关于它自己的密钥空间子集的事件,如上所述。然而,与集群中常规的Pub/Sub通信不同,事件通知不会广播到所有节点。换句话说,键空间事件是节点特定的。这意味着要接收集群的所有密钥空间事件,客户端需要订阅每个节点。
@history
- 6.0: Key miss events were added.
- 7.0: Event type new added