最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis實(shí)現(xiàn)延遲任務(wù)的三種方法詳解

 更新時(shí)間:2025年04月10日 11:21:20   作者:淺沫云歸  
延遲任務(wù)(Delayed Task)是指在未來(lái)的某個(gè)時(shí)間點(diǎn),執(zhí)行相應(yīng)的任務(wù),本文為大家整理了三種常見(jiàn)的實(shí)現(xiàn)方法,感興趣的小伙伴可以參考一下

1.前言

延遲任務(wù)(Delayed Task)是指在未來(lái)的某個(gè)時(shí)間點(diǎn),執(zhí)行相應(yīng)的任務(wù)。也就是說(shuō),延遲任務(wù)是一種計(jì)劃任務(wù),它被安排在特定的時(shí)間后執(zhí)行,而不是立即執(zhí)行。

延遲任務(wù)的常見(jiàn)使用場(chǎng)景有以下幾個(gè):

1.定時(shí)發(fā)送通知或消息:

發(fā)送定時(shí)短信、郵件或應(yīng)用內(nèi)消息,如注冊(cè)確認(rèn)、訂單狀態(tài)更新、促銷活動(dòng)通知等。

定時(shí)推送新聞、天氣預(yù)報(bào)、股票價(jià)格等實(shí)時(shí)信息。

2.異步處理和后臺(tái)任務(wù):

將耗時(shí)的操作安排為延遲任務(wù),避免阻塞主線程或用戶界面,提高系統(tǒng)的響應(yīng)性能。

執(zhí)行批量數(shù)據(jù)處理,如日志分析、數(shù)據(jù)報(bào)表生成等。

3.緩存管理和過(guò)期處理:

定時(shí)清理過(guò)期的緩存數(shù)據(jù),釋放存儲(chǔ)空間。

更新緩存中的數(shù)據(jù),保持?jǐn)?shù)據(jù)的時(shí)效性和準(zhǔn)確性。

4.計(jì)劃任務(wù)和定時(shí)調(diào)度:

在特定時(shí)間執(zhí)行系統(tǒng)維護(hù)任務(wù),如數(shù)據(jù)庫(kù)備份、系統(tǒng)更新等。

定時(shí)啟動(dòng)或關(guān)閉服務(wù),以節(jié)約資源或滿足業(yè)務(wù)需求。

5.訂單和支付處理:

在用戶下單后的一段時(shí)間內(nèi),如果用戶未支付,則自動(dòng)取消訂單。

定時(shí)檢查訂單的支付狀態(tài),并更新相應(yīng)的訂單信息。

6.重試和失敗恢復(fù)機(jī)制:

當(dāng)某個(gè)操作失敗時(shí),可以在延遲一段時(shí)間后自動(dòng)重試,以提高成功率。

實(shí)現(xiàn)分布式鎖的超時(shí)釋放,避免死鎖情況。

7.提醒和日程管理:

設(shè)置日程提醒,如會(huì)議、生日、紀(jì)念日等。

定時(shí)提醒用戶完成任務(wù)或進(jìn)行某項(xiàng)活動(dòng)。

8.定時(shí)數(shù)據(jù)采集和上報(bào):

定期從傳感器、設(shè)備或外部系統(tǒng)中采集數(shù)據(jù)。

定時(shí)上報(bào)應(yīng)用的使用情況、統(tǒng)計(jì)數(shù)據(jù)或用戶行為分析。

2.Redis如何實(shí)現(xiàn)延遲任務(wù)

Redis 本身并沒(méi)有直接提供延遲任務(wù)的功能,但可以通過(guò)一些策略和手段,在 Redis 中手動(dòng)實(shí)現(xiàn)延遲任務(wù)。

使用 Redis 實(shí)現(xiàn)延遲任務(wù)的主要手段有以下幾個(gè):

1. 使用過(guò)期鍵的事件通知執(zhí)行延時(shí)任務(wù):開(kāi)啟過(guò)期鍵通知,當(dāng) Redis 中鍵值過(guò)期時(shí)觸發(fā)時(shí)間,在事件中實(shí)現(xiàn)延遲代碼,但因?yàn)?Redis 的 Key 過(guò)期時(shí)不會(huì)被及時(shí)刪除,所以這個(gè)過(guò)期事件也不保證可以立即觸發(fā),所以此方式很少用來(lái)實(shí)現(xiàn)延遲任務(wù)(因?yàn)闃O其不穩(wěn)定)。

 2. 使用 ZSet 執(zhí)行延時(shí)任務(wù):在 ZSet 中插入延遲執(zhí)行時(shí)間和任務(wù) ID,如下命令所示:

ZADD delay_tasks <timestamp> <task_id>

然后,啟動(dòng)一個(gè)后臺(tái)線程或者定時(shí)任務(wù),定期通過(guò) ZRANGEBYSCORE 命令從有序集合中獲取已到達(dá)執(zhí)行時(shí)間的任務(wù),即分?jǐn)?shù)小于或等于當(dāng)前時(shí)間的任務(wù),進(jìn)行執(zhí)行即可實(shí)現(xiàn)延時(shí)任務(wù)。

3. 使用 Redisson 執(zhí)行延遲任務(wù):在 Redisson 框架中,提供了一個(gè) RDelayedQueue 用于實(shí)現(xiàn)延遲隊(duì)列,使用簡(jiǎn)單方便,推薦使用。

3.代碼實(shí)現(xiàn)

3.1. 過(guò)期鍵通知事件實(shí)現(xiàn)

Redis 提供了鍵空間通知功能,當(dāng)某個(gè)鍵發(fā)生變化(過(guò)期)時(shí),可以發(fā)送通知。你可以結(jié)合 EXPIRE 過(guò)期命令和鍵空間通知來(lái)實(shí)現(xiàn)延遲任務(wù)。

當(dāng)為某個(gè)鍵設(shè)置過(guò)期時(shí)間時(shí),一旦該鍵過(guò)期,Redis 會(huì)發(fā)送一個(gè)通知。你可以訂閱這個(gè)通知,并在接收到通知時(shí)執(zhí)行任務(wù)。但這種方法可能不夠精確,且依賴于 Redis 的內(nèi)部機(jī)制。

它的實(shí)現(xiàn)步驟是:

設(shè)置開(kāi)啟 Redis 過(guò)期鍵通知事件,可以通過(guò)執(zhí)行“CONFIG SET notify-keyspace-events KEA”命令來(lái)動(dòng)態(tài)開(kāi)啟鍵空間通知功能,而無(wú)需重啟 Redis 服務(wù)器。

設(shè)置過(guò)期鍵,可以通過(guò)命令“SET mykey "myvalue" EX 3”設(shè)置某個(gè) key 3 秒后過(guò)期(3s 后執(zhí)行)。

編寫(xiě)一個(gè)監(jiān)聽(tīng)程序來(lái)訂閱 Redis 的鍵空間通知。這可以通過(guò)使用 Redis 的發(fā)布/訂閱功能來(lái)實(shí)現(xiàn),具體實(shí)現(xiàn)代碼如下(以 Jedis 框架使用為例):

import redis.clients.jedis.Jedis;  
import redis.clients.jedis.JedisPubSub;  
  
public class RedisKeyspaceNotifier {  
  
    public static void main(String[] args) {  
        // 創(chuàng)建Jedis實(shí)例  
        Jedis jedis = new Jedis("localhost", 6379);  
  
        // 配置鍵空間通知(通常這一步在Redis配置文件中完成,但也可以在運(yùn)行時(shí)配置)  
        jedis.configSet("notify-keyspace-events", "KEA");  
  
        // 訂閱鍵空間通知  
        jedis.subscribe(new KeyspaceNotificationSubscriber(), "__keyevent@0__:expired");  
    }  
  
    static class KeyspaceNotificationSubscriber extends JedisPubSub {  
  
        @Override  
        public void onMessage(String channel, String message) {  
            System.out.println("Received message from channel: " + channel + ", message: " + message);  
            // 在這里處理接收到的鍵空間通知  
            // 例如,如果message是一個(gè)需要處理的任務(wù)ID,你可以在這里觸發(fā)相應(yīng)的任務(wù)處理邏輯  
        }  
  
        @Override  
        public void onSubscribe(String channel, int subscribedChannels) {  
            System.out.println("Subscribed to channel: " + channel);  
        }  
  
        @Override  
        public void onUnsubscribe(String channel, int subscribedChannels) {  
            System.out.println("Unsubscribed from channel: " + channel);  
        }  
    }  
}

但因?yàn)?Redis 的 Key 過(guò)期時(shí)不會(huì)被及時(shí)刪除,Redis 采用的是惰性刪除和定期刪除,所以這個(gè)過(guò)期事件也不保證可以立即觸發(fā),所以此方式很少用來(lái)實(shí)現(xiàn)延遲任務(wù)(因?yàn)闃O其不穩(wěn)定)。

3.2. 使用ZSet實(shí)現(xiàn)延遲任務(wù)

可以將任務(wù)及其執(zhí)行時(shí)間作為成員和分?jǐn)?shù)存儲(chǔ)在 ZSET 中,然后,使用一個(gè)后臺(tái)任務(wù)(如定時(shí)任務(wù)或守護(hù)進(jìn)程)定期檢查 ZSET,查找分?jǐn)?shù)(即執(zhí)行時(shí)間)小于或等于當(dāng)前時(shí)間的成員,并執(zhí)行相應(yīng)的任務(wù)。執(zhí)行后,從 ZSET 中刪除該成員,具體實(shí)現(xiàn)代碼如下:

import redis.clients.jedis.Jedis;  
  
import java.util.Set;  
  
public class RedisDelayedTaskDemo {  
  
    private static final String ZSET_KEY = "delayed_tasks";  
    private static final String REDIS_HOST = "localhost";  
    private static final int REDIS_PORT = 6379;  
  
    public static void main(String[] args) {  
        Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);  
  
        // 添加延遲任務(wù)  
        addDelayedTask(jedis, "task1", System.currentTimeMillis() / 1000 + 5); // 5秒后執(zhí)行  
        addDelayedTask(jedis, "task2", System.currentTimeMillis() / 1000 + 10); // 10秒后執(zhí)行  
  
        // 模擬定時(shí)任務(wù)檢查器  
        new Thread(() -> {  
            while (true) {  
                try {  
                    // 檢查并執(zhí)行到期的任務(wù)  
                    checkAndExecuteTasks(jedis);  
                    Thread.sleep(1000); // 每秒檢查一次  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        }).start();  
    }  
  
    private static void addDelayedTask(Jedis jedis, String task, long executeTime) {  
        jedis.zadd(ZSET_KEY, executeTime, task);  
        System.out.println("Added task: " + task + " with execution time: " + executeTime);  
    }  
  
    private static void checkAndExecuteTasks(Jedis jedis) {  
        long currentTime = System.currentTimeMillis() / 1000;  
        Set<String> tasks = jedis.zrangeByScore(ZSET_KEY, 0, currentTime);  
  
        for (String task : tasks) {  
            jedis.zrem(ZSET_KEY, task); // 從有序集合中移除任務(wù)  
            executeTask(task); // 執(zhí)行任務(wù)  
        }  
    }  
  
    private static void executeTask(String task) {  
        System.out.println("Executing task: " + task);  
        // 在這里添加實(shí)際的任務(wù)執(zhí)行邏輯  
    }  
}

在這個(gè)示例中,我們首先使用 addDelayedTask 方法向 Redis 的有序集合中添加任務(wù),并設(shè)置它們的執(zhí)行時(shí)間。然后,我們啟動(dòng)一個(gè)線程來(lái)模擬定時(shí)任務(wù)檢查器,它會(huì)每秒檢查一次是否有任務(wù)到期,并執(zhí)行到期的任務(wù)。

3.3 使用Redisson的延時(shí)隊(duì)列(常用)

在 Redisson 框架中,提供了一個(gè) RDelayedQueue 用于實(shí)現(xiàn)延遲隊(duì)列,使用簡(jiǎn)單方便,推薦使用,它的具體實(shí)現(xiàn)如下:

import org.redisson.Redisson;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
 
import java.util.concurrent.TimeUnit;
 
public class RDelayedQueueDemo {
 
    public static void main(String[] args) throws InterruptedException {
        // 創(chuàng)建 Redisson 客戶端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
 
        // 獲取延遲隊(duì)列
        RDelayedQueue<String> delayedQueue = 
            redisson.getDelayedQueue("delayedQueue");
 
        // 添加延遲任務(wù)
        delayedQueue.offer("task1", 5, TimeUnit.SECONDS);
 
        // 監(jiān)聽(tīng)并處理延遲任務(wù)
        Thread listenerThread = new Thread(() -> {
            while (true) {
                try {
                    // 通過(guò) take 方法等待并獲取到期的任務(wù)
                    String task = delayedQueue.take();
                    System.out.println("Handle task: " + task);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        listenerThread.start();
    }
}

在上述示例中,我們首先創(chuàng)建了一個(gè) Redisson 客戶端,通過(guò)配置文件指定了使用單節(jié)點(diǎn) Redis 服務(wù)器。然后,我們獲取一個(gè)延遲隊(duì)列 RDelayedQueue,并添加一個(gè)延遲任務(wù),延遲時(shí)間為 5 秒,接著,我們通過(guò)線程監(jiān)聽(tīng)并處理延遲隊(duì)列中的任務(wù)。

4.Redis實(shí)現(xiàn)延遲任務(wù)優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

  • 輕量級(jí)與高性能:Redis 是一個(gè)內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),因此讀寫(xiě)速度非???。將任務(wù)信息存儲(chǔ)在 Redis 中可以迅速地進(jìn)行存取操作。
  • 簡(jiǎn)單易用:Redis 的 API 簡(jiǎn)潔明了,易于集成到現(xiàn)有的應(yīng)用系統(tǒng)中。

缺點(diǎn):

  • 精度有限:Redis 的延遲任務(wù)依賴于系統(tǒng)的定時(shí)檢查機(jī)制,而不是精確的定時(shí)器。這意味著任務(wù)的執(zhí)行可能會(huì)有一定的延遲,特別是在系統(tǒng)負(fù)載較高或檢查間隔較長(zhǎng)的情況下。
  • 功能有限:與專業(yè)的任務(wù)調(diào)度系統(tǒng)相比,Redis 提供的延遲任務(wù)功能可能相對(duì)簡(jiǎn)單。對(duì)于復(fù)雜的任務(wù)調(diào)度需求,如任務(wù)依賴、任務(wù)優(yōu)先級(jí)等,可能需要額外的邏輯來(lái)實(shí)現(xiàn)。
  • 穩(wěn)定性較差:使用 Redis 實(shí)現(xiàn)延遲任務(wù)沒(méi)有重試機(jī)制和 ACK 確認(rèn)機(jī)制,所以穩(wěn)定性比較差。
  • 單點(diǎn)故障風(fēng)險(xiǎn):如果沒(méi)有正確配置 Redis 集群或主從復(fù)制,那么單個(gè) Redis 實(shí)例的故障可能導(dǎo)致整個(gè)延遲任務(wù)系統(tǒng)的癱瘓。

5. 總結(jié)

以上我們總結(jié)了使用redis實(shí)現(xiàn)延時(shí)任務(wù)的幾種方案,在一些簡(jiǎn)單的場(chǎng)景可以直接使用redisson提供的延時(shí)隊(duì)列來(lái)實(shí)現(xiàn)延時(shí)任務(wù),非常容易上手。在復(fù)雜大型的場(chǎng)景下,還是推薦使用專業(yè)的任務(wù)調(diào)度系統(tǒng),如xxl-job,Quartz等。

到此這篇關(guān)于Redis實(shí)現(xiàn)延遲任務(wù)的三種方法詳解的文章就介紹到這了,更多相關(guān)Redis延遲任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文解決Redis后臺(tái)持久化失敗的問(wèn)題:內(nèi)存不足導(dǎo)致fork失敗

    一文解決Redis后臺(tái)持久化失敗的問(wèn)題:內(nèi)存不足導(dǎo)致fork失敗

    Redis作為一個(gè)內(nèi)存數(shù)據(jù)庫(kù),在執(zhí)行后臺(tái)持久化(例如 BGSAVE 命令時(shí))需要fork一個(gè)子進(jìn)程來(lái)生成數(shù)據(jù)庫(kù)快照(RDB 文件),在生產(chǎn)環(huán)境中,有時(shí)你可能會(huì)在Redis日志中遇到持久化失敗的問(wèn)題,本文將詳細(xì)介紹該問(wèn)題的原因以及如何通過(guò)調(diào)整內(nèi)核和Redis配置來(lái)解決此問(wèn)題
    2025-07-07
  • Redis雙重判定鎖的實(shí)現(xiàn)(緩存擊穿的終極解決方案)

    Redis雙重判定鎖的實(shí)現(xiàn)(緩存擊穿的終極解決方案)

    本文詳細(xì)介紹了雙重判定鎖在分布式系統(tǒng)的應(yīng)用,通過(guò)兩次檢查避免了不必要的數(shù)據(jù)庫(kù)查詢,適用于緩存擊穿場(chǎng)景,提升系統(tǒng)效率與性能,感興趣的可以了解一下
    2026-05-05
  • Redis都做了哪些加快速度的設(shè)計(jì)

    Redis都做了哪些加快速度的設(shè)計(jì)

    這篇文章主要介紹了Redis都做了哪些加快速度的設(shè)計(jì)的相關(guān)資料,需要的朋友可以參考下
    2021-02-02
  • Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn)

    Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn)

    本文主要介紹了Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 使用Redis實(shí)現(xiàn)會(huì)話管理的示例代碼

    使用Redis實(shí)現(xiàn)會(huì)話管理的示例代碼

    文章介紹了如何使用Redis實(shí)現(xiàn)會(huì)話管理,包括會(huì)話的創(chuàng)建、讀取、更新和刪除操作,通過(guò)設(shè)置會(huì)話超時(shí)時(shí)間并重置,可以確保會(huì)話在用戶持續(xù)活動(dòng)期間不會(huì)過(guò)期,此外,展示了使用Redis的Hashes存儲(chǔ)更多信息,并使用Redis集群提高系統(tǒng)的可用性和擴(kuò)展性,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • 基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版)

    基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版)

    這篇文章主要介紹了基于Redis實(shí)現(xiàn)分布式鎖的方法(lua腳本版),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • 使用Redis實(shí)現(xiàn)秒殺功能的簡(jiǎn)單方法

    使用Redis實(shí)現(xiàn)秒殺功能的簡(jiǎn)單方法

    這篇文章主要給大家介紹了關(guān)于使用Redis實(shí)現(xiàn)秒殺功能的簡(jiǎn)單方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Redis使用RedisTemplate導(dǎo)致key亂碼問(wèn)題解決

    Redis使用RedisTemplate導(dǎo)致key亂碼問(wèn)題解決

    本文主要介紹了Redis使用RedisTemplate導(dǎo)致key亂碼問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • redis集群部署方案和redis常用命令

    redis集群部署方案和redis常用命令

    本文介紹了部署Redis集群的詳細(xì)步驟以及常用命令和管理操作,同時(shí)提醒了生產(chǎn)環(huán)境中的注意事項(xiàng),如配置持久化、密碼認(rèn)證和時(shí)鐘同步,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Redis中BigKey的隱患問(wèn)題小結(jié)

    Redis中BigKey的隱患問(wèn)題小結(jié)

    文章介紹Redis中BigKey的概念及其對(duì)性能的影響,包括內(nèi)存占用、網(wǎng)絡(luò)阻塞、CPU耗盡和集群不穩(wěn)定等問(wèn)題,對(duì)Redis中BigKey的隱患問(wèn)題感興趣的朋友一起看看吧
    2025-07-07

最新評(píng)論

永善县| 鞍山市| 台州市| 呈贡县| 迭部县| 乌拉特前旗| 宁南县| 墨脱县| 江山市| 汉源县| 历史| 富顺县| 佳木斯市| 敖汉旗| 彭泽县| 丰顺县| 信阳市| 武平县| 清涧县| 广南县| 舞阳县| 阿勒泰市| 内丘县| 五莲县| 西城区| 石城县| 长武县| 大埔区| 咸阳市| 芒康县| 正宁县| 鸡泽县| 左贡县| 扎赉特旗| 都安| 汨罗市| 清流县| 陕西省| 仪征市| 马尔康县| 花莲县|