redis 过期监听场景
业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭订单 . 网上有很多使用 redis 过期监听的 demo
redis配置
把notify-keyspace-events ex 这一行的注释打开
项目demo工程
项目结构如下图
maven依赖
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactid>kim-redis</artifactid>
<groupid>com.kim</groupid>
<version>1.0.0</version>
</parent>
<modelversion>4.0.0</modelversion>
<artifactid>kim-redis-expiration-notice</artifactid>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
</dependency>
<dependency>
<groupid>org.apache.commons</groupid>
<artifactid>commons-pool2</artifactid>
</dependency>
</dependencies>
</project>
配置文件
server:
port: 20103
spring:
redis:
#数据库索引
database: 0
host: 127.0.0.1
port: 6379
password: 123456
lettuce:
pool:
#最大连接数
max-active: 8
#最大阻塞等待时间(负数表示没限制)
max-wait: -1
#最大空闲
max-idle: 8
#最小空闲
min-idle: 0
#连接超时时间
timeout: 10000
启动类
/**
* @project: kim-redis
* @packagename: com.kim.redis.expiration.notice
* @filename: noticeapplication.java
* @description: the noticeapplication is...
* @author: kimwu
* @time: 2020-12-19 14:01:56
*/
@springbootapplication
public class noticeapplication {
public static void main(string[] args) {
springapplication.run(noticeapplication.class, args);
}
}
配置类
@configuration
public class redistimeoutconfiguration {
@autowired
private redisconnectionfactory redisconnectionfactory;
@bean
public redismessagelistenercontainer redismessagelistenercontainer() {
redismessagelistenercontainer redismessagelistenercontainer = new redismessagelistenercontainer();
redismessagelistenercontainer.setconnectionfactory(redisconnectionfactory);
return redismessagelistenercontainer;
}
@bean
public keyexpiredlistener keyexpiredlistener() {
return new keyexpiredlistener(this.redismessagelistenercontainer());
}
}
监听类
@slf4j
public class keyexpiredlistener extends keyexpirationeventmessagelistener {
public keyexpiredlistener(redismessagelistenercontainer listenercontainer) {
super(listenercontainer);
}
@override
public void onmessage(message message, byte[] pattern) {
string channel = new string(message.getchannel(), standardcharsets.utf_8);
//过期的key
string key = new string(message.getbody(), standardcharsets.utf_8);
log.info("redis key 过期:pattern={},channel={},key={}", new string(pattern), channel, key);
}
}
异常情况测试
当key过期时,项目宕机了
①写入redis的key
②手动关停服务,等待redis的key过期
③确认redis的key过期后,重启服务。服务不会收到通知
当key过期时,redis服务宕机了
①写入redis的key
②关停redis服务,等待redis的key过期
③启动redis服务,发现redis的过期key已经不存在了,服务没有收到通知
结论
redis的键过期本身不可靠,并不像rabbitmq一样保证了可靠性。
当服务本身宕机或者redis宕机时,将无法保证过期的key能够被消费。
当使用场景对数据完整性不那么精确时,可以使用redis的键过期策略。否则不太建议使用redis的键过期策略。
到此这篇关于使用redis实现延迟通知功能(redis过期键通知)的文章就介绍到这了,更多相关redis过期键通知内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!