聊聊專案中定時任務的處理方式

2023-02-06 06:01:38

  一個專案中一般都少不了定時任務,主要用來處理一些特殊的任務,有的是隻執行一次的

定時任務,有的是週期迴圈執行的定時任務。可根據專案需要來選擇定時任務型別。自己參與

開發的一個專案中,因為很多定時任務都是需要週期執行的,因此選用按週期迴圈執行的方式。

比如幾分鐘過載一次主表資料,過載資料字典表資料,定時更新主表資料狀態,定時更新快取

資料到資料庫中的定時任務等等。因此在專案最開始設計的時候,架構人員就考慮使用使用

週期性定時任務來處理各種任務。

  整體的大致思路是在專案啟動的時候,立馬啟動固定的執行緒數,比如18個執行緒,然後讓

這些執行緒去輪流執行定時任務,建立方式為Executors.newFixedThreadPool(20)。這種方式是

阿里巴巴的《Java開發手冊》中推薦的建立執行緒的一種方式。建立完執行緒池後,下一步就是

使用執行緒物件去定時執行任務,可以傳入一些引數,比如延遲啟動時間,執行間隔時間,需要

執行的任務物件等等。最後一步最重要的,就是寫定時任務處理類,定時任務類需要實現Runnable

介面,然後重寫run方法,接下來主要的定時任務邏輯都寫在run方法中。

  定時任務類中可能會查詢資料庫資料,或者是參照其他的service服務類來處理業務邏輯,這時

需要新增一個@Component註解即可將這個類交給Spring統一處理,也能自動注入需要使用的其他類。

自己最近寫的一個定時任務也是同樣的處理方式。資料的處理流程為,使用定時任務1將符合條件的

A中的資料定時新增到記憶體中;使用定時任務2將符合要求的表A的資料,按照一定的規則新增到

B中,並且將表B返回的ID新增到redis佇列中;使用定時任務3redis佇列中獲取資料,如果佇列

中有資料,則進行後續處理,將表B中的資料按照一定的規則新增到表C。這樣整個業務流程都串起來,

使用者登入系統後直接查詢表C的資料即可。

  自己寫好功能後,反反覆覆地進行測試,發現一些問題,比如定時任務在一個週期內只想時間過長,

還未執行完成,下一次的執行任務又開始執行。這顯然是不符合要求的,那怎麼解決呢?看過同事以前

寫的程式碼,解決辦法為新增分散式鎖。自己立馬去修復這個問題,對於需要新增分散式鎖的兩個定時任務

立馬新增分散式鎖,執行之前先獲取鎖,如果獲取到鎖則執行定時任務,沒有獲取到鎖這不執行任務。

經過測試問題解決。第二個問題是,執行時間間隔的問題,本地開發環境只有單個伺服器在執行,測試

環境中也只有一臺伺服器執行,都沒問題,可是生產環境上有多臺伺服器在執行,定時任務的執行時間

就需要從新分配。比如某個定時任務計劃是10s執行一次,生產環境有5臺,就需要將間隔時間設定

50s執行一次,不然可能出現的問題就是執行頻率遠遠大於10s。因為是多臺伺服器在同時執行定時

任務,而且開始執行的時間還不一致,所及執行時間間隔需要慎重計算。

  曾經參與開發過的專案中,有的會有一個單獨的定時任務專案,用來執行各種可設定的定時任務,

當然這些都是根據具體專案來選用和開發的。以上就是關於定時任務執行的整個設計思路,有其他

更好建議的小夥伴,歡迎留言討論。