业务场景:
处理订单过期自动取消这个业务,用户下单15分钟内未支付,我们需要自动修改订单状态
实现逻辑:
当用户下单的时候生成一条订单插入数据库,并将这条订单的id或者code设置15分钟过期事件存入redis,然后监听redis过期事件,如果是订单过期未支付就修改订单状态
修改redis配置文件:
我们要开启redis key过期提醒,修改redis相关事件配置。找到redis配置文件redis.conf,修改配置文件中 notify-keyspace-events "Ex",注意:这个双引号是一定要的,否则配置不成功,启动也不报错。例如,“Ex”表示想监控某个Key的过期事件,相关参数如下:
K:keyspace事件,事件以__keyspace@<db>__为前缀进行发布;
E:keyevent事件,事件以__keyevent@<db>__为前缀进行发布;
g:一般性的,非特定类型的命令,比如del,expire,rename等;
$:字符串特定命令;
l:列表特定命令;
s:集合特定命令;
h:哈希特定命令;
z:有序集合特定命令;
x:过期事件,当某个键过期并删除时会产生该事件;
e:驱逐事件,当某个键因maxmemore策略而被删除时,产生该事件;
A:g$lshzxe的别名,因此”AKE”意味着所有事件。
测试是否成功:
打开两个redis客户端,一个监听过期事件,一个发送消息,这里我们就是监听db0数据库的过期事件,然后存入一个order_key,5秒过期
监听端:
PSUBSCRIBE __keyevent@0__:expired
发送端:
然后我们查看监控的客户端发现已经监听到了:
测试成功!这里会发现收到了过期的keytest_key
,但是无法收到过期的value test_value
代码编写:
1.pom文件添加对redis的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置redis监听容器
package net.xdclass.base_project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
/**
* @author sqz
* @Description: redis监听配置类
* @date 2019/3/22 10:23
*/
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
// container.addMessageListener(new RedisExpiredListener(), new PatternTopic("__keyevent@0__:expired"));
return container;
}
}
3.定义监听器:
package net.xdclass.base_project.listener;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* @author sqz
* @Description: 监听所有db的过期事件__keyevent@*__:expired"
* @date 2019/3/22 10:30
*/
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/**
* 针对redis数据失效事件,进行数据处理
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
String expiredKey = message.toString();
if(expiredKey.startsWith("order_key")){
//如果是order_key开头的key,进行处理
System.out.println("order_key");
}
}
}
4.测试:
启动springboot项目,然后存入order_key,发现监听成功!
参考:https://www.jianshu.com/p/106f0eae07c8
源码地址:https://gitee.com/xuxinsunqizheng/springboot_module.git