實現(xiàn)定時任務的六種策略
這篇文章,我們聊聊實現(xiàn)定時任務的六種策略。
1. 自定義單線程
上圖中,我們啟動一個線程,該線程無限循環(huán)執(zhí)行,每隔20毫秒執(zhí)行業(yè)務代碼。
這種方式非常簡單易用,在很多中間件中得到廣泛應用。
2. JDK ScheduledExecutorService
ScheduledExecutorService 是 Java 標準庫提供的一個用于調(diào)度定時任務的接口。它提供了一種相對簡單的方式來執(zhí)行定時任務,不需要引入額外的庫。
在上述例子中:
- 創(chuàng)建了一個ScheduledExecutorService 實例,它使用了一個線程池,其中包含一個線程用于執(zhí)行定時任務。
- 定義了一個簡單的Runnable任務,輸出當前時間。
- 使用scheduleAtFixedRate方法安排任務,指定了任務的啟動延遲時間和執(zhí)行間隔時間。
- 主線程等待一段時間,然后關閉ScheduledExecutorService,確保定時任務不再執(zhí)行。
這是一個基本的使用例子,你可以根據(jù)需求調(diào)整延遲時間、執(zhí)行間隔、線程池大小等參數(shù)。
ScheduleExecutorService 因其簡單易用且性能優(yōu)異,在各大開源中間件項目(比如 RocketMQ、MetaQ、Canal 等)中被廣泛的使用。
3. Spring Task
在Spring框架中,你可以使用@Scheduled注解來創(chuàng)建定時任務。以下是Spring定時任務的基本用法:
(1) 配置類: 創(chuàng)建一個配置類,通常使用 @EnableScheduling 注解啟用 Spring 的定時任務功能。
(2) 定時任務方法: 在你的服務類或組件類中創(chuàng)建一個方法,并使用 @Scheduled 注解來指定定時任務的觸發(fā)條件。
在上述例子中,@Scheduled 注解允許你指定定時任務的執(zhí)行規(guī)則,可以是固定頻率(fixedRate)、固定延遲(fixedDelay)、或者使用cron表達式。
4. Quartz
Quartz是一款 Java 開源任務調(diào)度框架。
下面我們展示如何使用:
(1) 添加依賴
(2) Job(任務:你要做什么事)
(3) Trigger(觸發(fā)器:什么時候去做)
(4) scheduler(任務調(diào)度:你什么時候需要做什么事)將 job 與 Trigger 進行整合。
下面是一個例子:
這里需要強調(diào)的是,Quartz 支持集群模式,持久化方式是 JDBC ,需要創(chuàng)建如下表。
Quartz 集群模式對于業(yè)務數(shù)據(jù)庫有侵入性,需要考慮業(yè)務場景慎重使用。
5. elastic-job
ElasticJob 定位為輕量級無中心化解決方案,使用 jar 的形式提供分布式任務的協(xié)調(diào)服務。
應用內(nèi)部定義任務類,實現(xiàn) SimpleJob 接口,編寫自己任務的實際業(yè)務流程即可。
舉例:應用A有五個任務需要執(zhí)行,分別是A,B,C,D,E。任務E需要分成四個子任務,應用部署在兩臺機器上。
應用A在啟動后, 5個任務通過 Zookeeper 協(xié)調(diào)后被分配到兩臺機器上,通過Quartz Scheduler 分開執(zhí)行不同的任務。
ElasticJob 從本質(zhì)上來講 ,底層任務調(diào)度還是通過 Quartz ,相比Redis分布式鎖 或者 Quartz 分布式部署 ,它的優(yōu)勢在于可以依賴 Zookeeper 這個大殺器 ,將任務通過負載均衡算法分配給應用內(nèi)的 Quartz Scheduler容器。
6. xxl-job
XXL-JOB 是一個使用最廣泛的分布式任務調(diào)度平臺。
業(yè)務系統(tǒng)和調(diào)度平臺分開部署,我們在調(diào)度平臺上配置應用以及其定時任務,當任務需要執(zhí)行時,調(diào)度平臺會觸發(fā)業(yè)務系統(tǒng)的任務,業(yè)務系統(tǒng)執(zhí)行完任務之后,反饋給調(diào)度平臺任務執(zhí)行的結果。
接下來,我們使用 xxl-job 開發(fā)第一個任務 “Hello World”。
(1) 新建任務:
登錄調(diào)度中心,點擊下圖所示“新建任務”按鈕,新建示例任務。然后,參考下面截圖中任務的參數(shù)配置,點擊保存。
(2) 應用任務開發(fā)
(3) 觸發(fā)執(zhí)行
請點擊任務右側(cè) “執(zhí)行” 按鈕,可手動觸發(fā)一次任務執(zhí)行(通常情況下,通過配置Cron表達式進行任務調(diào)度觸發(fā))。
(4) 查看日志
請點擊任務右側(cè) “日志” 按鈕,可前往任務日志界面查看任務日志。在任務日志界面中,可查看該任務的歷史調(diào)度記錄以及每一次調(diào)度的任務調(diào)度信息、執(zhí)行參數(shù)和執(zhí)行信息。
運行中的任務點擊右側(cè)的“執(zhí)行日志”按鈕,可進入日志控制臺查看實時執(zhí)行日志。
7. 寫到最后
本文整理了實現(xiàn)定時任務的六種策略,我們需要根據(jù)實際場景選擇合適的策略。
同時,我們也需要考慮:
- 是否需要任務應用集群部署;
- 集群部署下假如出現(xiàn)并發(fā)執(zhí)行,業(yè)務是否會出現(xiàn)異常;
- 如何規(guī)避并發(fā)執(zhí)行導致的業(yè)務異常。