备注
原文见https://redis.io/docs/manual/keyspace-notifications/
Redis keyspace notifications
redis键空间通知机制用于实时监控redis的key和value的变化
键空间通知允许客户端订阅Pub/Sub通道,以便接收影响redis数据集的事件。
可以接收事件的示例如下:
- 影响给定key的所有命令
- 接受LPUSH命令的key
- database 0中所有key过期事件
提示
:如果客户端断开连接然后重新连上,所有在断连期间的时间都会丢失
事件类型
建空间通知对每个影响redis数据的操作会发送2个不同的事件。例如,针对database 0 中名为 mykey 的键的 DEL 操作将触发两条消息的传递,完全等同于以下两个 PUBLISH 命令。
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
第一个通道监听所有针对键 mykey 的事件,另一个通道仅监听键 mykey 上的 del 操作事件
第一种在通道中带有 keyspace 前缀的事件称为 Key-space 通知,而第二种带有 keyevent 前缀的事件称为 Key-event 通知。
在前面的示例中,为键 mykey 生成了一个 del 事件,会发送两条消息:
- Key-space 通道接收事件名称作为消息
- Key-event 通道接收键名称作为消息。
可以只启用一种通知,以便只传递我们感兴趣的事件子集。
配置
默认情况下,键空间事件通知是被禁用的,因为这个特性会额外消耗一些cpu,启用它不是特别明智。(By default keyspace event notifications are disabled because while not very sensible the feature uses some CPU power)
通过修改redis.conf中notify-keyspace-events配置项或者通过CONFIG SET命令启用Key-space事件通知。
将该配置项置为空字符串会禁用通知功能,为了启用该功能,使用非空字符串去配置,每个字符串都有其特殊含义。
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".
至少"K"或者"E"应该在配置项中,否则不会有任何事件被触发,即使配置了其他选项。
例如该配置项配置成“kl”后,就会为list类型开启Key-space事件的通知,你也可以通过配置成“KEA”开启大部分的事件通知。
不同的命令触发的不同的事件
- DEL generates a del event for every deleted key.
- RENAME generates two events, a rename_from event for the source key, and a rename_to event for the destination key.
- MOVE generates two events, a move_from event for the source key, and a move_to event for the destination key.
- COPY generates a copy_to event.
- MIGRATE generates a del event if the source key is removed.
- RESTORE generates a restore event for the 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.
- 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.
- SET and all its variants (SETEX, SETNX,GETSET) generate set events. However SETEX will also generate an expire events.
- MSET generates a separate set event for every key.
- SETRANGE generates a setrange event.
- INCR, DECR, INCRBY, DECRBY commands all generate incrby events.
- INCRBYFLOAT generates an incrbyfloat events.
- APPEND generates an append event.
- LPUSH and LPUSHX generates a single lpush event, even in the variadic case.
- RPUSH and RPUSHX generates a single rpush event, even in the variadic case.
- 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.
- 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.
- LINSERT generates an linsert event.
- LSET generates an lset event.
- LREM generates an lrem event, and additionally a del event if the resulting list is empty and the key is removed.
- LTRIM generates an ltrim event, and additionally a del event if the resulting list is empty and the key is removed.
- 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.
- 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.
- HSET, HSETNX and HMSET all generate a single hset event.
- HINCRBY generates an hincrby event.
- HINCRBYFLOAT generates an hincrbyfloat event.
- HDEL generates a single hdel event, and an additional del event if the resulting hash is empty and the key is removed.
- SADD generates a single sadd event, even in the variadic case.
- SREM generates a single srem event, and an additional del event if the resulting set is empty and the key is removed.
- SMOVE generates an srem event for the source key, and an sadd event for the destination key.
- SPOP generates an spop event, and an additional del event if the resulting set is empty and the key is removed.
- 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.
- ZINCR generates a zincr event.
- ZADD generates a single zadd event even when multiple elements are added.
- 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.
- ZREMBYSCORE generates a single zrembyscore event. When the resulting sorted set is empty and the key is generated, an additional del event is generated.
- ZREMBYRANK generates a single zrembyrank event. When the resulting sorted set is empty and the key is generated, an additional del event is generated.
- 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.
- 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 CREATE generates an xgroup-create event.
- XGROUP CREATECONSUMER generates an xgroup-createconsumer 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.
- PERSIST generates a persist event if the expiry time associated with key has been successfully deleted.
- 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命令去删除一个不存在的元素,并不会真正的去修改这个key,所以并不会生成事件。
键过期事件
当key过期后会以两种方式被清理
- 当有命令处理过期key(不管是查询还是修改),会触发清理
- 后台清理过期key
当执行清理key时就会发送expired事件,但是没法保证一定在key过期的时候执行清理操作。
当没有命令去访问key时,key过期后可能过很久才会得到清理,在清理的时候才会生成过期事件。
key的过期时间实在redis清理它时才会触发,而不是在理论上它的生存时间达到0时。
关于后台清理过期key的信息,详见https://github.com/redis/redis/issues/187
- slave不会触发key过期清理,他只接受master的DEL命令
- master使用两种方式清理过期key:后台增量随机抽样key去检测是否过期;访问key的时候触发过期清理(lazy模式)
为啥后台定期清理时是随机抽样清理,因为redis中可能存在很多key,如果每次后台清理时,都扫描全部,会产生巨大的开销。
另外如果访问从节点已经过期的key,并不会触发清理动作,因为从节点只接受主节点DEL命令,自己没有清理逻辑。
集群模式下的事件
集群中的每个节点只会对本节点上的key生成事件,不像Pub/Sub命令会在集群中广播。换句话说键空间事件是特定于节点的,如果需要监听集群所有key的事件,客户端需要订阅每一个节点。