Spring Boot监听Redis Key失效事件实现定时任务的示例
业务场景
我们以订单功能为例说明下:
生成订单后一段时间不支付订单会自动关闭。最简单的想法是设置定时任务轮询,但是每个订单的创建时间不一样,定时任务的规则无法设定,如果将定时任务执行的间隔设置的过短,太影响效率。
还有一种想法,在用户进入订单界面的时候,判断时间执行相关操作。方式可能有很多,在这里介绍一种监听Redis键值对过期时间来实现订单自动关闭。
实现思路
在生成订单时,向Redis中增加一个KV键值对,K为订单号,保证通过K能定位到数据库中的某个订单即可,V可为任意值。
假设,生成订单时向Redis中存放K为订单号,V也为订单号的键值对,并设置过期时间为30分钟,如果该键值对在30分钟过期后能够发送给程序一个通知,或者执行一个方法,那么即可解决订单关闭问题。
实现:通过监听Redis提供的过期队列来实现,监听过期队列后,如果Redis中某一个KV键值对过期了,那么将向监听者发送消息,监听者可以获取到该键值对的K,注意,是获取不到V的,因为已经过期了,这就是上面所提到的,为什么要保证能通过K来定位到订单,而V为任意值即可。拿到K后,通过K定位订单,并判断其状态,如果是未支付,更新为关闭,或者取消状态即可。
开启Rediskey过期提醒
修改redis相关事件配置。找到redis配置文件redis.conf,查看notify-keyspace-events配置项,如果没有,添加notify-keyspace-eventsEx,如果有值,则追加Ex,相关参数说明如下:
- K:keyspace事件,事件以keyspace@为前缀进行发布
- E:keyevent事件,事件以keyevent@为前缀进行发布
- g:一般性的,非特定类型的命令,比如del,expire,rename等
- $:字符串特定命令
- l:列表特定命令
- s:集合特定命令
- h:哈希特定命令
- z:有序集合特定命令
- x:过期事件,当某个键过期并删除时会产生该事件
- e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件
- A:g$lshzxe的别名,因此”AKE”意味着所有事件
引入依赖
在pom.xml中添加org.springframework.boot:spring-boot-starter-data-redis依赖
org.springframework.boot spring-boot-starter-data-redis
相关配置
定义配置RedisListenerConfig实现监听Rediskey过期时间
importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.data.redis.connection.RedisConnectionFactory; importorg.springframework.data.redis.listener.RedisMessageListenerContainer; @Configuration publicclassRedisListenerConfig{ @Bean RedisMessageListenerContainercontainer(RedisConnectionFactoryconnectionFactory){ RedisMessageListenerContainercontainer=newRedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); returncontainer; } }
定义监听器RedisKeyExpirationListener,实现KeyExpirationEventMessageListener接口,查看源码发现,该接口监听所有db的过期事件keyevent@*:expired"
importorg.springframework.data.redis.connection.Message; importorg.springframework.data.redis.listener.KeyExpirationEventMessageListener; importorg.springframework.data.redis.listener.RedisMessageListenerContainer; importorg.springframework.stereotype.Component; /** *监听所有db的过期事件__keyevent@*__:expired" */ @Component publicclassRedisKeyExpirationListenerextendsKeyExpirationEventMessageListener{ publicRedisKeyExpirationListener(RedisMessageListenerContainerlistenerContainer){ super(listenerContainer); } /** *针对redis数据失效事件,进行数据处理 *@parammessage *@parampattern */ @Override publicvoidonMessage(Messagemessage,byte[]pattern){ //获取到失效的key,进行取消订单业务处理 StringexpiredKey=message.toString(); System.out.println(expiredKey); } }
到此这篇关于SpringBoot监听RedisKey失效事件实现定时任务的示例的文章就介绍到这了,更多相关SpringBootRedisKey失效内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!