1.监听过期key
在Java中,使用KeyExpirationEventMessageListener的实现类来监听redis中即将过期的key,并调用onMessage方法对过期key进行处理,示例:
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
/**
* Creates new {@link MessageListener} for {@code __keyevent@*__:expired} messages.
*
* @param listenerContainer must not be {@literal null}.
*/
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
//接收到过期的key
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();//拿到key值
System.out.println("收到过期key:"+expiredKey);
super.onMessage(message, pattern);
}
}当然接收到KeyExpirationEvent的前提是redis-server配置文件里的notify-keyspace-events参数要打开,否则也是检测不到的,参数介绍参见文档
https://geek-docs.com/redis/redis-ask-answer/124_redis_notifykeyspaceevents_in_redis.html
在 Redis 中,键空间是指所有键的集合。每当执行与键相关的操作时,例如设置、修改、删除键等,Redis 都会生成相应的事件。通过配置 notify-keyspace-events 选项,我们可以开启对键空间事件的监听,从而实现实时监控和处理键空间的操作。
notify-keyspace-events 可以设置为以下各项的组合:
– K 键空间通知,所有通知事件都以keyspace@为前缀,并通过 PUBLISH 命令发送
– E 键事件通知,所有通知事件都以keyevent@为前缀,并通过 PUBLISH 命令发送
– g DEL、EXPIRE、RENAME等生成通知
– s SET、EXPIREAT等生成通知
– h HSET、HDEL等生成通知
– l LSET、LREM等生成通知
– z ZADD、ZREM等生成通知
– x 过期事件:当键被设置了过期时间时,会生成通知
– e 驱逐事件:当键因为空间被驱逐出去时,会生成通知
– A 任何事件都会生成通知# 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
# x Expired events (events generated every time a key expires)
# e Evicted events (events generated when a key is evicted for maxmemory)
# n New key events (Note: not included in the 'A' class)
# t Stream commands
# d Module key type events
# m Key-miss events (Note: It is not included in the 'A' class)
# A Alias for g$lshzxetd, so that the "AKE" string means all the events
# (Except key-miss events which are excluded from 'A' due to their
# unique nature).
示例 notify-keyspace-events "AKE"实际上这么做是有问题的,redis官方文档显示:
当某个键被访问,并被上述机制之一检测出已过期时,便会生成过期事件。因此,Redis服务器无法保证在键的生存时间精确变为零时立即生成过期事件。
也就是说,只有key被访问时(同时这个key濒临过期的情况下)才会触发过期事件,redis自己主动清理是不会触发过期事件的,因此这种对过期键的处理方式是有问题的.
当redis里的数据量很大时,对过期Key的正确的处理方式是什么?
2.过期key解决方案分析:
1.类似redis,提前将一些重要的key登记在缓存中,或者消息队列里,消费者每次向redis查询这些key的过期时间,并予以更新.
但假设有些Key已经被弃置了,这里就会有问题.一个比较好的方式是把key值单独放到一个redis里,消息队列的log只是起到一个崩溃恢复和重建的作用.
2.不过redis的问题是自己也会杀key,那其实不如使用elasticsearch来代替redis.
elasticsearch相当于一个分布式Map,redis就不是了.消息队列则是分布式日志,因此如果希望持久化的稳定的从Map里拿数据,还是应该用elasticsearch.
3.过期Key最终解决方案:
1.对于希望持久存在于redis里的key,可以用elasticsearch,存储这些key名
2.开启若干个定时服务,定时从elasticsearch里获取这些key,并在redis里更新过期时间
3.有些时候商品会下架,可能需要永远删除这个key,也就是不希望再更新这个key的过期时间了,就可以同步在elasticsearch里设置.这样定时任务就拿不到这个任务了.




