SpringBoot集成XXL-JOB實(shí)現(xiàn)靈活控制的分片處理方案
場(chǎng)景
一個(gè)應(yīng)用需要支持大量數(shù)據(jù)的批處理任務(wù),要求:
- 并行處理能力:應(yīng)用需能夠同時(shí)處理多個(gè)數(shù)據(jù)塊,即實(shí)現(xiàn)并行處理。
- 靈活的并發(fā)控制:可以靈活調(diào)整并行處理的任務(wù)數(shù)量,以確保資源利用最大化且不過(guò)載。
- 均衡負(fù)載分配:應(yīng)將任務(wù)均勻分配到不同的服務(wù)器節(jié)點(diǎn)上,以平衡各節(jié)點(diǎn)的負(fù)載,避免單點(diǎn)壓力過(guò)大。
解決思路
因?yàn)樾枰⑿刑幚硗粡垟?shù)據(jù)表里的數(shù)據(jù),所以比較自然地想到了分片查詢數(shù)據(jù),可以利用對(duì) id 取模的方法進(jìn)行分片,避免同一條數(shù)據(jù)被重復(fù)處理。那XXL-JOB 的路由策略「分片廣播 & 動(dòng)態(tài)分片」很貼合這種場(chǎng)景」來(lái)調(diào)度定時(shí)任務(wù);
實(shí)現(xiàn)DEMO
SpringBoot環(huán)境下,我們集成xxl-job來(lái)實(shí)現(xiàn)上述方案。
SpringBoot如何集成xxl-job查看官網(wǎng)即可,這里不再敘述,下面看下分片調(diào)度的代碼:
1.xxl-job調(diào)度管理頁(yè)面配置分片調(diào)度任務(wù)
路由策略選擇: 分片廣播
2. 編寫task代碼:
要獲取分片總數(shù)和當(dāng)前分片序號(hào),作為參數(shù)傳給sql語(yǔ)句:
@Resource private OrderDataMapper orderDataMapper; @XxlJob("orderDataStatusTask") public void orderDataStatusTask() { // 計(jì)時(shí)器 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ù):分片號(hào)={},數(shù)據(jù)量={},總分片數(shù)={}", XxlJobHelper.getShardIndex(), orderDataList.size(), XxlJobHelper.getShardTotal()); if (CollUtil.isEmpty(orderDataList)) { return; } // 處理邏輯,略了.... XxlJobHelper.log("當(dāng)前分片({})處理完成,耗時(shí)={}秒", XxlJobHelper.getShardIndex(), timer.stop().elapsed(TimeUnit.SECONDS)); }
這里服務(wù)啟動(dòng)了4個(gè)實(shí)例,總分片數(shù)ShardTotal就是4,每個(gè)實(shí)例的ShardIndex分別是0,1,2,3
3. mybatis中編寫sql語(yǔ)句
根據(jù)分片總數(shù)和當(dāng)前分片數(shù)據(jù)對(duì)Id哈希取模, 這里做了兩次hash,主要作用是用id最后一位hash方便直接看出數(shù)據(jù)被哪個(gè)分片調(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個(gè)實(shí)例個(gè)調(diào)度一次,并且拉取到各自部分的數(shù)據(jù)進(jìn)行處理:
第3個(gè)實(shí)例的調(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ù):分片號(hào)=3,數(shù)據(jù)量=100,總分片數(shù)=4 2024-09-25 08:31:41 [com.xxx.xxxx#orderDataStatusTask]-[53]-[Thread-144] 當(dāng)前分片(3)處理完成,耗時(shí)=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個(gè)實(shí)例的調(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ù):分片號(hào)=4,數(shù)據(jù)量=80,總分片數(shù)=4 2024-09-25 08:31:41 [com.xxx.xxxx#orderDataStatusTask]-[53]-[Thread-144] 當(dāng)前分片(4)處理完成,耗時(shí)=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實(shí)現(xiàn)靈活控制的分片處理方案的文章就介紹到這了,更多相關(guān)SpringBoot XXL-JOB分片處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- xxl-job定時(shí)任務(wù)配置應(yīng)用及添加到springboot項(xiàng)目中實(shí)現(xiàn)動(dòng)態(tài)API調(diào)用
- SpringBoot集成xxl-job實(shí)現(xiàn)超牛的定時(shí)任務(wù)的步驟詳解
- SpringBoot部署xxl-job方法詳細(xì)講解
- springboot整合xxl-job實(shí)現(xiàn)分布式定時(shí)任務(wù)的過(guò)程
- 分布式調(diào)度XXL-Job整合Springboot2.X實(shí)戰(zhàn)操作過(guò)程(推薦)
- SpringBoot整合Xxl-job實(shí)現(xiàn)定時(shí)任務(wù)的全過(guò)程
- SpringBoot整合Xxl-Job的完整步驟記錄
- springboot整合 xxl-job及使用步驟
相關(guān)文章
利用Java中Calendar計(jì)算兩個(gè)日期之間的天數(shù)和周數(shù)
Java 語(yǔ)言的Calendar(日歷),Date(日期),和DateFormat(日期格式)組成了Java標(biāo)準(zhǔn)的一個(gè)基本但是非常重要的部分。日期是商業(yè)邏輯計(jì)算一個(gè)關(guān)鍵的部分。下面這篇文章就給大家介紹了如何利用Java中Calendar計(jì)算兩個(gè)日期之間的天數(shù)和周數(shù),下面來(lái)一起看看吧。2016-12-12Java常見基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
這篇文章主要介紹了Java常見數(shù)據(jù)結(jié)構(gòu)面試題,帶有答案及解釋,希望對(duì)廣大的程序愛好者有所幫助,同時(shí)祝大家有一個(gè)好成績(jī),需要的朋友可以參考下,希望可以幫助到你2021-07-07Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之生活旅行分享平臺(tái)的實(shí)現(xiàn)
這是一個(gè)使用了java+Springboot+JPA+Jsp+Html+js+Ajax+maven+mysql開發(fā)的生活旅行分享平臺(tái),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有分享發(fā)布平臺(tái)該有的所有功能,感興趣的朋友快來(lái)看看吧2022-02-02Java實(shí)現(xiàn)解析dcm醫(yī)學(xué)影像文件并提取文件信息的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)解析dcm醫(yī)學(xué)影像文件并提取文件信息的方法,結(jié)合實(shí)例形式分析了java基于第三方庫(kù)文件針對(duì)dcm醫(yī)學(xué)影像文件的解析操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-04-04SpringBoot實(shí)現(xiàn)多環(huán)境配置文件切換教程詳解
很多時(shí)候,我們項(xiàng)目在開發(fā)環(huán)境和生成環(huán)境的環(huán)境配置是不一樣的,例如,數(shù)據(jù)庫(kù)配置,這個(gè)時(shí)候就需要切換環(huán)境配置文件。本文將詳細(xì)講解SpringBoot如何切換配置文件,需要的可以參考一下2022-03-03Java concurrency之AtomicLongArray原子類_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java concurrency之AtomicLongArray原子類的相關(guān)知識(shí),感興趣的朋友參考下吧2017-06-06