Redis模擬延時(shí)隊(duì)列實(shí)現(xiàn)日程提醒的方法
使用Redis模擬延時(shí)隊(duì)列
實(shí)際上通過MQ實(shí)現(xiàn)延時(shí)隊(duì)列更加方便,只是在實(shí)際業(yè)務(wù)中種種原因?qū)е伦罱K選擇使用redis作為該業(yè)務(wù)實(shí)現(xiàn)的中間件,順便記錄一下。
該業(yè)務(wù)是用于日程短信提醒,用戶添加日程后,就會被放入redis隊(duì)列中等待被執(zhí)行發(fā)送短信提醒業(yè)務(wù)。
本文介紹如何使用Redis來實(shí)現(xiàn)一個(gè)簡單的延時(shí)任務(wù)隊(duì)列,通過這個(gè)示例,可以幫助你理解如何利用Redis的有序集合特性來管理和執(zhí)行延時(shí)任務(wù)。
設(shè)計(jì)思路
Redis有序集合(Sorted Set)可以很好地用來實(shí)現(xiàn)延時(shí)隊(duì)列的功能。通過將任務(wù)的執(zhí)行時(shí)間作為分?jǐn)?shù)(score)來存入有序集合中,并定期檢查集合中小于等于當(dāng)前時(shí)間的任務(wù)來觸發(fā)執(zhí)行。
代碼實(shí)現(xiàn)
JedisCluster連接初始化
首先,我們需要初始化JedisCluster連接來與Redis集群進(jìn)行交互。
private static final String ZSET_KEY = "sms_delayed_tasks";
private JedisCluster jedisCluster;
public void RedisClusterScheduler() {
Set<HostAndPort> nodes = new HashSet<>();
//從配置文件中讀取redis集群配置
for (String node : AcpCore.getProp("spring.redis.cluster.nodes").split(",")) {
String[] hostPort = node.split(":");
nodes.add(new HostAndPort(hostPort[0], Integer.parseInt(hostPort[1])));
}
GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(128);
poolConfig.setMaxIdle(128);
poolConfig.setMinIdle(16);
jedisCluster = new JedisCluster(nodes, 2000, 2000, 5, AcpCore.getProp("spring.redis.password"), poolConfig);
if (!isCalled) {
isCalled = true;
startTaskChecker();
}
}添加延時(shí)任務(wù)
我們可以通過指定任務(wù)和執(zhí)行時(shí)間來添加延時(shí)任務(wù)。該方法將執(zhí)行時(shí)間轉(zhuǎn)換為時(shí)間戳,并將任務(wù)存儲在Redis有序集合中。
public void addDelayedTask(String task, String time) {
long executeTime = convertToTimestamp(time);
if (executeTime > System.currentTimeMillis() / 1000) {
jedisCluster.zadd(ZSET_KEY, executeTime, task);
log.info("添加任務(wù): " + task + " 執(zhí)行時(shí)間: " + executeTime);
} else {
log.info("任務(wù)時(shí)間必須在當(dāng)前時(shí)間之后: " + task);
}
}
private long convertToTimestamp(String time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return sdf.parse(time).getTime() / 1000;
} catch (ParseException e) {
e.printStackTrace();
return System.currentTimeMillis() / 1000;
}
}檢查和執(zhí)行任務(wù)
通過一個(gè)定時(shí)任務(wù)不斷檢查當(dāng)前時(shí)間之前的任務(wù)并執(zhí)行。
private void startTaskChecker() {
executorService.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
checkAndExecuteTasks();
Thread.sleep(1000);
} catch (Exception e) {
log.info(new Date() + "發(fā)生異常但不中斷,異常是:" + e);
}
}
});
}
private void checkAndExecuteTasks() {
long currentTime = System.currentTimeMillis() / 1000;
Set<String> tasks = jedisCluster.zrangeByScore(ZSET_KEY, 0, currentTime);
for (String task : tasks) {
jedisCluster.zrem(ZSET_KEY, task);
executeTask(task);
}
}執(zhí)行任務(wù)的邏輯
假設(shè)任務(wù)內(nèi)容是一個(gè)JSON對象,執(zhí)行邏輯在這里可以是任何操作,比如調(diào)用外部服務(wù)、發(fā)送消息等。
private void executeTask(String taskJson) {
JSONObject task = JSONObject.parseObject(taskJson);
// 在此處添加具體的業(yè)務(wù)邏輯
log.info("執(zhí)行任務(wù): " + task);
}總結(jié)
通過Redis的有序集合和簡單的定時(shí)器,能夠?qū)崿F(xiàn)一個(gè)簡潔有效的延時(shí)任務(wù)隊(duì)列。
當(dāng)然,這個(gè)示例是一個(gè)簡化的模型,在生產(chǎn)環(huán)境中,你需要考慮任務(wù)的冪等性、系統(tǒng)崩潰后的恢復(fù)策略、任務(wù)的優(yōu)先級等問題。希望本文能為你提供實(shí)現(xiàn)延時(shí)隊(duì)列的思路和參考。
到此這篇關(guān)于Redis模擬延時(shí)隊(duì)列 實(shí)現(xiàn)日程提醒的文章就介紹到這了,更多相關(guān)Redis延時(shí)隊(duì)列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- redis延時(shí)隊(duì)列的項(xiàng)目實(shí)踐
- redis延時(shí)隊(duì)列zset實(shí)現(xiàn)的示例
- Redisson延時(shí)隊(duì)列RedissonDelayed的具體使用
- Redis簡易延時(shí)隊(duì)列的實(shí)現(xiàn)示例
- Redis消息隊(duì)列、阻塞隊(duì)列、延時(shí)隊(duì)列的實(shí)現(xiàn)
- redis實(shí)現(xiàn)分布式延時(shí)隊(duì)列的示例代碼
- 生產(chǎn)redisson延時(shí)隊(duì)列不消費(fèi)問題排查解決
- 基于Redis實(shí)現(xiàn)延時(shí)隊(duì)列的優(yōu)化方案小結(jié)
- redis實(shí)現(xiàn)延時(shí)隊(duì)列的兩種方式(小結(jié))
- Redis 延時(shí)隊(duì)列詳解
相關(guān)文章
Redis遠(yuǎn)程連接Redis客戶端的實(shí)現(xiàn)步驟
本文主要介紹了Redis遠(yuǎn)程連接Redis客戶端的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
Redis刪除某個(gè)目錄下的數(shù)據(jù)的實(shí)現(xiàn)
本文介紹了如何在Redis中刪除指定目錄下的數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09
Redis消息隊(duì)列、阻塞隊(duì)列、延時(shí)隊(duì)列的實(shí)現(xiàn)
Redis是一種常用的內(nèi)存數(shù)據(jù)庫,它提供了豐富的功能,通常用于數(shù)據(jù)緩存和分布式隊(duì)列,本文主要介紹了Redis消息隊(duì)列、阻塞隊(duì)列、延時(shí)隊(duì)列的實(shí)現(xiàn),感興趣的可以了解一下2023-11-11
使用Docker部署Redis并配置持久化與密碼保護(hù)的詳細(xì)步驟
本文將詳細(xì)介紹如何使用 Docker 部署 Redis,并通過 redis.conf 配置文件實(shí)現(xiàn)數(shù)據(jù)持久化和密碼保護(hù),適合在生產(chǎn)環(huán)境中使用,文章通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下2025-03-03
Redis實(shí)現(xiàn)庫存扣減的解決方案防止商品超賣
在日常開發(fā)中有很多地方都有類似扣減庫存的操作,比如電商系統(tǒng)中的商品庫存,抽獎系統(tǒng)中的獎品庫存等,基于redis實(shí)現(xiàn)扣減庫存的具體實(shí)現(xiàn),初始化庫存回調(diào)函數(shù)(IStockCallback)扣減庫存服務(wù)(StockService),感興趣的朋友跟隨小編一起看看吧2022-06-06

