Spring quartz 叢集模式下trigger_state error問題原因

wtopps發表於2017-08-31

問題描述

在專案中採用了Spring quartz排程任務來執行定時任務,quartz本身是支援叢集化方式的,可以配置一個資料來源,quartz會在資料庫中建立一系列的表,使用這些表來儲存排程的資訊,叢集中所有的節點都訪問這一個資料庫,這樣可以實現叢集環境下的定時任務排程。

但是在最近生產環境出現了這樣的問題,新增的一個定時排程任務,當服務啟動後,執行兩次以後,該任務就不再執行了,但是其他原有的定時任務並沒有出現問題,只有這個新增的任務無法執行,檢查qrtz_triggers表,發現該條排程任務的記錄的trigger_state變成了”error”狀態。

問題分析

1、檢查是否新增的定時任務丟擲異常,導致了任務中斷,加入大量的日誌以及異常捕獲,未發現任何異常的日誌,排除了程式碼報錯的可能

2、猜測是否是因為資料庫中排程相關表存在髒資料,導致了新增的排程任務不執行;隨後將相關表全部清空,重啟叢集中所有節點,觀察,發現仍然是執行兩次後變為”error”

3、檢查qrtz_scheduler_state表,發現存在多條記錄,根據網上查詢的資訊,將多條記錄刪除,只保留一條,再重啟叢集,觀察,發現仍然不行

4、由第三條可知,qrtz_scheduler_state表中有多條記錄,仔細觀察instance_name的記錄,發現是由伺服器節點的例項名加數字組成,將instance的地址與叢集中每個節點進行對比,發現問題原因,有兩個instance的id並不在生成環境的叢集節點中,但是與叢集公用一個資料庫,那兩個節點的程式碼版本,發現與當前線上版本不一致,沒有新增的定時排程任務,由此導致了該問題的發生

問題總結

當使用quartz叢集模式時,當叢集中的程式碼版本不一致,會出現qrtz_triggers中trigger_state的狀態變為”error”的情況,原因是叢集模式先quartz執行排程任務,是根據資料庫表中的排程記錄進行執行,當執行到有對應程式碼的節點上,不會出現問題,但是當執行到沒有對應程式碼的節點上,就會變為”error”,
因此在叢集環境下,節點較多的時候使用quartz,需要注意每個節點的程式碼版本一定要保持一致

相關文章