优雅使用Redis键过期事件
背景
基于Redis的主动事件的处理,比如:当用户购买了会员卡
十分钟
内没有付款,需要通过小程序或者APP向用户主动推送购买会员卡的优势,引导用户继续完成支付并购买等,类似的场景需要用户在指定的时间点后
主动通知或者继续引导,使用Redis过期键Event
优雅、快捷的实现
实战
在Redis中有两种通知:
类型:
- 键空间通知:Keyspace@<db>_:mykey(针对mykey的所有的操作的通知)
- 键事件通知:Keyevent@<db>_:expired (键的过期事件)
解释:
- KeySpace键空间通知。即针对
指定key
发生的一切改动,推送给订阅的客户端,侧重于针对指定Key
的操作;比如Keyspace@0:mykey,当更新、删除mykey时,会推送该事件 - keyEvent键时间通知。侧重于指定的事件,如:expired(过期事件)、DEL(删除键事件)等;所有的键不针对指定的键,如果要筛选键要通过代码完成
实现方式共有两种方式:(基于Spring Boot完成)
RedisMessageListenerContainer
在Spring Boot 启动之后,最后通过(SmartLifecycle
)启动,通过定时任务每隔两秒执行一次订阅的任务,一旦有消息,则遍历所有的MessageListener,通过OnMessage方法执行;所以:
- 继承
MessageListenerAdapter
监听器,重写OnMessage方法 - 继承
KeyExpirationEventMessageListener
监听器, 重写doHandleMessage方法
以下分别详细讲述实现方式:(关于Redis相关数据源的配置,暂不包括)
MessageListenerAdapter监听器
通过适配器自定义监听器后,需要单独配置RedisMessageListerContainer的MessageListener以及监听Pattern(Keyspace或者Keyevent、db、事件),如下:
@Bean
@ConditionalOnMissingBean(RedisMessageListenerContainer.class)
public RedisMessageListenerContainer container(){
RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
//连接池的设置,暂不描述
listenerContainer.setConnectionFactory(jedisConnectionFactory());
//添加自定义的监听器,并将指定的事件添加进去
listenerContainer.addMessageListener(new MyKeyExpireListener(),new PatternTopic("__keyevent@12__:expired"));
return listenerContainer;
}
KeyExpirationEventMessageListener监听器
KeyExpirationEventMessageListener继承自KeyspaceEventMessageListener,而KeyspaceEventMessageListener监听所有db的Keyevent,而KeyExpirationEventMessageListener专门监听Key的过期事件的类;然后基于Spring Boot 的事件通知机制,当监听到所有db库中的key有过期事件时,通过ApplicationContext发送RedisKeyExpiredEvent事件,消息体即Key;通过继承KeyExpirationEventMessageListener无需再设置RedisMEssageListenerContainer,通过@Compont注解,让IOC容器发现即可
缺点:
Key的过期事件通知,无法将value也通知到,消息体只有key,在某些场景下,需要将key-Value在储存另外一份作为映射,或者拿到key以后再基于数据库进行操作;
https://magical-life.coding.me/
欢迎评论区拍砖