当前位置: 移动技术网 > IT编程>开发语言>Java > Redis集群下过期key监听

Redis集群下过期key监听

2019年09月09日  | 移动技术网IT编程  | 我要评论

1. 前言

在使用redis集群时,发现过期key始终监听不到。网上也没有现成的解决方案。于是想,既然不能监听集群,那我可以建立多个redis连接,分别对每个redis的key过期进行监听。以上做法可能不尽人意,目前也没找到好的解决方案,如果有好的想法,请留言告知哦!不多说,直接贴我自己的代码!

2. 代码实现

关于redis集群配置代码此处不贴,直接贴配置监听类代码!

 1 redis.host1: 10.113.56.68
 2 redis.port1: 7030
 3 redis.host2: 10.113.56.68
 4 redis.port2: 7031
 5 redis.host3: 10.113.56.68
 6 redis.port3: 7032
 7 redis.host4: 10.113.56.68
 8 redis.port4: 7033
 9 redis.host5: 10.113.56.68
10 redis.port5: 7034
11 redis.host6: 10.113.56.68
12 redis.port6: 7035
  1 import org.springframework.beans.factory.annotation.value;
  2 import org.springframework.cache.cachemanager;
  3 import org.springframework.context.annotation.bean;
  4 import org.springframework.context.annotation.configuration;
  5 import org.springframework.data.redis.cache.rediscachemanager;
  6 import org.springframework.data.redis.connection.redisclusterconfiguration;
  7 import org.springframework.data.redis.connection.jedis.jedisconnectionfactory;
  8 import org.springframework.data.redis.core.redistemplate;
  9 import org.springframework.data.redis.listener.redismessagelistenercontainer;
 10 import org.springframework.data.redis.serializer.stringredisserializer;
 11 import redis.clients.jedis.jedis;
 12 import redis.clients.jedis.jedispoolconfig;
 13 
 14 import java.util.arrays;
 15 
 16 /**
 17  * @author  xiabing5
 18  * @create  2019/8/6 14:46
 19  * @desc    监听redis中key过期事件
 20  **/
 21 @configuration
 22 public class redislistenerconfig {
 23 
 24     @value("${redis.host1}")
 25     private string host1;
 26 
 27     @value("${redis.host2}")
 28     private string host2;
 29 
 30     @value("${redis.host3}")
 31     private string host3;
 32 
 33     @value("${redis.host4}")
 34     private string host4;
 35 
 36     @value("${redis.host5}")
 37     private string host5;
 38 
 39     @value("${redis.host6}")
 40     private string host6;
 41 
 42     @value("${redis.port1}")
 43     private int port1;
 44 
 45     @value("${redis.port2}")
 46     private int port2;
 47 
 48     @value("${redis.port3}")
 49     private int port3;
 50 
 51     @value("${redis.port4}")
 52     private int port4;
 53 
 54     @value("${redis.port5}")
 55     private int port5;
 56 
 57     @value("${redis.port6}")
 58     private int port6;
 59 
 60     @bean
 61     jedispoolconfig jedispoolconfig(){
 62         jedispoolconfig jedispoolconfig = new jedispoolconfig();
 63         jedispoolconfig.setmaxidle(100);
 64         jedispoolconfig.setmaxwaitmillis(1000);
 65         return jedispoolconfig;
 66     }
 67 
 68     // redis-cluster不支持key过期监听,建立多个连接,对每个redis节点进行监听
 69     @bean
 70     redismessagelistenercontainer rediscontainer1() {
 71         final redismessagelistenercontainer container = new redismessagelistenercontainer();
 72         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
 73         jedisconnectionfactory.sethostname(host1);
 74         jedisconnectionfactory.setport(port1);
 75         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
 76         jedisconnectionfactory.afterpropertiesset();
 77         container.setconnectionfactory(jedisconnectionfactory);
 78         return container;
 79     }
 80 
 81     @bean
 82     redismessagelistenercontainer rediscontainer2() {
 83         final redismessagelistenercontainer container = new redismessagelistenercontainer();
 84         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
 85         jedisconnectionfactory.sethostname(host2);
 86         jedisconnectionfactory.setport(port2);
 87         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
 88         jedisconnectionfactory.afterpropertiesset();
 89         container.setconnectionfactory(jedisconnectionfactory);
 90         return container;
 91     }
 92 
 93     @bean
 94     redismessagelistenercontainer rediscontainer3() {
 95         final redismessagelistenercontainer container = new redismessagelistenercontainer();
 96         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
 97         jedisconnectionfactory.sethostname(host3);
 98         jedisconnectionfactory.setport(port3);
 99         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
100         jedisconnectionfactory.afterpropertiesset();
101         container.setconnectionfactory(jedisconnectionfactory);
102         return container;
103     }
104 
105     @bean
106     redismessagelistenercontainer rediscontainer4() {
107         final redismessagelistenercontainer container = new redismessagelistenercontainer();
108         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
109         jedisconnectionfactory.sethostname(host4);
110         jedisconnectionfactory.setport(port4);
111         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
112         jedisconnectionfactory.afterpropertiesset();
113         container.setconnectionfactory(jedisconnectionfactory);
114         return container;
115     }
116 
117     @bean
118     redismessagelistenercontainer rediscontainer5() {
119         final redismessagelistenercontainer container = new redismessagelistenercontainer();
120         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
121         jedisconnectionfactory.sethostname(host5);
122         jedisconnectionfactory.setport(port5);
123         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
124         jedisconnectionfactory.afterpropertiesset();
125         container.setconnectionfactory(jedisconnectionfactory);
126         return container;
127     }
128 
129     @bean
130     redismessagelistenercontainer rediscontainer6() {
131         final redismessagelistenercontainer container = new redismessagelistenercontainer();
132         jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
133         jedisconnectionfactory.sethostname(host6);
134         jedisconnectionfactory.setport(port6);
135         jedisconnectionfactory.setpoolconfig(jedispoolconfig());
136         jedisconnectionfactory.afterpropertiesset();
137         container.setconnectionfactory(jedisconnectionfactory);
138         return container;
139     }
140 
141     @bean
142     rediskeyexpirationlistener rediskeyexpirationlistener1() {
143         return new rediskeyexpirationlistener(rediscontainer1());
144     }
145 
146     @bean
147     rediskeyexpirationlistener rediskeyexpirationlistener2() {
148         return new rediskeyexpirationlistener(rediscontainer2());
149     }
150 
151     @bean
152     rediskeyexpirationlistener rediskeyexpirationlistener3() {
153         return new rediskeyexpirationlistener(rediscontainer3());
154     }
155 
156     @bean
157     rediskeyexpirationlistener rediskeyexpirationlistener4() {
158         return new rediskeyexpirationlistener(rediscontainer4());
159     }
160 
161     @bean
162     rediskeyexpirationlistener rediskeyexpirationlistener5() {
163         return new rediskeyexpirationlistener(rediscontainer5());
164     }
165 
166     @bean
167     rediskeyexpirationlistener rediskeyexpirationlistener6() {
168         return new rediskeyexpirationlistener(rediscontainer6());
169     }
170 
171 }
 1 import org.springframework.beans.factory.annotation.autowired;
 2 import org.springframework.data.redis.connection.message;
 3 import org.springframework.data.redis.listener.keyexpirationeventmessagelistener;
 4 import org.springframework.data.redis.listener.redismessagelistenercontainer;
 5 
 6 import java.util.date;
 7 
 8 
 9 /**
10  * @author  xiabing5
11  * @create  2019/9/4 9:47
12  * @desc    redis过期监听
13  **/
14 public class rediskeyexpirationlistener extends keyexpirationeventmessagelistener {
15 
16     @autowired
17     redisutil redisutil;
18 
19     @autowired
20     loginuserstatisticsmapper loginuserstatisticsmapper;
21 
22     public rediskeyexpirationlistener(redismessagelistenercontainer listenercontainer) {
23         super(listenercontainer);
24     }
25 
26     @override
27     public void onmessage(message message, byte[] pattern) {
28         // 用户做自己的业务处理即可,message.tostring()可以获取失效的key
29         string mesg = message.tostring();      
30        
31     }
32 }

3. redis防止过期key重复监听

对于项目集群情况下,部署多个服务后,容易出现redis过期被多个服务同时监听到,从而执行相同的业务逻辑,这不是我们期望的。单机部署下方法的同步可以采用synchronize关键字。但集群下,就得采用分布式锁。在需要加锁的地方,只要加锁和解锁即可。此处正好写到redis,那就贴一个自己用的redis分布式锁。

 1 import org.springframework.beans.factory.annotation.autowired;
 2 import org.springframework.stereotype.component;
 3 import redis.clients.jedis.jedis;
 4 
 5 import java.util.collections;
 6 import java.util.uuid;
 7 
 8 /**
 9  * @author  xiabing5
10  * @create  2019/9/6 15:54
11  * @desc    redis分布式锁
12  **/
13 @component
14 public class redislock {
15 
16     @autowired
17     jedis jedis;
18 
19     private static final string set_if_not_exist = "nx"; // nx表示如果不存在key就设置value
20     private static final string set_with_expire_time = "px"; // px表示毫秒
21 
22     // 加锁
23     public string trylock(string key,long acquiretimeout) {
24         // 生成随机value
25         string identifiervalue = uuid.randomuuid().tostring();
26         // 设置超时时间
27         long endtime = system.currenttimemillis() + acquiretimeout;
28         // 循环获取锁
29         while (system.currenttimemillis() < endtime) {
30             string result = jedis.set(key,identifiervalue, set_if_not_exist, set_with_expire_time, acquiretimeout);
31             if("ok".equals(result)) {
32                 return identifiervalue;
33             }
34         }
35         return null;
36     }
37 
38     // 解锁
39 //    public void dellock(string key,string identifiervalue) {
40 //        // 判断是否是同一把锁
41 //        try{
42 //            if(jedis.get(key).equals(identifiervalue)){
43 //                // 此处操作非原子性,容易造成释放非自己的锁
44 //                jedis.del(key);
45 //            }
46 //        }catch(exception e) {
47 //            e.printstacktrace();
48 //        }
49 //    }
50 
51     // 使用lua代码解锁
52     public void dellock(string key,string identifiervalue) {
53         try{
54             string script = "if redis.call('get', keys[1]) == argv[1] then return redis.call('del', keys[1]) else return 0 end";
55             long result = (long) jedis.eval(script, collections.singletonlist(key), collections.singletonlist(identifiervalue));
56             if (1 == result) {
57                system.out.println(result+"释放锁成功");
58             } if (0 == result) {
59                 system.out.println(result+"释放锁失败");
60             }
61         }catch (exception e) {
62             e.printstacktrace();
63         }
64     }
65 
66 }

4. 总结

自己实现的一个小demo,废话比较少。小白自己写的配置类,理解有问题请留言!自己实现的方案感觉不妥,只是基本完成需求,还得继续研究。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网