1.需求
处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态
2.方案
可以利用redis天然的key自动过期机制,下单时将订单id写入redis,过期时间30分钟,30分钟后检查订单状态,如果未支付,则进行处理但是key过期了redis有通知吗?答案是肯定的。
3.试验步骤
3.1.开启redis key过期提醒
修改redis相关事件配置。找到redis配置文件redis.conf,查看“notify-keyspace-events”的配置项,如果没有,添加“notify-keyspace-events Ex”,如果有值,添加Ex,相关参数说明如下:
E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布;
x:过期事件,当某个键过期并删除时会产生该事件;
3.2.redis测试
打开一个redis-cli ,监控db0的key过期事件
127.0.0.1:6379> PSUBSCRIBE __keyevent@0__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@0__:expired"
3) (integer) 1
打开另一个redis-cli ,发送定时过期key
127.0.0.1:6379> setex test_key 3 test_value
观察上一个redis-cli ,会发现收到了过期的keytest_key,但是无法收到过期的value test_value
127.0.0.1:6379> PSUBSCRIBE __keyevent@0__:expired
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyevent@0__:expired"
3) (integer) 1
1) "pmessage"
2) "__keyevent@0__:expired"
3) "__keyevent@0__:expired"
4) "test_key"
4.在springboot中使用
4.1.定义监听器
定义监听器,监控__keyevent@0__:expired事件,即db0过期事件。
package com.easygo.listener;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
/**
* @BelongsProject: easygo
* @Description: 配置的Redis消息的监听器,获取redis的消息并进行处理
*/
public class RedisMessageListener implements MessageListener {
/**
* message:要处理的消息
* @param message 消息内容
* @param pattern 获取的频道信息
*/
@Override
public void onMessage(Message message, byte[] pattern) {
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(pattern)));
}
}
4.2.定义配置RedisListenerConfig
/**
* @BelongsProject: easygo
* @BelongsPackage: com.easygo.config
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-04-08 11:20
* @Description: SpringBoot整合SpringData Redis
*/
@Configuration
public class RedisConfig {
@Bean
RedisMessageListenerContainer container(@Qualifier("jedisConnectionFactory") JedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener(new RedisMessageListener(), new PatternTopic("__keyevent@0__:expired"));
return container;
}
}
4.3.新增key并设置过期时间
/**
* 新增Redis并设置Redis的key的过期时间
*/
@Test
public void testSetValueWithTimeOut() {
//key的过期时间是10秒种自动失效
redisTemplate.opsForValue().set("message", "各位老司机,开往红浪漫的车已经发车...", 30L, TimeUnit.SECONDS);
System.out.println("设置完成");
}
4.4.查询key的过期时间
public Long testTimeTTL(){
//根据key获取过期时间
Long time1 = redisTemplate.getExpire("baike");
//根据key获取过期时间并换算成指定单位
Long time2 = redisTemplate.getExpire("baike", TimeUnit.SECONDS);
System.out.println(time2);
return time2;
}
3648



被折叠的 条评论
为什么被折叠?



