SpringBoot集成XXL-JOB實現(xiàn)靈活控制的分片處理方案
場景
一個應(yīng)用需要支持大量數(shù)據(jù)的批處理任務(wù),要求:
- 并行處理能力:應(yīng)用需能夠同時處理多個數(shù)據(jù)塊,即實現(xiàn)并行處理。
- 靈活的并發(fā)控制:可以靈活調(diào)整并行處理的任務(wù)數(shù)量,以確保資源利用最大化且不過載。
- 均衡負(fù)載分配:應(yīng)將任務(wù)均勻分配到不同的服務(wù)器節(jié)點上,以平衡各節(jié)點的負(fù)載,避免單點壓力過大。
解決思路
因為需要并行處理同一張數(shù)據(jù)表里的數(shù)據(jù),所以比較自然地想到了分片查詢數(shù)據(jù),可以利用對 id 取模的方法進(jìn)行分片,避免同一條數(shù)據(jù)被重復(fù)處理。那XXL-JOB 的路由策略「分片廣播 & 動態(tài)分片」很貼合這種場景」來調(diào)度定時任務(wù);
實現(xiàn)DEMO
SpringBoot環(huán)境下,我們集成xxl-job來實現(xiàn)上述方案。
SpringBoot如何集成xxl-job查看官網(wǎng)即可,這里不再敘述,下面看下分片調(diào)度的代碼:
1.xxl-job調(diào)度管理頁面配置分片調(diào)度任務(wù)
路由策略選擇: 分片廣播

2. 編寫task代碼:
要獲取分片總數(shù)和當(dāng)前分片序號,作為參數(shù)傳給sql語句:
@Resource
private OrderDataMapper orderDataMapper;
@XxlJob("orderDataStatusTask")
public void orderDataStatusTask() {
// 計時器
Stopwatch timer = Stopwatch.createStarted();
// 獲取xxl-job的localThread中的總的分片數(shù)和當(dāng)前分片
OrderDataParam param = new OrderDataParam();
param.setShardIndex(XxlJobHelper.getShardIndex());
param.setShardTotal(XxlJobHelper.getShardTotal());
// 其他參數(shù)設(shè)置,略了....
// 根據(jù)分片數(shù)拉取當(dāng)前分片的數(shù)據(jù)
List<OrderData> orderDataList = orderDataMapper.getInitStatusOrder(param);
XxlJobHelper.log("獲取待處理訂單數(shù)據(jù):分片號={},數(shù)據(jù)量={},總分片數(shù)={}", XxlJobHelper.getShardIndex(), orderDataList.size(), XxlJobHelper.getShardTotal());
if (CollUtil.isEmpty(orderDataList)) {
return;
}
// 處理邏輯,略了....
XxlJobHelper.log("當(dāng)前分片({})處理完成,耗時={}秒", XxlJobHelper.getShardIndex(), timer.stop().elapsed(TimeUnit.SECONDS));
}
這里服務(wù)啟動了4個實例,總分片數(shù)ShardTotal就是4,每個實例的ShardIndex分別是0,1,2,3

3. mybatis中編寫sql語句
根據(jù)分片總數(shù)和當(dāng)前分片數(shù)據(jù)對Id哈希取模, 這里做了兩次hash,主要作用是用id最后一位hash方便直接看出數(shù)據(jù)被哪個分片調(diào)度了。
// 獲取未處理的訂單數(shù)據(jù)
// 根據(jù)id末位數(shù)取hash后分片拉取
<select id="getInitStatusOrder" parameterType="com.xxx.OrderDataParam"
resultType="com.xxx.OrderData">
select id,order_no,customer_code,
from tt_order_data t
where t.status = 0
and t.fail_count <![CDATA[ < ]]> #{retryCount}
and t.update_time <![CDATA[ >= ]]> #{lastUpdateTime}
and mod(mod(t.id, 10) , #{shardTotal}) = #{shardIndex}
limit 0,200
</select>
4.最后看下調(diào)度日志
同一次調(diào)度任務(wù),4個實例個調(diào)度一次,并且拉取到各自部分的數(shù)據(jù)進(jìn)行處理:
第3個實例的調(diào)度日志:
2024-09-25 08:31:40 [com.xxl.job.core.thread.JobThread#run]-[130]-[Thread-144]
----------- xxl-job job execute start -----------
----------- Param:{"lastHoursAgoModify":4,"rows":3000,"lastMonthAgoCreate":6,"retryCount":1}
2024-09-25 08:31:40 [com.xxx.xxxx#orderDataStatusTask]-[47]-[Thread-144] 獲取待處理訂單數(shù)據(jù):分片號=3,數(shù)據(jù)量=100,總分片數(shù)=4
2024-09-25 08:31:41 [com.xxx.xxxx#orderDataStatusTask]-[53]-[Thread-144] 當(dāng)前分片(3)處理完成,耗時=1秒
2024-09-25 08:31:41 [com.xxl.job.core.thread.JobThread#run]-[176]-[Thread-144]
----------- xxl-job job execute end(finish) -----------
----------- Result: handleCode=200, handleMsg = null
2024-09-25 08:31:41 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
第4個實例的調(diào)度日志:
2024-09-25 08:31:40 [com.xxl.job.core.thread.JobThread#run]-[130]-[Thread-144]
----------- xxl-job job execute start -----------
----------- Param:{"lastHoursAgoModify":4,"rows":3000,"lastMonthAgoCreate":6,"retryCount":1}
2024-09-25 08:31:40 [com.xxx.xxxx#orderDataStatusTask]-[47]-[Thread-144] 獲取待處理訂單數(shù)據(jù):分片號=4,數(shù)據(jù)量=80,總分片數(shù)=4
2024-09-25 08:31:41 [com.xxx.xxxx#orderDataStatusTask]-[53]-[Thread-144] 當(dāng)前分片(4)處理完成,耗時=1秒
2024-09-25 08:31:41 [com.xxl.job.core.thread.JobThread#run]-[176]-[Thread-144]
----------- xxl-job job execute end(finish) -----------
----------- Result: handleCode=200, handleMsg = null
2024-09-25 08:31:41 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
到此這篇關(guān)于SpringBoot集成XXL-JOB實現(xiàn)靈活控制的分片處理方案的文章就介紹到這了,更多相關(guān)SpringBoot XXL-JOB分片處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- xxl-job定時任務(wù)配置應(yīng)用及添加到springboot項目中實現(xiàn)動態(tài)API調(diào)用
- SpringBoot集成xxl-job實現(xiàn)超牛的定時任務(wù)的步驟詳解
- SpringBoot部署xxl-job方法詳細(xì)講解
- springboot整合xxl-job實現(xiàn)分布式定時任務(wù)的過程
- 分布式調(diào)度XXL-Job整合Springboot2.X實戰(zhàn)操作過程(推薦)
- SpringBoot整合Xxl-job實現(xiàn)定時任務(wù)的全過程
- SpringBoot整合Xxl-Job的完整步驟記錄
- springboot整合 xxl-job及使用步驟
相關(guān)文章
SpringBoot使用MockMvc進(jìn)行Web集成測試的示例詳解
MockMvc?是一個測試框架,可以模擬?HTTP?請求和響應(yīng),在本文中,我們將介紹如何使用MockMvc進(jìn)行Web集成測試,以及如何編寫測試用例來測試Spring?MVC控制器,希望對大家有所幫助2023-06-06
java基礎(chǔ)--自己動手實現(xiàn)一個LRU
這篇文章主要介紹了運用方案如何實現(xiàn)LUR,文章中通過代碼講解的非常詳細(xì),對大家的工作或?qū)W習(xí)有一定的參考價值,感興趣的朋友可以參考一下2021-08-08
使用Spark?SQL實現(xiàn)讀取不帶表頭的txt文件
這篇文章主要為大家詳細(xì)介紹了如何使用Spark?SQL實現(xiàn)讀取不帶表頭的txt文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
Java利用遞歸實現(xiàn)樹形結(jié)構(gòu)的工具類
有時候,我們的數(shù)據(jù)是帶有層級的,比如常見的省市區(qū)三級聯(lián)動,就是一層套著一層。而我們在數(shù)據(jù)庫存放數(shù)據(jù)的時候,往往是列表形式的,這個時候可能就需要遞歸處理為樹形結(jié)構(gòu)了。本文就為大家介紹了Java利用遞歸實現(xiàn)樹形結(jié)構(gòu)的工具類,希望對大家有所幫助2023-03-03
Java的靜態(tài)方法Arrays.asList()使用指南
Arrays.asList() 是一個 Java 的靜態(tài)方法,它可以把一個數(shù)組或者多個參數(shù)轉(zhuǎn)換成一個 List 集合,這個方法可以作為數(shù)組和集合之間的橋梁,方便我們使用集合的一些方法和特性,本文將介紹 Arrays.asList() 的語法、應(yīng)用場景、坑點和總結(jié)2023-09-09
Spring之SseEmitter實現(xiàn)讓你的進(jìn)度條實時更新
Spring SseEmitter是一種實現(xiàn)服務(wù)器端推送事件(SSE)的機制,支持單向通信,適用于實時數(shù)據(jù)傳輸需求,通過代碼示例和應(yīng)用場景分析,展示了如何在服務(wù)端和客戶端使用SseEmitter進(jìn)行實時數(shù)據(jù)推送2025-02-02
詳解Mybatis中javaType和ofType的區(qū)別
本文主要介紹了詳解Mybatis中javaType和ofType的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05

