Redis集群下过期key监听
1. 前言
在使用redis集群时,发现过期key始终监听不到。网上也没有现成的解决方案。于是想,既然不能监听集群,那我可以建立多个redis连接,分别对每个redis的key过期进行监听。以上做法可能不尽人意,目前也没找到好的解决方案,如果有好的想法,请留言告知哦!不多说,直接贴我自己的代码!
2. 代码实现
关于Redis集群配置代码此处不贴,直接贴配置监听类代码!
redis.host1: 10.113.56.68
redis.port1: 7030
redis.host2: 10.113.56.68
redis.port2: 7031
redis.host3: 10.113.56.68
redis.port3: 7032
redis.host4: 10.113.56.68
redis.port4: 7033
redis.host5: 10.113.56.68
redis.port5: 7034
redis.host6: 10.113.56.68
redis.port6: 7035
application配置类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig; import java.util.Arrays; /**
* @Author xiabing5
* @Create 2019/8/6 14:46
* @Desc 监听redis中Key过期事件
**/
@Configuration
public class RedisListenerConfig { @Value("${redis.host1}")
private String host1; @Value("${redis.host2}")
private String host2; @Value("${redis.host3}")
private String host3; @Value("${redis.host4}")
private String host4; @Value("${redis.host5}")
private String host5; @Value("${redis.host6}")
private String host6; @Value("${redis.port1}")
private int port1; @Value("${redis.port2}")
private int port2; @Value("${redis.port3}")
private int port3; @Value("${redis.port4}")
private int port4; @Value("${redis.port5}")
private int port5; @Value("${redis.port6}")
private int port6; @Bean
JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(100);
jedisPoolConfig.setMaxWaitMillis(1000);
return jedisPoolConfig;
} // redis-cluster不支持key过期监听,建立多个连接,对每个redis节点进行监听
@Bean
RedisMessageListenerContainer redisContainer1() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host1);
jedisConnectionFactory.setPort(port1);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisMessageListenerContainer redisContainer2() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host2);
jedisConnectionFactory.setPort(port2);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisMessageListenerContainer redisContainer3() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host3);
jedisConnectionFactory.setPort(port3);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisMessageListenerContainer redisContainer4() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host4);
jedisConnectionFactory.setPort(port4);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisMessageListenerContainer redisContainer5() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host5);
jedisConnectionFactory.setPort(port5);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisMessageListenerContainer redisContainer6() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(host6);
jedisConnectionFactory.setPort(port6);
jedisConnectionFactory.setPoolConfig(jedisPoolConfig());
jedisConnectionFactory.afterPropertiesSet();
container.setConnectionFactory(jedisConnectionFactory);
return container;
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener1() {
return new RedisKeyExpirationListener(redisContainer1());
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener2() {
return new RedisKeyExpirationListener(redisContainer2());
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener3() {
return new RedisKeyExpirationListener(redisContainer3());
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener4() {
return new RedisKeyExpirationListener(redisContainer4());
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener5() {
return new RedisKeyExpirationListener(redisContainer5());
} @Bean
RedisKeyExpirationListener redisKeyExpirationListener6() {
return new RedisKeyExpirationListener(redisContainer6());
} }
Bean配置类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import java.util.Date; /**
* @Author xiabing5
* @Create 2019/9/4 9:47
* @Desc redis过期监听
**/
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { @Autowired
RedisUtil redisUtil; @Autowired
LoginUserStatisticsMapper loginUserStatisticsMapper; public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
} @Override
public void onMessage(Message message, byte[] pattern) {
// 用户做自己的业务处理即可,message.toString()可以获取失效的key
String mesg = message.toString(); }
}
监听操作类
3. Redis防止过期key重复监听
对于项目集群情况下,部署多个服务后,容易出现redis过期被多个服务同时监听到,从而执行相同的业务逻辑,这不是我们期望的。单机部署下方法的同步可以采用synchronize关键字。但集群下,就得采用分布式锁。在需要加锁的地方,只要加锁和解锁即可。此处正好写到Redis,那就贴一个自己用的redis分布式锁。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis; import java.util.Collections;
import java.util.UUID; /**
* @Author xiabing5
* @Create 2019/9/6 15:54
* @Desc redis分布式锁
**/
@Component
public class RedisLock { @Autowired
Jedis jedis; private static final String SET_IF_NOT_EXIST = "NX"; // NX表示如果不存在key就设置value
private static final String SET_WITH_EXPIRE_TIME = "PX"; // PX表示毫秒 // 加锁
public String tryLock(String key,Long acquireTimeout) {
// 生成随机value
String identifierValue = UUID.randomUUID().toString();
// 设置超时时间
Long endTime = System.currentTimeMillis() + acquireTimeout;
// 循环获取锁
while (System.currentTimeMillis() < endTime) {
String result = jedis.set(key,identifierValue, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, acquireTimeout);
if("OK".equals(result)) {
return identifierValue;
}
}
return null;
} // 解锁
// public void delLock(String key,String identifierValue) {
// // 判断是否是同一把锁
// try{
// if(jedis.get(key).equals(identifierValue)){
// // 此处操作非原子性,容易造成释放非自己的锁
// jedis.del(key);
// }
// }catch(Exception e) {
// e.printStackTrace();
// }
// } // 使用Lua代码解锁
public void delLock(String key,String identifierValue) {
try{
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Long result = (Long) jedis.eval(script, Collections.singletonList(key), Collections.singletonList(identifierValue));
if (1 == result) {
System.out.println(result+"释放锁成功");
} if (0 == result) {
System.out.println(result+"释放锁失败");
}
}catch (Exception e) {
e.printStackTrace();
}
} }
Redis锁解决分布式同步问题
4. 总结
自己实现的一个小demo,废话比较少。小白自己写的配置类,理解有问题请留言!自己实现的方案感觉不妥,只是基本完成需求,还得继续研究。
Redis集群下过期key监听的更多相关文章
- SpringBoot整合redis实现过期key监听事件
Spring整合redis实现key过期事件监听:https://www.cnblogs.com/pxblog/p/13969375.html 可以用于简单的过期订单取消支付.7天自动收货场景中 1. ...
- redis入门(14)redis集群下的数据分区存储
redis入门(10)redis集群下的数据分区存储
- redis过期key监听事件
目录 redis安装 docker拉取 启动 redis 配置 命令监听 问题 程序监听 具体监听类 效果 总结 redis常用语缓存操作,但是redis功能不仅仅于此.今天我们来看看redis的ke ...
- spring+redis 集群下的操作
文章就是记录一下工作当中的用到的点,与测试方法以备用,会不断更新. 配置文件spring-redis.xml: <?xml version="1.0" encoding=&q ...
- 【Redis过期Key监听】
https://blog.csdn.net/wlddhj/article/details/89881055
- Python scan查找Redis集群中的key
import redis import sys from rediscluster import StrictRedisCluster #host = "172.17.155.118&quo ...
- Redis集群环境下的键值空间监听事件实现方案
一直想记录工作中遇到的问题和解决的方法,奈何没有找到一方乐土,最近经常反思,是否需要记录平时的点滴,后台还是决定下定决心记录一些,以便以后用到的时候找不着,实现这样的一个功能主要也是业务所需要的. 需 ...
- Spring整合redis实现key过期事件监听
打开redis服务的配置文件 添加notify-keyspace-events Ex 如果是注释了,就取消注释 这个是在以下基础上进行添加的 Spring整合redis:https://www. ...
- 离线安装redis集群
Step0:redis集群组件需求 Step1:离线安装ruby Step2:离线安装rubygems Step3:安装rubygems的 redis api Step4:离线安装tcl 8.6 St ...
随机推荐
- 通过自制yum源离线安装ansible
系统环境 --CentOS release 7 python版本--Python 3.5.4 背景:在企业环境中,安装ansible的服务器往往不能访问互联网,简单的下载ansible源码安装,会 ...
- jquery 动态载入页面,并且保证 url 变动
最近做一个新的项目,项目页头,导航,页尾是不变的,只有中间部分是通过加载其他页面,达到内容刷新的. 大概结构如下, 要求, 1. 正文部分可以通过加载一个页面达到刷新效果 2. 保留加载的页面 url ...
- mysql docker 主从配置
主从复制相关 前置条件: docker安装的mysql是5.7.26版本 1. 编排docker-compose文件如下: version: '3' services: mysql-master: v ...
- JVM运行时数据区--深入理解Java虚拟机 读后感
程序计数器 程序计数器是线程私有的区域,很好理解嘛~,每个线程当然得有个计数器记录当前执行到那个指令.占用的内存空间小,可以把它看成是当前线程所执行的字节码的行号指示器.如果线程在执行Java方法,这 ...
- c#自定义控件中的事件处理
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; u ...
- Java后台解决跨域问题
首先说一下什么是跨域? JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制,a.com域名下的js无法操作b.c ...
- Zabbix遇到的问题集锦
一.Web界面上显示Zabbix server is not running 二.Zabbix显示中文字体 三.利用Python发送告警注意细节 四.zabbix上发告警信息不发恢复信息 五.Agen ...
- Zabbix4.0安装浅谈
一.此篇文章存在意义 针对超级小白,大神绕过 在zabbix官网https://www.zabbix.com/download里,需要数据库,但是并没有指导小白的我们如何安装数据库,此文章包含了Mys ...
- 【程序人生】从湖北省最早的四位java高级工程师之一到出家为僧所引发的深思
从我刚上大学接触程序员这个职业开始,到如今我从事了七年多程序员,这期间我和我的不少小伙伴接受了太多的负面信息,在成长的道路上也真了交了不少的情商税.这些负面信息中,有一件就是我大学班主任 ...
- CSS布局:元素垂直居中
CSS布局之元素垂直居中 本文将依次介绍在不同条件下实现垂直居中的多种方法及简单原理 Tip:下文中说的适用场景只是举了几个简单的例子方便读者理解.实际应用场景太复杂,生搬硬套容易出错.最重要的是掌握 ...