系统城装机大师 - 固镇县祥瑞电脑科技销售部宣传站!

当前位置:首页 > 数据库 > Redis > 详细页面

Redis集群下过期key监听的实现代码

时间:2019-12-04来源:系统城作者:电脑系统城

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. import java.util.Date;
  6.  
  7. /**
  8. * @Author xiabing5
  9. * @Create 2019/9/4 9:47
  10. * @Desc redis过期监听
  11. **/
  12. public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
  13. @Autowired
  14. RedisUtil redisUtil;
  15. @Autowired
  16. LoginUserStatisticsMapper loginUserStatisticsMapper;
  17. public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
  18. super(listenerContainer);
  19. }
  20. @Override
  21. public void onMessage(Message message, byte[] pattern) {
  22. // 用户做自己的业务处理即可,message.toString()可以获取失效的key
  23. String mesg = message.toString();
  24. }
  25. }

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. import java.util.Collections;
  5. import java.util.UUID;
  6. /**
  7. * @Author xiabing5
  8. * @Create 2019/9/6 15:54
  9. * @Desc redis分布式锁
  10. **/
  11. @Component
  12. public class RedisLock {
  13. @Autowired
  14. Jedis jedis;
  15. private static final String SET_IF_NOT_EXIST = "NX"; // NX表示如果不存在key就设置value
  16. private static final String SET_WITH_EXPIRE_TIME = "PX"; // PX表示毫秒
  17. // 加锁
  18. public String tryLock(String key,Long acquireTimeout) {
  19. // 生成随机value
  20. String identifierValue = UUID.randomUUID().toString();
  21. // 设置超时时间
  22. Long endTime = System.currentTimeMillis() + acquireTimeout;
  23. // 循环获取锁
  24. while (System.currentTimeMillis() < endTime) {
  25. String result = jedis.set(key,identifierValue, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME,acquireTimeout);
  26. if("OK".equals(result)) {
  27. return identifierValue;
  28. }
  29. }
  30. return null;
  31. }
  32. // 解锁
  33. // public void delLock(String key,String identifierValue) {
  34. // // 判断是否是同一把锁
  35. // try{
  36. // if(jedis.get(key).equals(identifierValue)){
  37. // // 此处操作非原子性,容易造成释放非自己的锁
  38. // jedis.del(key);
  39. // }
  40. // }catch(Exception e) {
  41. // e.printStackTrace();
  42. // }
  43. // }
  44. // 使用Lua代码解锁
  45. public void delLock(String key,String identifierValue) {
  46. try{
  47. String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
  48. Long result = (Long) jedis.eval(script, Collections.singletonList(key),Collections.singletonList(identifierValue));
  49. if (1 == result) {
  50. System.out.println(result+"释放锁成功");
  51. } if (0 == result) {
  52. System.out.println(result+"释放锁失败");
  53. }
  54. }catch (Exception e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. }

 

4. 总结

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

以上所述是小编给大家介绍的Redis集群下过期key监听的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

分享到:

相关信息

  • redis实现session共享的方法

    引言大厂很多项目都是部署到多台服务器上,这些服务器在各个地区都存在,当我们访问服务时虽然执行的是同一个服务,但是可能是不同服务器运行的;在我学习项目时遇到这样一个登录情...

    2023-11-01

  • 简单聊一聊redis过期时间的问题

    1.多次修改一个redis的String过期键,如何保证他仍然能保留第一次设置时的删除时间 2.修改hash、set、Zset、list的值,会使过期时间重置吗?...

    2023-11-01

系统教程栏目

栏目热门教程

人气教程排行

站长推荐

热门系统下载