笑不活了!項(xiàng)目真的用上 XXL-Job 了
兄弟們,咱們公司的定時(shí)任務(wù)系統(tǒng)是否都踩過這些坑:線上任務(wù)突然不執(zhí)行了,排查半天才發(fā)現(xiàn)是數(shù)據(jù)庫鎖表了;凌晨三點(diǎn)接到運(yùn)維電話說任務(wù)超時(shí)把服務(wù)器內(nèi)存吃爆了;想動(dòng)態(tài)調(diào)整任務(wù)執(zhí)行時(shí)間得求著運(yùn)維改配置文件,改完還得重啟服務(wù)...... 說多了都是淚,這不,我們項(xiàng)目組最近居然真的用上了 XXL-Job,這波操作簡(jiǎn)直讓人笑不活了 —— 不是因?yàn)樗指阈Γm然 "XXL" 確實(shí)讓人聯(lián)想到某知名服裝品牌的加大碼),而是這套分布式任務(wù)調(diào)度系統(tǒng)真的把我們從定時(shí)任務(wù)的苦海里救出來了!
一、先搞明白:XXL-Job 到底是個(gè)啥?
估計(jì)有剛?cè)胄械耐瑢W(xué)要問了:"我之前用 Quartz 挺順手的,為啥要換這個(gè) XXL-Job?" 別急,先給大家講個(gè)故事:假設(shè)你是一個(gè)食堂的打飯阿姨,每天要給 1000 個(gè)學(xué)生打飯。剛開始學(xué)生少,你一個(gè)人拿著飯勺就能搞定(這就是單體應(yīng)用里的定時(shí)任務(wù))。后來學(xué)生越來越多,你發(fā)現(xiàn)自己忙不過來了,于是找了幾個(gè)幫手(集群部署),但問題來了:每個(gè)幫手都不知道其他人打了多少飯,有的窗口排起長(zhǎng)隊(duì),有的窗口卻沒人(任務(wù)執(zhí)行不均衡)。這時(shí)候就需要一個(gè)總調(diào)度員,專門負(fù)責(zé)分配打飯任務(wù),告訴每個(gè)幫手該打多少份、幾點(diǎn)打、怎么處理突發(fā)情況(比如某個(gè)幫手突然拉肚子)—— 這個(gè)總調(diào)度員,就是 XXL-Job。
1.1 官方定義太正經(jīng)?人話版解讀來了
XXL-Job 是一個(gè)開源的分布式任務(wù)調(diào)度平臺(tái),核心功能包括:
- 分布式調(diào)度:支持任務(wù)在多臺(tái)服務(wù)器上分布式執(zhí)行,解決單節(jié)點(diǎn)性能瓶頸
- 可視化管理:自帶 Web 控制臺(tái),任務(wù)狀態(tài)、執(zhí)行日志、失敗重試策略都能圖形化配置
- 彈性擴(kuò)展:新增服務(wù)器時(shí)不需要修改代碼,注冊(cè)到調(diào)度中心就能自動(dòng)分配任務(wù)
- 故障容錯(cuò):任務(wù)執(zhí)行失敗自動(dòng)重試,支持分片廣播、故障轉(zhuǎn)移等高級(jí)特性
劃重點(diǎn):它不是一個(gè)框架,而是一個(gè)完整的調(diào)度平臺(tái)!以前用 Quartz 的時(shí)候,你得自己搭數(shù)據(jù)庫、寫管理界面、處理集群沖突,現(xiàn)在 XXL-Job 把這些全都封裝好了,簡(jiǎn)直是懶癌患者的福音。
1.2 和老對(duì)手 Quartz 比,到底強(qiáng)在哪?
功能特性 | Quartz | XXL-Job |
集群管理 | 需要自己實(shí)現(xiàn)(依賴數(shù)據(jù)庫鎖) | 原生支持,自動(dòng)選舉主節(jié)點(diǎn) |
可視化管理 | 無(需手動(dòng)開發(fā)) | 自帶完整 Web 控制臺(tái) |
任務(wù)動(dòng)態(tài)管理 | 難(需重啟服務(wù)或更新數(shù)據(jù)庫) | 支持動(dòng)態(tài)新增、修改、暫停任務(wù) |
故障重試 | 簡(jiǎn)單重試策略 | 支持自定義重試次數(shù)、間隔、補(bǔ)償機(jī)制 |
分片處理 | 需手動(dòng)實(shí)現(xiàn) | 原生支持分片廣播,自動(dòng)分配任務(wù)分片 |
語言支持 | 僅 Java | 支持 Java、Python、PHP 等多語言 |
舉個(gè)真實(shí)案例:之前我們用 Quartz 做訂單超時(shí)關(guān)閉任務(wù),每次擴(kuò)容服務(wù)器都要手動(dòng)修改數(shù)據(jù)庫里的節(jié)點(diǎn)配置,有一次運(yùn)維小哥手抖改壞了配置,導(dǎo)致 80% 的任務(wù)都沒執(zhí)行,那天晚上運(yùn)營(yíng)小姐姐的奪命連環(huán) Call 簡(jiǎn)直是噩夢(mèng)。換成 XXL-Job 后,新服務(wù)器啟動(dòng)后自動(dòng)注冊(cè)到調(diào)度中心,再也不用手動(dòng)改配置了,運(yùn)維小哥現(xiàn)在看到我都笑得特別燦爛。
二、核心架構(gòu)揭秘:XXL-Job 憑啥能搞定分布式調(diào)度?
接下來咱們深入底層,看看這個(gè) "加大碼" 調(diào)度系統(tǒng)的核心組件是怎么分工協(xié)作的。建議打開官網(wǎng)的架構(gòu)圖(https://www.xuxueli.com/xxl-job/),跟著我一起拆解:
2.1 調(diào)度中心:整個(gè)系統(tǒng)的 "大腦"
這是 XXL-Job 的核心組件,主要負(fù)責(zé):
- 任務(wù)注冊(cè)與發(fā)現(xiàn):執(zhí)行器啟動(dòng)時(shí)會(huì)向調(diào)度中心注冊(cè)自己的 IP 和端口,就像員工每天上班打卡報(bào)崗
- 任務(wù)調(diào)度:根據(jù)任務(wù)配置的 Cron 表達(dá)式生成調(diào)度計(jì)劃,比如每天凌晨 2 點(diǎn)執(zhí)行的任務(wù),調(diào)度中心會(huì)提前算好時(shí)間
- 故障處理:如果某個(gè)執(zhí)行器連續(xù) 3 次心跳檢測(cè)失敗,調(diào)度中心會(huì)自動(dòng)把它從任務(wù)分配列表中剔除,就像發(fā)現(xiàn)某個(gè)員工總是摸魚,直接把他的任務(wù)派給其他人
- 數(shù)據(jù)統(tǒng)計(jì):記錄每個(gè)任務(wù)的執(zhí)行次數(shù)、成功率、平均耗時(shí),生成各種報(bào)表,方便我們排查性能瓶頸
劃重點(diǎn):調(diào)度中心支持集群部署,通過數(shù)據(jù)庫實(shí)現(xiàn)高可用(多個(gè)調(diào)度中心節(jié)點(diǎn)共享同一個(gè)數(shù)據(jù)庫,利用數(shù)據(jù)庫鎖保證主節(jié)點(diǎn)唯一性),就算其中一個(gè)節(jié)點(diǎn)掛了,其他節(jié)點(diǎn)馬上就能頂上,媽媽再也不用擔(dān)心半夜調(diào)度中心掛掉了!
2.2 執(zhí)行器:真正干活的 "打工人"
執(zhí)行器就是我們自己的業(yè)務(wù)代碼,需要集成 XXL-Job 的客戶端 SDK。主要職責(zé):
- 接收任務(wù):定時(shí)監(jiān)聽調(diào)度中心的任務(wù)請(qǐng)求,就像快遞員隨時(shí)等待調(diào)度中心派單
- 執(zhí)行任務(wù):調(diào)用具體的業(yè)務(wù)方法,比如發(fā)送短信、生成報(bào)表、清理過期數(shù)據(jù)
- 結(jié)果反饋:任務(wù)執(zhí)行完成后,不管成功還是失敗,都要給調(diào)度中心反饋結(jié)果,方便后續(xù)處理
這里有個(gè)很貼心的設(shè)計(jì):執(zhí)行器支持 "單機(jī)模式" 和 "分布式模式"。如果你的任務(wù)不需要分布式執(zhí)行(比如簡(jiǎn)單的本地文件清理),可以用單機(jī)模式;如果是復(fù)雜的分布式任務(wù)(比如分庫分表的數(shù)據(jù)統(tǒng)計(jì)),就用分布式模式,自動(dòng)實(shí)現(xiàn)任務(wù)分片。
2.3 任務(wù)隊(duì)列:調(diào)度中心和執(zhí)行器的 "傳話筒"
調(diào)度中心生成調(diào)度計(jì)劃后,不會(huì)直接通知執(zhí)行器,而是把任務(wù)放到隊(duì)列里(支持?jǐn)?shù)據(jù)庫隊(duì)列、Redis 隊(duì)列、Kafka 隊(duì)列)。執(zhí)行器主動(dòng)從隊(duì)列里拉取任務(wù),這種 "生產(chǎn)者 - 消費(fèi)者" 模式有兩個(gè)好處:
- 解耦:調(diào)度中心和執(zhí)行器不需要直接通信,降低系統(tǒng)耦合度
- 削峰填谷:如果突然有大量任務(wù)需要執(zhí)行(比如雙 11 零點(diǎn)的批量訂單處理),隊(duì)列可以緩沖任務(wù),避免執(zhí)行器被瞬間壓垮
我們項(xiàng)目里用的是數(shù)據(jù)庫隊(duì)列,因?yàn)闃I(yè)務(wù)量中等,數(shù)據(jù)庫性能足夠。如果是高并發(fā)場(chǎng)景,強(qiáng)烈建議用 Kafka 隊(duì)列,吞吐量能提升 10 倍以上!
三、實(shí)戰(zhàn)環(huán)節(jié):從 0 到 1 搭建 XXL-Job 調(diào)度系統(tǒng)
光說不練假把式,接下來帶大家實(shí)操一遍如何在 Spring Boot 項(xiàng)目中集成 XXL-Job。提前聲明:這里用的是 2.3.0 版本,最新版本可能有些配置會(huì)變,但核心流程差不多。
3.1 環(huán)境準(zhǔn)備:先把調(diào)度中心跑起來
調(diào)度中心是一個(gè)獨(dú)立的 Spring Boot 項(xiàng)目,官方已經(jīng)提供了源碼,我們只需要下載編譯即可:
- 下載源碼:
git clone https://github.com/xuxueli/xxl-job.git
cd xxl-job/xxl-job-admin
- 配置數(shù)據(jù)庫:創(chuàng)建數(shù)據(jù)庫xxl_job,執(zhí)行xxl-job/doc/db/tables_xxl_job.sql初始化表結(jié)構(gòu)。然后修改application.properties中的數(shù)據(jù)庫配置:
spring.datasource.url=jdbc:mysql://localhost:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
- 啟動(dòng)調(diào)度中心:直接運(yùn)行XxlJobAdminApplication的 main 方法,訪問http://localhost:8080/xxl-job-admin,默認(rèn)賬號(hào)密碼admin/123456
3.2 集成執(zhí)行器:讓你的業(yè)務(wù)代碼支持調(diào)度
假設(shè)我們有一個(gè)訂單服務(wù),需要定時(shí)關(guān)閉超時(shí)未支付的訂單,步驟如下:
- 添加 Maven 依賴:
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
- 配置執(zhí)行器參數(shù)(application.properties):
# XXL-Job配置
xxl.job.admin.addresses=http://localhost:8080/xxl-job-admin # 調(diào)度中心地址
xxl.job.executor.appname=order-executor # 執(zhí)行器名稱,用于調(diào)度中心識(shí)別
xxl.job.executor.ip= # 留空自動(dòng)獲取本機(jī)IP
xxl.job.executor.port=9999 # 執(zhí)行器端口,避免和其他服務(wù)沖突
xxl.job.executor.logpath=/data/xxl-job/logs # 日志存儲(chǔ)路徑
xxl.job.executor.logretentiondays=30 # 日志保留天數(shù)
- 創(chuàng)建執(zhí)行器配置類:
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XxlJobConfig {
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor xxlJobExecutor = new XxlJobSpringExecutor();
xxlJobExecutor.setAdminAddresses(xxlJobAdminAddresses);
xxlJobExecutor.setAppname(xxlJobExecutorAppname);
xxlJobExecutor.setIp(xxlJobExecutorIp);
xxlJobExecutor.setPort(xxlJobExecutorPort);
xxlJobExecutor.setLogPath(xxlJobExecutorLogpath);
xxlJobExecutor.setLogRetentionDays(xxlJobExecutorLogretentiondays);
return xxlJobExecutor;
}
}
- 編寫任務(wù)處理器:
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;
@Component
public class OrderCloseJob {
// 任務(wù)名稱隨便起,建議和業(yè)務(wù)相關(guān)
@XxlJob("orderCloseHandler")
public ReturnT<String> orderCloseHandler(String param) throws Exception {
// 業(yè)務(wù)邏輯:查詢所有超時(shí)未支付的訂單,狀態(tài)改為"已關(guān)閉"
int count = orderService.closeTimeoutOrders();
return ReturnT.SUCCESS("關(guān)閉訂單數(shù)量:" + count);
}
}
3.3 控制臺(tái)配置任務(wù):讓調(diào)度中心知道該干啥
回到調(diào)度中心界面,依次點(diǎn)擊【任務(wù)管理】-【新增任務(wù)】,填寫以下關(guān)鍵信息:
- 執(zhí)行器名稱:選擇剛才配置的order-executor
- 任務(wù) handler 名稱:就是我們?cè)诖a里寫的orderCloseHandler
- Cron 表達(dá)式:比如0 0 2 * * ?表示每天凌晨 2 點(diǎn)執(zhí)行
- 路由策略:如果是分布式執(zhí)行,建議選 "輪詢" 或 "隨機(jī)";如果是分片任務(wù),選 "分片廣播"
- 超時(shí)時(shí)間:根據(jù)任務(wù)實(shí)際執(zhí)行時(shí)間設(shè)置,比如 180 秒,防止任務(wù)卡死
- 失敗重試次數(shù):建議設(shè)置 3 次,第一次失敗后間隔 1 分鐘重試,第二次間隔 5 分鐘,第三次間隔 10 分鐘(可在系統(tǒng)配置里修改默認(rèn)重試策略)
保存后點(diǎn)擊【啟動(dòng)任務(wù)】,不出意外的話,任務(wù)會(huì)按照 Cron 表達(dá)式準(zhǔn)時(shí)執(zhí)行,執(zhí)行結(jié)果會(huì)顯示在【調(diào)度日志】里,點(diǎn)擊日志 ID 還能看到具體的執(zhí)行日志,簡(jiǎn)直不要太方便!
四、進(jìn)階玩法:這些高級(jí)功能讓你玩轉(zhuǎn)分布式任務(wù)
4.1 分片任務(wù):讓 1000 萬數(shù)據(jù)處理快到飛起
假設(shè)你要處理一張有 1000 萬條數(shù)據(jù)的表,單臺(tái)服務(wù)器處理可能需要 2 小時(shí),用分片任務(wù)可以輕松解決:
- 在任務(wù)配置里將路由策略設(shè)為 "分片廣播"
- 執(zhí)行器代碼中通過XxlJobHelper獲取分片參數(shù):
@XxlJob("dataProcessHandler")
public ReturnT<String> dataProcessHandler(String param) throws Exception {
// 獲取分片信息
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
// 計(jì)算當(dāng)前分片處理的數(shù)據(jù)范圍
long start = shardIndex * 10000;
long end = (shardIndex + 1) * 10000;
// 處理數(shù)據(jù)
dataService.processRange(start, end);
return ReturnT.SUCCESS("分片" + shardIndex + "處理完成");
}
- 調(diào)度中心會(huì)自動(dòng)將任務(wù)分配給多個(gè)執(zhí)行器節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)處理不同的分片,處理時(shí)間直接縮短到原來的 1/N(N 是節(jié)點(diǎn)數(shù))。我們項(xiàng)目用 4 臺(tái)服務(wù)器分片處理訂單統(tǒng)計(jì)任務(wù),原來需要 3 小時(shí),現(xiàn)在 40 分鐘就搞定了,運(yùn)維小哥看監(jiān)控的時(shí)候都驚掉了下巴。
4.2 故障轉(zhuǎn)移:讓任務(wù)永遠(yuǎn)不會(huì) "無人處理"
假設(shè)某個(gè)執(zhí)行器節(jié)點(diǎn)突然掛掉,正在處理的任務(wù)怎么辦?XXL-Job 有兩種處理策略:
- 快速失?。喝蝿?wù)直接標(biāo)記為失敗,觸發(fā)重試機(jī)制(適合非關(guān)鍵任務(wù))
- 故障轉(zhuǎn)移:調(diào)度中心檢測(cè)到節(jié)點(diǎn)故障后,會(huì)自動(dòng)將任務(wù)重新分配給其他正常節(jié)點(diǎn)(適合關(guān)鍵任務(wù),比如訂單支付回調(diào))
配置方法:在任務(wù)配置里的 "容錯(cuò)策略" 選擇 "故障轉(zhuǎn)移",默認(rèn)是快速失敗。建議對(duì)核心業(yè)務(wù)任務(wù)開啟故障轉(zhuǎn)移,雖然會(huì)增加一點(diǎn)延遲,但能保證任務(wù)最終執(zhí)行。
4.3 動(dòng)態(tài)參數(shù):讓任務(wù)配置更靈活
以前改任務(wù)參數(shù)得改代碼、打包、重啟,現(xiàn)在 XXL-Job 支持動(dòng)態(tài)傳遞參數(shù):
- 在任務(wù)配置的 "任務(wù)參數(shù)" 里填寫參數(shù),比如{"startTime":"2025-05-22 00:00:00","endTime":"2025-05-22 23:59:59"}
- 執(zhí)行器代碼中通過參數(shù)解析:
@XxlJob("reportGenerateHandler")
public ReturnT<String> reportGenerateHandler(String param) throws Exception {
// 解析JSON參數(shù)
ReportParam reportParam = JSON.parseObject(param, ReportParam.class);
// 生成報(bào)表
reportService.generate(reportParam.getStartTime(), reportParam.getEndTime());
return ReturnT.SUCCESS("報(bào)表生成完成");
}
甚至可以在調(diào)度中心手動(dòng)觸發(fā)任務(wù)時(shí)臨時(shí)修改參數(shù),比如某天需要重新生成昨天的報(bào)表,直接在觸發(fā)界面改時(shí)間參數(shù)就行,再也不用求開發(fā)改代碼了,運(yùn)營(yíng)小姐姐現(xiàn)在自己就能搞定。
五、原理剖析:為什么 XXL-Job 能做到高可靠、高性能?
5.1 調(diào)度流程大揭秘:從 Cron 表達(dá)式到任務(wù)執(zhí)行
- 表達(dá)式解析:調(diào)度中心啟動(dòng)時(shí),會(huì)掃描所有任務(wù)的 Cron 表達(dá)式,生成未來一段時(shí)間的調(diào)度計(jì)劃(默認(rèn)生成 1000 個(gè)調(diào)度周期),存在xxl_job_trigger表中
- 任務(wù)觸發(fā):調(diào)度中心有一個(gè)獨(dú)立的線程池,專門負(fù)責(zé)掃描xxl_job_trigger表中即將執(zhí)行的任務(wù),通過任務(wù)隊(duì)列發(fā)送給執(zhí)行器
- 執(zhí)行器響應(yīng):執(zhí)行器收到任務(wù)后,放入本地的線程池異步執(zhí)行,避免阻塞主線程
- 結(jié)果回調(diào):執(zhí)行器執(zhí)行完成后,通過 HTTP 接口將結(jié)果回調(diào)給調(diào)度中心,更新任務(wù)狀態(tài)和執(zhí)行日志
這里有個(gè)優(yōu)化點(diǎn):調(diào)度中心不會(huì)頻繁掃描數(shù)據(jù)庫,而是用 "時(shí)間輪" 算法(類似 Linux 的定時(shí)器)來管理調(diào)度計(jì)劃,性能比傳統(tǒng)的數(shù)據(jù)庫輪詢高 10 倍以上。
5.2 負(fù)載均衡策略:如何讓任務(wù)分配更合理
XXL-Job 支持 6 種路由策略,常用的有:
- 輪詢:按順序分配給每個(gè)執(zhí)行器節(jié)點(diǎn),適合無狀態(tài)任務(wù)
- 隨機(jī):隨機(jī)選擇節(jié)點(diǎn),適合負(fù)載均衡
- 最少活躍數(shù):選擇當(dāng)前執(zhí)行任務(wù)最少的節(jié)點(diǎn),適合 CPU 密集型任務(wù)
- 分片廣播:每個(gè)節(jié)點(diǎn)都執(zhí)行一次任務(wù),適合需要遍歷全量數(shù)據(jù)的任務(wù)
我們項(xiàng)目在處理訂單導(dǎo)出任務(wù)時(shí),用 "最少活躍數(shù)" 策略,讓配置高的服務(wù)器處理更多任務(wù),資源利用率提升了 30%。
5.3 容錯(cuò)機(jī)制:三層保護(hù)確保任務(wù)不丟失
- 調(diào)度中心容錯(cuò):集群部署,數(shù)據(jù)庫鎖保證主節(jié)點(diǎn)唯一性,即使所有調(diào)度中心節(jié)點(diǎn)掛掉,重啟后會(huì)自動(dòng)恢復(fù)未執(zhí)行的任務(wù)
- 執(zhí)行器容錯(cuò):任務(wù)執(zhí)行失敗時(shí),自動(dòng)記錄失敗次數(shù),達(dá)到重試次數(shù)后標(biāo)記為失敗,并觸發(fā)報(bào)警(需要配置報(bào)警郵箱或釘釘機(jī)器人)
- 數(shù)據(jù)持久化:所有任務(wù)調(diào)度記錄、執(zhí)行日志都存在數(shù)據(jù)庫里,支持歷史查詢和審計(jì),再也不用擔(dān)心任務(wù)執(zhí)行情況 "死無對(duì)證" 了
六、選型對(duì)比:XXL-Job、Quartz、Elastic-Job 到底怎么選?
6.1 適用場(chǎng)景對(duì)比
框架 | 適用場(chǎng)景 | 優(yōu)勢(shì) | 劣勢(shì) |
Quartz | 單體應(yīng)用、簡(jiǎn)單定時(shí)任務(wù) | 輕量、靈活 | 分布式支持差、管理界面需自建 |
Elastic-Job | 復(fù)雜分布式任務(wù)、高并發(fā)場(chǎng)景 | 支持分片、分布式協(xié)調(diào)強(qiáng)大 | 學(xué)習(xí)成本高、依賴 ZooKeeper |
XXL-Job | 中等規(guī)模分布式任務(wù)、快速落地 | 開箱即用、可視化管理、易維護(hù) | 功能復(fù)雜度低于 Elastic-Job |
6.2 我們?yōu)槭裁催x XXL-Job?
- 快速上線:從調(diào)研到上線只用了 3 天,包括搭建調(diào)度中心、改造業(yè)務(wù)代碼、配置監(jiān)控報(bào)警
- 易維護(hù):運(yùn)維同學(xué)通過 Web 界面就能管理任務(wù),再也不用求開發(fā)改代碼
- 社區(qū)活躍:作者持續(xù)更新,Issues 響應(yīng)快,遇到問題基本都能在社區(qū)找到解決方案
- 多語言支持:雖然我們用 Java,但未來如果有 Python 服務(wù)需要接入,直接用官方提供的 Python 執(zhí)行器就行
6.3 避坑指南:這些坑我們替你踩過了
- 端口沖突:執(zhí)行器端口默認(rèn)是 9999,如果和其他服務(wù)沖突,記得在配置里修改,否則啟動(dòng)會(huì)報(bào)錯(cuò)
- 分片參數(shù)解析:用分片廣播時(shí),一定要檢查shardIndex和shardTotal是否正確,否則可能導(dǎo)致數(shù)據(jù)重復(fù)處理或遺漏
- 日志存儲(chǔ):默認(rèn)日志存在本地磁盤,如果執(zhí)行器是 Docker 容器,記得掛載日志目錄,否則容器重啟后日志就沒了
- 任務(wù)超時(shí):如果任務(wù)執(zhí)行時(shí)間超過配置的超時(shí)時(shí)間,調(diào)度中心會(huì)強(qiáng)制終止任務(wù)(通過調(diào)用線程的 interrupt 方法),但對(duì)于數(shù)據(jù)庫連接等資源可能無法正確釋放,建議在代碼里做好超時(shí)處理
- 數(shù)據(jù)庫分表:如果任務(wù)量非常大(比如每天百萬級(jí)調(diào)度記錄),建議對(duì)xxl_job_trigger、xxl_job_log等表進(jìn)行分表,否則單表數(shù)據(jù)量過大會(huì)影響查詢性能
七、寫在最后:XXL-Job 真香,但別濫用!
說實(shí)話,剛開始聽說要用 XXL-Job 的時(shí)候,我心里是抗拒的 —— 畢竟 Quartz 用了好幾年,代碼里到處都是它的影子,改造起來麻煩。但真正用了之后才發(fā)現(xiàn),真香!現(xiàn)在我們項(xiàng)目里的定時(shí)任務(wù):
- 從原來的 "黑盒" 變成了 "透明工廠",每個(gè)任務(wù)的執(zhí)行狀態(tài)、耗時(shí)、失敗原因都一目了然
- 運(yùn)維效率提升 50% 以上,再也不用半夜起來改配置文件、重啟服務(wù)
- 故障處理更從容,任務(wù)失敗自動(dòng)重試,關(guān)鍵任務(wù)還有故障轉(zhuǎn)移,運(yùn)營(yíng)小姐姐再也沒打過半夜電話
但還是要提醒大家:XXL-Job 雖然強(qiáng)大,但不是萬能的。如果你的項(xiàng)目還是單體應(yīng)用,任務(wù)量不大,用 Quartz 完全夠用,沒必要引入這么復(fù)雜的調(diào)度平臺(tái)。但如果是分布式系統(tǒng),有大量定時(shí)任務(wù)需要管理,那 XXL-Job 絕對(duì)是你的不二之選。