監(jiān)聽Redis實(shí)時(shí)數(shù)據(jù)變化實(shí)現(xiàn)過程
前言
監(jiān)聽Redis的Value實(shí)時(shí)變化。
一、實(shí)現(xiàn)思路
最簡(jiǎn)單粗暴的方式,首先遍歷一遍數(shù)據(jù)存到map,然后不斷遍歷redis判斷value是否跟已有的map值相等即可。
二、實(shí)現(xiàn)步驟
1. 定義緩存Map
假設(shè)需要監(jiān)聽數(shù)據(jù)key前綴為aaa,創(chuàng)建定時(shí)調(diào)度服務(wù):
private static final Map<String, String> LAST_VALUES = new ConcurrentHashMap<>(); private static final String KEY_PREFIX = "aaa"; private ScheduledExecutorService scheduler;
2. 入口方法
使用@PostConstruct注解執(zhí)行初始化:
@PostConstruct
public void init() {
// 異步加載所有鍵值,不阻塞啟動(dòng)
CompletableFuture.runAsync(this::loadInitialValues);
// 每5秒掃描一次
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::scanChanges, 0, 5, TimeUnit.SECONDS);
}3. 初始化
使用Jedis創(chuàng)建連接,定義掃描參數(shù),使用redis的scan命令遍歷所有的匹配"aaa"+ "*"模式的鍵,游標(biāo)從0開始,使用do-while,返回為0表示迭代結(jié)束,將所有value存到map:
private void loadInitialValues() {
try (Jedis jedis = new Jedis("localhost", 6379)) {
String cursor = "0";
ScanParams params = new ScanParams().match(KEY_PREFIX + "*").count(100);
do {
ScanResult<String> scanResult = jedis.scan(cursor, params);
cursor = scanResult.getCursor();
for (String key : scanResult.getResult()) {
String jsonString = jedis.get(key);
if (jsonString != null) {
LAST_VALUES.put(key, jsonString);
}
}
} while (!"0".equals(cursor));
log.info("Loaded {} initial values from Redis.", LAST_VALUES.size());
} catch (Exception e) {
throw new RuntimeException(e);
}
}4. 掃描變更數(shù)據(jù)
判斷新舊數(shù)據(jù)是否一致,不一致則通過自定義方法處理數(shù)據(jù):
private void scanChanges() {
try (Jedis jedis = new Jedis("localhost", 6379)) {
String cursor = "0";
ScanParams params = new ScanParams().match(KEY_PREFIX + "*").count(100);
do {
ScanResult<String> scanResult = jedis.scan(cursor, params);
cursor = scanResult.getCursor();
for (String key : scanResult.getResult()) {
String currentValueStr = jedis.get(key);
String oldValueStr = LAST_VALUES.getOrDefault(key, null);
if (!Objects.equals(currentValueStr, oldValueStr)) {
try {
//處理數(shù)據(jù)
dealWithData(key, oldValueStr, currentValueStr );
lastValues.put(key, currentValue);
LAST_VALUES.put(key, currentValueStr);
} catch (Exception e) {
log.error("Failed to process data change for key: {}", key, e);
}
}
}
} while (!"0".equals(cursor));
} catch (Exception e) {
throw new RuntimeException(e);
}
}總結(jié)
本文介紹了最簡(jiǎn)單的監(jiān)聽Redis中value值的變化方法,還可以設(shè)置Redis Keyspace 通知監(jiān)聽。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- redis之基于SpringBoot實(shí)現(xiàn)Redis stream實(shí)時(shí)流事件處理方式
- 使用Redis實(shí)現(xiàn)實(shí)時(shí)排行榜功能
- 使用Redis和Node.js來開發(fā)簡(jiǎn)單的實(shí)時(shí)聊天功能
- 使用Redis實(shí)現(xiàn)實(shí)時(shí)排行榜的示例
- 淺談我是如何用redis做實(shí)時(shí)訂閱推送的
- 基于Redis Streams的實(shí)時(shí)消息處理實(shí)戰(zhàn)指南
- 基于Redis-Shake實(shí)現(xiàn)Redis實(shí)時(shí)同步的示例代碼
相關(guān)文章
redis使用不當(dāng)導(dǎo)致應(yīng)用卡死bug的過程解析
本文主要記一次找因redis使用不當(dāng)導(dǎo)致應(yīng)用卡死bug的過程,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
Redis處理MQ消費(fèi)冪等的實(shí)現(xiàn)示例
本文主要介紹了Redis處理MQ消費(fèi)冪等的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05
Redis存儲(chǔ)的列表分頁和檢索的實(shí)現(xiàn)方法
在 Redis 中,列表(List)是一種有序的數(shù)據(jù)結(jié)構(gòu),通常用于存儲(chǔ)一系列元素,由于列表是有序的,可以通過索引來訪問元素,因此可以很方便地實(shí)現(xiàn)分頁和檢索功能,以下是 Redis 列表的分頁和檢索的實(shí)現(xiàn)方法,需要的朋友可以參考下2025-02-02
嵌入式Redis服務(wù)器在Spring Boot測(cè)試中的使用教程
這篇文章主要介紹了嵌入式Redis服務(wù)器在Spring Boot測(cè)試中的使用,本文通過實(shí)例代碼場(chǎng)景分析給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-07-07
redis安裝和配置_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了redis安裝和配置,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
詳解Redis高效恢復(fù)策略內(nèi)存快照與AOF
這篇文章主要為大家介紹了Redis高效恢復(fù)策略內(nèi)存快照與AOF及對(duì)比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
Redis之SDS數(shù)據(jù)結(jié)構(gòu)的使用
本文主要介紹了Redis之SDS數(shù)據(jù)結(jié)構(gòu)的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

