【Redis系列】Spring boot实现监听Redis key失效事件
talk is cheap, show me the code.
一、开启Redis key过期提醒
方式二:修改配置文件
redis.conf# 默认 notify-keyspace-events ""
notify-keyspace-events Ex
方式二:命令行开启
CONFIG SET notify-keyspace-events Ex
CONFIG GET notify-keyspace-events
二、notify-keyspace-events
notify-keyspace-events 选项的默认值为空
notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知。
| 字符 | 发送的通知 |
|---|---|
| K | 键空间通知,所有通知以 keyspace@ 为前缀 |
| E | 键事件通知,所有通知以 keyevent@ 为前缀 |
| g | DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知 |
| $ | 字符串命令的通知 |
| l | 列表命令的通知 |
| s | 集合命令的通知 |
| h | 哈希命令的通知 |
| z | 有序集合命令的通知 |
| x | 过期事件:每当有过期键被删除时发送 |
| e | 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送 |
| A | 参数 g$lshzxe 的别名 |
三、Coding
初始化一个
Spring Boot项目pom.xml<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
定义配置类
RedisListenerConfig@Configuration
public class RedisListenerConfig { @Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
} }
定义数据生产类
ProviderDataToRedis@Slf4j
@Component
public class ProviderDataToRedis implements CommandLineRunner { @Autowired
private StringRedisTemplate stringRedisTemplate; @Override
public void run(String... args) throws Exception {
int[] num = new int[]{1};
Random random = new Random();
while (true) {
int max = random.nextInt(5);
IntStream.range(0, max).forEach(n -> stringRedisTemplate.opsForValue().set(String.format("mq:s1:%s", ++num[0]), "已预订", 5, TimeUnit.SECONDS));
log.info("放了 {} 条数据到redis...", max);
TimeUnit.SECONDS.sleep(3);
}
}
}
定义监听器 实现
KeyExpirationEventMessageListener接口查看源码发现,该接口监听所有db的过期事件
keyevent@*:expired"定义
Status1ExpirationListener监听状态1到期@Slf4j
@Component
public class Status1ExpirationListener extends KeyExpirationEventMessageListener { public Status1ExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
} @Autowired
private StringRedisTemplate stringRedisTemplate; @Override
public void onMessage(Message message, byte[] pattern) {
// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
String expiredKey = message.toString();
if (expiredKey.startsWith("mq:s1:")) {
log.info("-----------------------------------");
log.info(String.format("过期key[%s]", expiredKey));
String newKey = String.format("mq:s2:%s", expiredKey.substring(6));
String newValue = "行程中";
stringRedisTemplate.opsForValue().set(newKey, newValue, 3, TimeUnit.SECONDS);
log.info(String.format("%s: %s", newKey, newValue));
log.info("-----------------------------------");
}
} }
定义
Status2ExpirationListener监听状态2到期@Slf4j
@Component
public class Status2ExpirationListener extends KeyExpirationEventMessageListener { public Status2ExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
} @Override
public void onMessage(Message message, byte[] pattern) {
// 用户做自己的业务处理即可,注意message.toString()可以获取失效的key
String expiredKey = message.toString();
if (expiredKey.startsWith("mq:s2:")) {
log.info("***********************************");
log.info(String.format("过期key[%s]", expiredKey));
log.info("[{}]行程已完成,修改数据库状态。", newKey);
log.info("***********************************");
}
} }
四、测试输出
...
2021-01-25 23:16:58.012 INFO 55511 --- [ main] n.y.tools.listener.ProviderDataToRedis : 放了 4 条数据到redis...
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : 过期key[mq:s1:272]
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : 过期key[mq:s1:271]
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : mq:s2:272: 行程中
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : mq:s2:271: 行程中
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : 过期key[mq:s2:270]
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : [270]行程已完成,修改数据库状态。
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : 过期key[mq:s2:269]
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : 过期key[mq:s2:268]
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : [269]行程已完成,修改数据库状态。
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : [268]行程已完成,修改数据库状态。
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : 过期key[mq:s2:267]
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : [267]行程已完成,修改数据库状态。
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : ***********************************
...
五、一直增加的线程数
从测试输出的日志中可以看出,线程一直在增加,这个问题还有待解决!
六、参考
http://redisdoc.com/topic/notification.html
【Redis系列】Spring boot实现监听Redis key失效事件的更多相关文章
- Spring boot实现监听Redis key失效事件实现和其它方式
需求: 处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态 用户绑定隐私号码当订单结束取消绑定等 解决方案1: 可以利用redis自带的key自动过期机制,下单时将订单id写入redis,过 ...
- 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 如何快速集成 Redis 哨兵?
上一篇:Spring Boot 如何快速集成 Redis? 前面的分享栈长介绍了如何使用 Spring Boot 快速集成 Redis,上一篇是单机版,也有粉丝留言说有没有 Redis Sentine ...
- 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的操作实例 ...
- Spring Boot 多站点利用 Redis 实现 Session 共享
如何在不同站点(web服务进程)之间共享会话 Session 呢,原理很简单,就是把这个 Session 独立存储在一个地方,所有的站点都从这个地方读取 Session. 通常我们使用 Redis 来 ...
- 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁
spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...
- 7、Spring Boot 2.x 集成 Redis
1.7 Spring Boot 2.x 集成 Redis 简介 继续上篇的MyBatis操作,详细介绍在Spring Boot中使用RedisCacheManager作为缓存管理器,集成业务于一体. ...
随机推荐
- Python十大装B语法!你会几种?
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 Python 是一种代表简单思想的语言,其语法相对简单,很容易上手.不过,如果就此小视 Python ...
- asp.net webapi 给字段赋初始值DefaultValue 解决前端传空字符串后台接受不是“”而是NULL
/// <summary> /// 存储ID /// </summary> public Guid SaveID { get; set; } /// <summary&g ...
- 阿里巴巴java开发手册-泰山版 下载
最近,阿里的<Java开发手册>又更新了,这个版本历经一年的修炼,取名:<Java开发手册(泰山版)>正式出道.正所谓无规矩不成方圆,在程序员的世界里,也存在很多规范,阿里出版 ...
- 人脸识别--SeetaFace
检测:http://download.csdn.net/detail/qq_14845119/9639840 对齐:http://download.csdn.net/detail/qq_1484511 ...
- Java学习日报7.17
控制台运行
- C语言中一维数组
(1)输出数组元素 #include<stdio.h> int main() { int index; /*定义循环变量*/ int iArray[6]={0,1,2,3,4,5}; /* ...
- springcloud学习(一)之Eureka
前言 微服务原则上是应该有多个服务提供者的实例的,在通常情况下服务提供者的数量和分布往往是动态变化的,这样在传统的单体应用中的那种硬编码服务url进行远程调用的方式就不足取.服务注册中心就是为了解决服 ...
- DRF之访问权限控制和访问频率控制(节流)
权限控制 前言 用户验证用户权限,根据不同访问权限控制对不同内容的访问. 建议了解视图.token验证的内容. 使用流程 自定义访问权限类,继承BasePermission,重写has_permiss ...
- 一张图看懂sql的各种join
下图展示了 LEFT JOIN.RIGHT JOIN.INNER JOIN.OUTER JOIN 相关的 7 种用法.
- 风炫安全web安全学习第三十三节课 文件包含漏洞基础以及利用伪协议进行攻击
风炫安全web安全学习第三十三节课 文件包含漏洞基础以及利用伪协议进行攻击 文件包含漏洞 参考文章:https://chybeta.github.io/2017/10/08/php文件包含漏洞/ 分类 ...