elasticJob misfire任務錯過機制


  elasticJob的分片任務在調度執行中,由於某種原因未執行完畢,下一次調度任務觸發后,如果在同一個Job實例中出現兩個線程處理同一個分片上的數據,這樣就會造成兩個線程處理到相同的數據。

  為了避免上述問題,Elastic-Job引入任務錯過機制(misfire)與冪等機制(monitorExecution),來確保同一條數據不會被多個Job同時處理,避免同一條數據被同一個Job實例的多個線程處理。

  重申一次Elastci-Job的分布式是數據的分布式,一個任務在多個Job實例上運行,每個Job實例處理該Job的部分數據(數據分片)。

1、Elastic-Job如何確保同一個Job實例的多個線程不會處理相同的數據。

  場景:任務調度周期為每5s執行一次,正常每次調度任務處理需要耗時2s,如果在某一段時間由於數據庫壓力變大,導致原本只需要2s就能處理完成的任務,現在需要16s才能完成。
  在這個數據處理的過程中,每5s又會觸發一次調度(任務處理),如果不加以控制的話,在同一個實例上根據分片條件去查詢數據庫,查詢到的數據有可能相同(部分相同),這樣同一條任務數據將被多次運行。
如果這個任務是處理轉賬業務,如果在業務方法不實現冪等,則會引發非常嚴重的問題,那ElasticJob是否可以避免這個問題呢?

  答案是肯定。elastic-Job提供了一個配置參數:monitorExecution=true,開啟冪等性。

冪等機制開啟后的工作流程:

  (1)Elastic-Job在開啟monitorExecution(true)【冪等機制】機制的情況下,在分片任務開始時會在注冊中心zookeeper上創建${namespace}/jobname/sharding/{item}/running臨時節點,在任務結束后會刪除該目錄。

  (2)在判斷是否有分片正在運行時,只需判斷是否存在上述節點即可。如果存在,調用setMisfire方法,將分片狀態設置為mirefire,表示錯失了一次任務執行。如果該分片被設置為mirefire並開啟了事件跟蹤,將事件跟蹤保存在數據庫中。

  (3)設置misfire的方法會為分配給該實例下的所有分片創建持久節點${namespace}/jobname/shading/{item}/misfire節點。

  (4)注意,只要分配給該實例的任何一分片未執行完畢,則在該實例下的所有分片都增加misfire節點,然后忽略本次任務觸發執行,等待任務結束后再執行其他未忽略的任務。

  (5)在任務執行完成后檢查是否存在${namespace}/jobname/sharding/{item}/misfire節點,如果存在,則首先清除misfie相關的文件,然后執行任務。

Elastic-Job的misfire實現方案總結:

  在下一個調度周期到達之后,只要發現這個分片的任何一個分片正在執行,則為該實例分片的所有分片都設置為misfire,等任務執行完畢后,再統一執行下一次任務調度。

技術原理其實很簡單,就是通過zookeeper來實現分布式鎖來完成冪等性。

2、Elastic-Job如何確保數據不會被多個Job實例處理?

  Elastic-Job基於數據分片,不同分片根據分片參數(人為配置),從數據庫中查詢各自數據(任務數據分片),如果當節點宕機,數據會重新分片,如果任務未執行完成,然后執行分片,數據是否會被不同的任務同時處理呢?

  答案是不會,因為當節點宕機(作業執行節點)后,是否需要重新分片事件監聽器會監聽到Job實例代表的節點刪除,設置重新分片。在任務被調度執行具體處理邏輯之前,需要重新分片,重新分片的前提就是要所有的分片任務全部執行完畢,這也依賴是否開啟冪等控制(monitorExecution)。

  如果開啟冪等機制,Elastic-Job能感知正在執行處理邏輯的分片,重新分片需要等待當前所有分片任務全部運行完畢后才會觸發,故不會存在不同節點處理相同數據的問題。

  場景:一個任務JOB的調度頻率為每10s一次,在某個時間,該job執行耗時用了33s(平時只需執行5s),按照正常調度,應該后續會觸發3次調度,那該job后執行完,會連續執行3次調度嗎?

  答案:在33s這次任務執行完成后,如果后面的任務執行在10s內執行完畢的話,只會觸發一次,不會補償3次,因為ElasticJob記錄任務錯失執行,只是創建了misfire節點,並不會記錄錯失的次數,因為也沒這個必要。

3、Elastic-Job的misfire功能對於執行頻率很高的任務,是不是不起作用?

  misfire在間隔時間短的任務中比較雞肋。按照這個例子說,20s之后,新一次的作業就執行了,沒必要再進行misfire。

  misfire的正確用法是用於處理間隔時間長的作業,或者業務有局限的作業。舉個例子:

  1天跑一次的報表作業,作業的業務邏輯中寫死本次作業只抓取昨天的數據。那么一旦上次作業跑動超過一天,那么第二天本該運行的作業就失去了運行的機會,第二天的數據也會缺失。因此需要misfire。

  如果業務寫的足夠好,比如,無論哪天跑都能把未處理的數據分好組生成報表,misfire的存在意義就僅僅是觸發時間縮短而已了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM