2012-02-15 160 views
15

我正在尋找推薦的解決方案來解決celerybeat是芹菜/ rabbitmq部署的單點故障。通過搜索網絡,我沒有發現任何有意義的東西。解決celerybeat是單點故障

就我而言,每天一次定時調度程序啓動一系列可能運行半天或更長時間的作業。由於只能有一個celerybeat實例,所以如果它或它運行的服務器發生了問題,關鍵作業將不會運行。

我希望已經有一個工作解決方案,因爲我不能是唯一需要可靠(集羣或類似)調度程序的人。如果我不需要,我不想訴諸某種數據庫支持的調度程序。

回答

5

芹菜github回購存在一個問題。不知道他們是否正在努力。

作爲解決方法,您可以爲任務添加一個鎖,以便一次只運行特定PeriodicTask的一個實例。

喜歡的東西:

if not cache.add('My-unique-lock-name', True, timeout=lock_timeout): 
    return 

搞清楚鎖定超時是很好,很棘手。我們使用0.9 *任務run_every秒,如果不同的celerybeats會嘗試在不同的時間運行它們。只是爲了留下一些餘量(例如,當芹菜稍微落後於一次計劃時,那麼它按計劃會導致鎖仍然活動)。

然後,您可以在所有機器上使用celerybeat實例。每個任務將爲每個celerybeat實例排隊,但只有一個任務會完成運行。

任務仍然遵循run_every這種方式 - 最壞的情況:任務將以0.9 * run_every速度運行。

這種情況下的一個問題是:如果任務在排定時間排隊但未在預定時間處理(例如因爲隊列處理器不可用) - 則鎖定可能放置在錯誤的時間,導致可能1個下一個任務無法運行。爲了解決這個問題,你需要某種檢測機制,無論任務是按時或多或少。

但是,在生產中使用時,這不應該是常見的情況。

另一種解決方案是將celerybeat調度器子類化並覆蓋它的tick方法。然後在處理任務之前爲每個滴答聲添加一個鎖。這確保了只有具有相同週期性任務的celerybeats纔會多次排隊同一個任務。每個勾號只有一個celerybeat(贏得比賽條件的人)將排隊任務。在一個芹菜跳下去的時候,下一個跳動的另一個將贏得比賽。

這當然可以與第一個解決方案結合使用。

當然,對於這項工作,緩存後端需要爲所有服務器進行復制和/或共享。

這是一個老問題,但我希望它可以幫助任何人。