一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫 - Redis - Redis集群下過期key監(jiān)聽的實現(xiàn)代碼

Redis集群下過期key監(jiān)聽的實現(xiàn)代碼

2019-11-27 16:02超人小冰 Redis

這篇文章主要介紹了Redis集群下過期key監(jiān)聽的實現(xiàn)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下

1. 前言

在使用redis集群時,發(fā)現(xiàn)過期key始終監(jiān)聽不到。網(wǎng)上也沒有現(xiàn)成的解決方案。于是想,既然不能監(jiān)聽集群,那我可以建立多個redis連接,分別對每個redis的key過期進(jìn)行監(jiān)聽。以上做法可能不盡人意,目前也沒找到好的解決方案,如果有好的想法,請留言告知哦!不多說,直接貼我自己的代碼!

2. 代碼實現(xiàn)

關(guān)于Redis集群配置代碼此處不貼,直接貼配置監(jiān)聽類代碼!

?
1
2
3
4
5
6
7
8
9
10
11
12
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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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  監(jiān)聽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過期監(jiān)聽,建立多個連接,對每個redis節(jié)點進(jìn)行監(jiān)聽
  @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());
  }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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過期監(jiān)聽
 **/
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) {
    // 用戶做自己的業(yè)務(wù)處理即可,message.toString()可以獲取失效的key
    String mesg = message.toString();  
  }
}

3. Redis防止過期key重復(fù)監(jiān)聽

對于項目集群情況下,部署多個服務(wù)后,容易出現(xiàn)redis過期被多個服務(wù)同時監(jiān)聽到,從而執(zhí)行相同的業(yè)務(wù)邏輯,這不是我們期望的。單機部署下方法的同步可以采用synchronize關(guān)鍵字。但集群下,就得采用分布式鎖。在需要加鎖的地方,只要加鎖和解鎖即可。此處正好寫到Redis,那就貼一個自己用的redis分布式鎖。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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就設(shè)置value
  private static final String SET_WITH_EXPIRE_TIME = "PX"; // PX表示毫秒
  // 加鎖
  public String tryLock(String key,Long acquireTimeout) {
    // 生成隨機value
    String identifierValue = UUID.randomUUID().toString();
    // 設(shè)置超時時間
    Long endTime = System.currentTimeMillis() + acquireTimeout;
    // 循環(huán)獲取鎖
    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. 總結(jié)

自己實現(xiàn)的一個小demo,廢話比較少。小白自己寫的配置類,理解有問題請留言!自己實現(xiàn)的方案感覺不妥,只是基本完成需求,還得繼續(xù)研究。

以上所述是小編給大家介紹的Redis集群下過期key監(jiān)聽的實現(xiàn)代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

原文鏈接:https://www.cnblogs.com/xiaobingblog/archive/2019/09/09/11490726.html

延伸 · 閱讀

精彩推薦
  • Redis詳解Redis復(fù)制原理

    詳解Redis復(fù)制原理

    與大多數(shù)db一樣,Redis也提供了復(fù)制機制,以滿足故障恢復(fù)和負(fù)載均衡等需求。復(fù)制也是Redis高可用的基礎(chǔ),哨兵和集群都是建立在復(fù)制基礎(chǔ)上實現(xiàn)高可用的...

    李留廣10222021-08-09
  • RedisRedis的配置、啟動、操作和關(guān)閉方法

    Redis的配置、啟動、操作和關(guān)閉方法

    今天小編就為大家分享一篇Redis的配置、啟動、操作和關(guān)閉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡5312019-11-14
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友...

    xiaojin21cen10152021-07-27
  • RedisRedis全量復(fù)制與部分復(fù)制示例詳解

    Redis全量復(fù)制與部分復(fù)制示例詳解

    這篇文章主要給大家介紹了關(guān)于Redis全量復(fù)制與部分復(fù)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis爬蟲具有一定的參考學(xué)習(xí)...

    豆子先生5052019-11-27
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    這篇文章主要給大家介紹了關(guān)于redis中如何使用lua腳本讓你的靈活性提高5個逼格的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具...

    一線碼農(nóng)5812019-11-18
  • RedisRedis 事務(wù)知識點相關(guān)總結(jié)

    Redis 事務(wù)知識點相關(guān)總結(jié)

    這篇文章主要介紹了Redis 事務(wù)相關(guān)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • Redisredis實現(xiàn)排行榜功能

    redis實現(xiàn)排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實現(xiàn)排行榜功能,本文就來簡單的介紹一下如何使用,具有一定的參考價值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • RedisRedis如何實現(xiàn)數(shù)據(jù)庫讀寫分離詳解

    Redis如何實現(xiàn)數(shù)據(jù)庫讀寫分離詳解

    Redis的主從架構(gòu),能幫助我們實現(xiàn)讀多,寫少的情況,下面這篇文章主要給大家介紹了關(guān)于Redis如何實現(xiàn)數(shù)據(jù)庫讀寫分離的相關(guān)資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
主站蜘蛛池模板: 999精品视频在线观看热6 | jux629三浦理惠子在线播放 | yy111111免费观看 | 2022超帅男同gayxxx | 色老板视频在线 | 日韩欧美一区二区在线观看 | 久久99影院 | 摸进老太婆的裤裆小说 | 青春草视频在线免费观看 | 欧美精品亚洲精品日韩专区va | 大伊人青草狠狠久久 | 色综合久久综精品 | 国产福利一区二区三区四区 | 国产a免费观看 | 天美传媒传媒免费观看 | 韩剧网3600热播剧 | 精品国产一区二区三区国产馆 | 午夜日本大胆裸艺术 | 91茄子| 天堂成人在线 | 四虎影视免费观看免费观看 | 国产99青草全福视在线 | 国产视频99| 亚洲国产在线2o20 | 性夜影院爽黄A爽免费动漫 性色欲情网站IWWW九文堂 | 美女把小内内脱个精光打屁屁 | yy6080午夜国产免费福利 | 韩国美女被的免费视频 | 久久这里只有精品国产精品99 | 欧美贵妇videos办公室360 | 午夜国产在线 | 色99视频 | 精品国产免费久久久久久 | 女人肮脏的交易中文字幕未删减版 | 欧美日韩国产手机在线观看视频 | 国内精品久久久久久中文字幕 | 男女小视频在线观看 | 91碰碰| 日本mv精品中文字幕 | 男人猛进女人屁股免费 | 动漫精品午夜在线播放 |