Spring boot实现监听Redis key失效事件实现和其它方式
需求:
处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态
用户绑定隐私号码当订单结束取消绑定等
解决方案1:
可以利用redis自带的key自动过期机制,下单时将订单id写入redis,过期时间30分钟,30分钟后检查订单状态,如果未支付,则进行处理但是key过期了redis有通知吗?答案是肯定的。
开启redis key过期提醒
修改redis相关事件配置。找到redis配置文件redis.conf,只需修改配置文件redis.conf中的:notify-keyspace-events Ex,默认为notify-keyspace-events "", 查看“notify-keyspace-events”的配置项,如果没有,添加“notify-keyspace-events Ex”,如果有值,添加Ex,相关参数说明如下:
- K:keyspace事件,事件以__keyspace@<db>__为前缀进行发布;
- E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布;
- g:一般性的,非特定类型的命令,比如del,expire,rename等;
- $:字符串特定命令;
- l:列表特定命令;
- s:集合特定命令;
- h:哈希特定命令;
- z:有序集合特定命令;
- x:过期事件,当某个键过期并删除时会产生该事件;
- e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件;
- A:g$lshzxe的别名,因此”AKE”意味着所有事件。
Redis测试:
打开一个redis-cli ,监控db0的key过期事件
打开另一个redis-cli ,发送定时过期key
观察上一个redis-cli ,会发现收到了过期的key hello,但是无法收到过期的value world
根据这个特性在springboot中使用
1.pom 中添加依赖
- <!-- redis -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
2.定义配置RedisListenerConfig
- /**
- * @author mazhq
- * @Title: RedisListenerConfig
- * @ProjectName: zeus
- * @date 2019/2/20 11:25
- */
- @Configuration
- public class RedisListenerConfig {
- @Bean
- RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
- RedisMessageListenerContainer container = new RedisMessageListenerContainer();
- container.setConnectionFactory(connectionFactory);
- //container.addMessageListener(new RedisExpiredListener(), new PatternTopic("__keyevent@0__:expired"));
- return container;
- }
- }
- 3.定义监听器,实现
KeyExpirationEventMessageListener
接口,查看源码发现,该接口监听所有db的过期事件keyevent@*:expired"
- /**
- * @author mazhq
- * @Title: RedisKeyExpirationListener
- * @ProjectName: zeus
- * @date 2019/2/20 11:26
- */
- @Component
- public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
- private final static Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListener.class);
- @Autowired
- private RedisClient redisClient;
- /**
- * Creates new {@link MessageListener} for {@code __keyevent@*__:expired} messages.
- *
- * @param listenerContainer must not be {@literal null}.
- */
- public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
- super(listenerContainer);
- }
- @Override
- public void onMessage(Message message, byte[] pattern) {
- // 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
- String expiredKey = message.toString();
- if(expiredKey.startsWith("zeus:order")){
- //TODO
- }
- }
- }
或者打开RedisListenerConfig
中 container.addMessageListener(new RedisExpiredListener(), new PatternTopic("__keyevent@0__:expired"));
注释,再定义监听器,监控__keyevent@0__:expired
事件,即db0过期事件
。这个地方定义的比较灵活,可以自己定义监控什么事件。
- public class RedisExpiredListener implements MessageListener {
- /**
- * 客户端监听订阅的topic,当有消息的时候,会触发该方法;
- * 并不能得到value, 只能得到key。
- * 姑且理解为: redis服务在key失效时(或失效后)通知到java服务某个key失效了, 那么在java中不可能得到这个redis-key对应的redis-value。
- * * 解决方案:
- * 创建copy/shadow key, 例如 set vkey "vergilyn"; 对应copykey: set copykey:vkey "" ex 10;
- * 真正的key是"vkey"(业务中使用), 失效触发key是"copykey:vkey"(其value为空字符为了减少内存空间消耗)。
- * 当"copykey:vkey"触发失效时, 从"vkey"得到失效时的值, 并在逻辑处理完后"del vkey"
- *
- * 缺陷:
- * 1: 存在多余的key; (copykey/shadowkey)
- * 2: 不严谨, 假设copykey在 12:00:00失效, 通知在12:10:00收到, 这间隔的10min内程序修改了key, 得到的并不是 失效时的value.
- * (第1点影响不大; 第2点貌似redis本身的Pub/Sub就不是严谨的, 失效后还存在value的修改, 应该在设计/逻辑上杜绝)
- * 当"copykey:vkey"触发失效时, 从"vkey"得到失效时的值, 并在逻辑处理完后"del vkey"
- *
- */
- @Override
- public void onMessage(Message message, byte[] bytes) {
- byte[] body = message.getBody();// 建议使用: valueSerializer
- byte[] channel = message.getChannel();
- System.out.print("onMessage >> " );
- System.out.println(String.format("channel: %s, body: %s, bytes: %s"
- ,new String(channel), new String(body), new String(bytes)));
- }
- }
解决方案2
使用spring + quartz定时任务(支持任务信息写入mysql,多节点分布式执行任务
),下单成功后,生成一个30分钟后运行的任务,30分钟后检查订单状态,如果未支付,则进行处理
解决方案3
将订单过期时间信息写入mysql,按分钟轮询查询mysql,如果超时则进行处理,效率差!时间精准度底!
结论
推荐使用方案1和方案2
Spring boot实现监听Redis key失效事件实现和其它方式的更多相关文章
- 【Redis系列】Spring boot实现监听Redis key失效事件
talk is cheap, show me the code. 一.开启Redis key过期提醒 方式二:修改配置文件 redis.conf # 默认 notify-keyspace-events ...
- SpringBoot实现监听redis key失效事件
需求: 处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态 解决方案1: 可以利用redis天然的key自动过期机制,下单时将订单id写入redis,过期时间30分钟,30分钟后检查订单状态 ...
- 订单超时、活动过期解决方案:php监听redis key失效触发回调事件
Redis 的 2.8.0 版本之后可用,键空间消息(Redis Keyspace Notifications),配合 2.0.0 版本之后的 SUBSCRIBE 就能完成这个定时任务的操作了,定时的 ...
- Node.js 中监听 redis key 过期事件
It is in fact possible to listen to the “expired” type keyevent notification using a subscribed clie ...
- springboot redis 监听过期key值事件
redis 中的key值过期后,触发通知事件 1.创建springboot工程,创建监听类 maven配置 <dependencies> <dependency> <gr ...
- springboot使用Redis,监听Redis键过期的事件设置与使用代码
我使用的是Windows下的Redis服务,所以一下Redis设置都是在Windows平台进行. 1.修改Redis配置文件 1.1:Windows下的Redis存在两个配置文件 修改带有servic ...
- Spring Boot 2.x整合Redis
最近在学习Spring Boot 2.x整合Redis,在这里和大家分享一下,希望对大家有帮助. Redis是什么 Redis 是开源免费高性能的key-value数据库.有以下的优势(源于Redis ...
- Spring boot配置多个Redis数据源操作实例
原文:https://www.jianshu.com/p/c79b65b253fa Spring boot配置多个Redis数据源操作实例 在SpringBoot是项目中整合了两个Redis的操作实例 ...
- 7、Spring Boot 2.x 集成 Redis
1.7 Spring Boot 2.x 集成 Redis 简介 继续上篇的MyBatis操作,详细介绍在Spring Boot中使用RedisCacheManager作为缓存管理器,集成业务于一体. ...
随机推荐
- 浅谈css中渐变衔接
无论transition还是keyframes,如何让变化更自然,这是前端应该考虑的问题. 这里,我简单总结下自己的方法. 以实践为例子. 1.图像渐变 @keyframes looppic{ fro ...
- python 文件不存在时才能写入,读写模式xt
想向一个文件中写入数据,但是前提必须是这个文件在文件系统上不存在.也就是不允许覆盖已存在的文件内容. 可以在open() 函数中使用x 模式来代替w 模式的方法来解决这个问题.比如: >> ...
- 如何安装nginx_lua_module模块,升级nginx,nginx-lua-fastdfs-GraphicsMagick动态生成缩略图,实现图片自动裁剪缩放
如何安装nginx_lua_module模块,升级nginx,nginx-lua-fastdfs-GraphicsMagick动态生成缩略图,实现图片自动裁剪缩放 参考网站:nginx-lua-fas ...
- mysql下的将多个字段名的值复制到另一个字段名中(批量更新数据)字符串拼接cancat实战例子
mysql下的将多个字段名的值复制到另一个字段名中(批量更新数据)mysql字符串拼接cancat实战例子: mysql update set 多个字段相加,如果是数字相加可以直接用+号(注:hund ...
- 一起来全面解析5G网络领域最关键的十大技术
提到5G,很多人的第一印象就是它的网络速度快.延时性低.带宽大,没错,这就是5G时代的特点!5G作为第五代移动通信网络,其峰值理论传输速度可达每秒数十Gb,这比4G网络的传输速度快数百倍,整部超高画质 ...
- 深入浅出JavaScript运行机制
一.引子 本文介绍JavaScript运行机制,这一部分比较抽象,我们先从一道面试题入手: console.log(1); setTimeout(function(){ console.log(3); ...
- golang debug调试
1. debug by gdb: office doc download the runtime-gdb file. $ wget -q -O - https://golang.org/src/run ...
- 如何写出安全的 API 接口?接口参数加密签名设计思路
原文链接:http://blog.csdn.net/ma_jiang/article/details/53636840
- 启动jenkins服务错误
背景 重新安装了jenkins,需要启动,使用的yum install安装的,启动jenkins的话只需要执行service jenkins start,但出了两个问题 1. 是提示找不到java 2 ...
- Wannafly14挑战赛 C(tarjan缩点)题解
题目:牛客题目链接 思路:这道题有点像这道题 先缩点,缩完之后判断一下整个强连通分量入度是不是0,如果是的话向ans压入该强连通分量最小的那个值.最后排序一下ans输出就行了. 思路一下就想到了,就是 ...