talk is cheap, show me the code.
一、開啟Redis key過期提醒
-
方式二:修改配置檔案
redis.conf
# 預設 notify-keyspace-events "" notify-keyspace-events Ex
-
方式二:命令列開啟
CONFIG SET notify-keyspace-events Ex CONFIG GET notify-keyspace-events
二、notify-keyspace-events
notify-keyspace-events 選項的預設值為空
notify-keyspace-events 的引數可以是以下字元的任意組合, 它指定了伺服器該傳送哪些型別的通知。
字元 | 傳送的通知 |
---|---|
K | 鍵空間通知,所有通知以 keyspace@ |
E | 鍵事件通知,所有通知以 keyevent@ |
g | DEL 、 EXPIRE 、 RENAME 等型別無關的通用命令的通知 |
$ | 字串命令的通知 |
l | 列表命令的通知 |
s | 集合命令的通知 |
h | 雜湊命令的通知 |
z | 有序集合命令的通知 |
x | 過期事件:每當有過期鍵被刪除時傳送 |
e | 驅逐(evict)事件:每當有鍵因為 maxmemory 政策而被刪除時傳送 |
A | 引數 g$lshzxe 的別名 |
三、Coding
-
初始化一個
Spring Boot
專案 -
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
-
定義配置類
RedisListenerConfig
@Configuration public class RedisListenerConfig { @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); return container; } }
-
定義資料生產類
ProviderDataToRedis
@Slf4j @Component public class ProviderDataToRedis implements CommandLineRunner { @Autowired private StringRedisTemplate stringRedisTemplate; @Override public void run(String... args) throws Exception { int[] num = new int[]{1}; Random random = new Random(); while (true) { int max = random.nextInt(5); IntStream.range(0, max).forEach(n -> stringRedisTemplate.opsForValue().set(String.format("mq:s1:%s", ++num[0]), "已預訂", 5, TimeUnit.SECONDS)); log.info("放了 {} 條資料到redis...", max); TimeUnit.SECONDS.sleep(3); } } }
-
定義監聽器 實現
KeyExpirationEventMessageListener
介面檢視原始碼發現,該介面監聽所有db的過期事件
keyevent@*:expired"
定義
Status1ExpirationListener
監聽狀態1到期@Slf4j @Component public class Status1ExpirationListener extends KeyExpirationEventMessageListener { public Status1ExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Autowired private StringRedisTemplate stringRedisTemplate; @Override public void onMessage(Message message, byte[] pattern) { // 使用者做自己的業務處理即可,注意message.toString()可以獲取失效的key String expiredKey = message.toString(); if (expiredKey.startsWith("mq:s1:")) { log.info("-----------------------------------"); log.info(String.format("過期key[%s]", expiredKey)); String newKey = String.format("mq:s2:%s", expiredKey.substring(6)); String newValue = "行程中"; stringRedisTemplate.opsForValue().set(newKey, newValue, 3, TimeUnit.SECONDS); log.info(String.format("%s: %s", newKey, newValue)); log.info("-----------------------------------"); } } }
定義
Status2ExpirationListener
監聽狀態2到期@Slf4j @Component public class Status2ExpirationListener extends KeyExpirationEventMessageListener { public Status2ExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } @Override public void onMessage(Message message, byte[] pattern) { // 使用者做自己的業務處理即可,注意message.toString()可以獲取失效的key String expiredKey = message.toString(); if (expiredKey.startsWith("mq:s2:")) { log.info("***********************************"); log.info(String.format("過期key[%s]", expiredKey)); log.info("[{}]行程已完成,修改資料庫狀態。", newKey); log.info("***********************************"); } } }
四、測試輸出
...
2021-01-25 23:16:58.012 INFO 55511 --- [ main] n.y.tools.listener.ProviderDataToRedis : 放了 4 條資料到redis...
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : 過期key[mq:s1:272]
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.037 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : 過期key[mq:s1:271]
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : mq:s2:272: 行程中
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : mq:s2:271: 行程中
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1070] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.039 INFO 55511 --- [ container-1072] c.i.r.l.Status1ExpirationListener : -----------------------------------
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : 過期key[mq:s2:270]
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : [270]行程已完成,修改資料庫狀態。
2021-01-25 23:17:00.140 INFO 55511 --- [ container-1075] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : 過期key[mq:s2:269]
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : 過期key[mq:s2:268]
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : [269]行程已完成,修改資料庫狀態。
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1077] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : [268]行程已完成,修改資料庫狀態。
2021-01-25 23:17:00.242 INFO 55511 --- [ container-1079] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : ***********************************
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : 過期key[mq:s2:267]
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : [267]行程已完成,修改資料庫狀態。
2021-01-25 23:17:00.546 INFO 55511 --- [ container-1081] c.i.r.l.Status2ExpirationListener : ***********************************
...
五、一直增加的執行緒數
從測試輸出的日誌中可以看出,執行緒一直在增加,這個問題還有待解決!