Redis集群下过期key监听的实现代码
程序员文章站
2022-06-24 23:09:03
1. 前言
在使用redis集群时,发现过期key始终监听不到。网上也没有现成的解决方案。于是想,既然不能监听集群,那我可以建立多个redis连接,分别对每个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
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()); } }
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(); } } }
4. 总结
自己实现的一个小demo,废话比较少。小白自己写的配置类,理解有问题请留言!自己实现的方案感觉不妥,只是基本完成需求,还得继续研究。
以上所述是小编给大家介绍的redis集群下过期key监听的实现代码,希望对大家有所帮助