Redis 过期监听 + 加阻塞队列
https://redis.io/docs/manual/keyspace-notifications/
简单一句话就是要订阅key失效事件
应用场景:在线客服中开启会话后,如果客户一段时间未回复,则结束会话。为了保证会话结束的时效性,通过redis 订阅key失效事件处理
配置 notify-keyspace-events Ex
key失效后就会发布消息,业务中订阅这个topic
@Bean public RedisConsumer initRedisConsumer() { System.out.println(RedisManager.set("aabbcc", "123", 10)); return new RedisConsumer("__keyevent@7__:expired", (k,v)->System.out.println("接收到["+k+"]的消息:" + v), false); }
收到消息:
接收到[__keyevent@7__:expired]的消息:aabbcc
修改配置需要重启,消息不丢失
补充:因为被动失效时效性不能保证完全实时,可以起一个定时任务去查询key,主动触发检测
补充2:主动删除key,不会触发失效通知
Redis keyspace notifications
Monitor changes to Redis keys and values in real time
Keyspace notifications allow clients to subscribe to Pub/Sub channels in order to receive events affecting the Redis data set in some way.
Examples of events that can be received are:
- All the commands affecting a given key.
- All the keys receiving an LPUSH operation.
- All the keys expiring in the database 0.
Note: Redis Pub/Sub is fire and forget that is, if your Pub/Sub client disconnects, and reconnects later, all the events delivered during the time the client was disconnected are lost.
Type of events
Keyspace notifications are implemented by sending two distinct types of events for every operation affecting the Redis data space. For instance a DEL
operation targeting the key named mykey
in database 0
will trigger the delivering of two messages, exactly equivalent to the following two PUBLISH
commands:
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
The first channel listens to all the events targeting the key mykey
and the other channel listens only to del
operation events on the key mykey
The first kind of event, with keyspace
prefix in the channel is called a Key-space notification, while the second, with the keyevent
prefix, is called a Key-event notification.
In the previous example a del
event was generated for the key mykey
resulting in two messages:
- The Key-space channel receives as message the name of the event.
- The Key-event channel receives as message the name of the key.
It is possible to enable only one kind of notification in order to deliver just the subset of events we are interested in.
Configuration
By default keyspace event notifications are disabled because while not very sensible the feature uses some CPU power. Notifications are enabled using the notify-keyspace-events
of redis.conf or via the CONFIG SET.
Setting the parameter to the empty string disables notifications. In order to enable the feature a non-empty string is used, composed of multiple characters, where every character has a special meaning according to the following table:
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".
At least K
or E
should be present in the string, otherwise no event will be delivered regardless of the rest of the string.
For instance to enable just Key-space events for lists, the configuration parameter must be set to Kl
, and so forth.
You can use the string KEA
to enable most types of events.
Events generated by different commands
Different commands generate different kind of events according to the following list.
DEL
generates adel
event for every deleted key.RENAME
generates two events, arename_from
event for the source key, and arename_to
event for the destination key.MOVE
generates two events, amove_from
event for the source key, and amove_to
event for the destination key.COPY
generates acopy_to
event.MIGRATE
generates adel
event if the source key is removed.RESTORE
generates arestore
event for the key.EXPIRE
and all its variants (PEXPIRE
,EXPIREAT
,PEXPIREAT
) generate anexpire
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 adel
event is generated instead.SORT
generates asortstore
event whenSTORE
is used to set a new key. If the resulting list is empty, and theSTORE
option is used, and there was already an existing key with that name, the result is that the key is deleted, so adel
event is generated in this condition.SET
and all its variants (SETEX
,SETNX
,GETSET
) generateset
events. HoweverSETEX
will also generate anexpire
events.MSET
generates a separateset
event for every key.SETRANGE
generates asetrange
event.INCR
,DECR
,INCRBY
,DECRBY
commands all generateincrby
events.INCRBYFLOAT
generates anincrbyfloat
events.APPEND
generates anappend
event.LPUSH
andLPUSHX
generates a singlelpush
event, even in the variadic case.RPUSH
andRPUSHX
generates a singlerpush
event, even in the variadic case.RPOP
generates anrpop
event. Additionally adel
event is generated if the key is removed because the last element from the list was popped.LPOP
generates anlpop
event. Additionally adel
event is generated if the key is removed because the last element from the list was popped.LINSERT
generates anlinsert
event.LSET
generates anlset
event.LREM
generates anlrem
event, and additionally adel
event if the resulting list is empty and the key is removed.LTRIM
generates anltrim
event, and additionally adel
event if the resulting list is empty and the key is removed.RPOPLPUSH
andBRPOPLPUSH
generate anrpop
event and anlpush
event. In both cases the order is guaranteed (thelpush
event will always be delivered after therpop
event). Additionally adel
event will be generated if the resulting list is zero length and the key is removed.LMOVE
andBLMOVE
generate anlpop
/rpop
event (depending on the wherefrom argument) and anlpush
/rpush
event (depending on the whereto argument). In both cases the order is guaranteed (thelpush
/rpush
event will always be delivered after thelpop
/rpop
event). Additionally adel
event will be generated if the resulting list is zero length and the key is removed.HSET
,HSETNX
andHMSET
all generate a singlehset
event.HINCRBY
generates anhincrby
event.HINCRBYFLOAT
generates anhincrbyfloat
event.HDEL
generates a singlehdel
event, and an additionaldel
event if the resulting hash is empty and the key is removed.SADD
generates a singlesadd
event, even in the variadic case.SREM
generates a singlesrem
event, and an additionaldel
event if the resulting set is empty and the key is removed.SMOVE
generates ansrem
event for the source key, and ansadd
event for the destination key.SPOP
generates anspop
event, and an additionaldel
event if the resulting set is empty and the key is removed.SINTERSTORE
,SUNIONSTORE
,SDIFFSTORE
generatesinterstore
,sunionstore
,sdiffstore
events respectively. In the special case the resulting set is empty, and the key where the result is stored already exists, adel
event is generated since the key is removed.ZINCR
generates azincr
event.ZADD
generates a singlezadd
event even when multiple elements are added.ZREM
generates a singlezrem
event even when multiple elements are deleted. When the resulting sorted set is empty and the key is generated, an additionaldel
event is generated.ZREMBYSCORE
generates a singlezrembyscore
event. When the resulting sorted set is empty and the key is generated, an additionaldel
event is generated.ZREMBYRANK
generates a singlezrembyrank
event. When the resulting sorted set is empty and the key is generated, an additionaldel
event is generated.ZDIFFSTORE
,ZINTERSTORE
andZUNIONSTORE
respectively generatezdiffstore
,zinterstore
andzunionstore
events. In the special case the resulting sorted set is empty, and the key where the result is stored already exists, adel
event is generated since the key is removed.XADD
generates anxadd
event, possibly followed anxtrim
event when used with theMAXLEN
subcommand.XDEL
generates a singlexdel
event even when multiple entries are deleted.XGROUP CREATE
generates anxgroup-create
event.XGROUP CREATECONSUMER
generates anxgroup-createconsumer
event.XGROUP DELCONSUMER
generates anxgroup-delconsumer
event.XGROUP DESTROY
generates anxgroup-destroy
event.XGROUP SETID
generates anxgroup-setid
event.XSETID
generates anxsetid
event.XTRIM
generates anxtrim
event.PERSIST
generates apersist
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, anevicted
event is generated. - Every time a new key is added to the data set, a
new
event is generated.
IMPORTANT all the commands generate events only if the target key is really modified. For instance an SREM
deleting a non-existing element from a Set will not actually change the value of the key, so no event will be generated.
If in doubt about how events are generated for a given command, the simplest thing to do is to watch yourself:
$ redis-cli config set notify-keyspace-events KEA
$ redis-cli --csv psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__key*__:*",1
At this point use redis-cli
in another terminal to send commands to the Redis server and watch the events generated:
"pmessage","__key*__:*","__keyspace@0__:foo","set"
"pmessage","__key*__:*","__keyevent@0__:set","foo"
...
Timing of expired events
Keys with a time to live associated are expired by Redis in two ways:
- When the key is accessed by a command and is found to be expired.
- Via a background system that looks for expired keys in the background, incrementally, in order to be able to also collect keys that are never accessed.
The expired
events are generated when a key is accessed and is found to be expired by one of the above systems, as a result there are no guarantees that the Redis server will be able to generate the expired
event at the time the key time to live reaches the value of zero.
If no command targets the key constantly, and there are many keys with a TTL associated, there can be a significant delay between the time the key time to live drops to zero, and the time the expired
event is generated.
Basically expired
events are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero.
Events in a cluster
Every node of a Redis cluster generates events about its own subset of the keyspace as described above. However, unlike regular Pub/Sub communication in a cluster, events' notifications are not broadcasted to all nodes. Put differently, keyspace events are node-specific. This means that to receive all keyspace events of a cluster, clients need to subscribe to each of the nodes.
@history
>= 6.0
: Key miss events were added.>= 7.0
: Event typenew
added