分布式定時(shí)任務(wù)(一)

1,什么是分布式定時(shí)任務(wù);
2,為什么要采用分布式定時(shí)任務(wù)
3,怎么樣設(shè)計(jì)實(shí)現(xiàn)一個(gè)分布式定時(shí)任務(wù)
4,當(dāng)前比較流行的分布式定時(shí)任務(wù)框架

1,什么是分布式定時(shí)任務(wù)

  • 首先,我們要了解計(jì)劃任務(wù)這個(gè)概念,計(jì)劃任務(wù)是指由計(jì)劃的定時(shí)運(yùn)行或者周期性運(yùn)行的程序。我們最常見的就是Linux的‘crontab’和Windows的‘計(jì)劃任務(wù)’。

  • 那么什么是分布式定時(shí)任務(wù),個(gè)人總結(jié)為:把分散的,可靠性差的計(jì)劃任務(wù)納入統(tǒng)一的平臺(tái),并實(shí)現(xiàn)集群管理調(diào)度和分布式部署的一種定時(shí)任務(wù)的管理方式。叫做分布式定時(shí)任務(wù)。

2,為什么要采用分布式定時(shí)任務(wù)

單點(diǎn)定時(shí)任務(wù)的缺點(diǎn):

  • 功能相對簡單,交互性差,任務(wù)部署效率低,開發(fā)和維護(hù)成本比較高,不能很好的滿足各系統(tǒng)定時(shí)任務(wù)的管理和控制,尤其在多系統(tǒng)的環(huán)境下更加明顯;
  • 許多任務(wù)都是單機(jī)部署,可用性差;
  • 任務(wù)跟蹤和告警難以實(shí)現(xiàn)。

分布式定時(shí)任務(wù)的優(yōu)勢

  • 通過集群的方式進(jìn)行管理調(diào)度,大大降低了開發(fā)和維護(hù)成本;
  • 分布式部署,保證了系統(tǒng)的高可用性,伸縮性,負(fù)載均衡,提高了容錯(cuò);
  • 可以通過控制臺(tái)部署和管理定時(shí)任務(wù),方便靈活高效;
  • 任務(wù)都可以持久化到數(shù)據(jù)庫,避免了宕機(jī)和數(shù)據(jù)丟失帶來的隱患,同時(shí)有完善的任務(wù)失敗重做機(jī)制和詳細(xì)的任務(wù)跟蹤及告警策略。

3,怎么樣設(shè)計(jì)和實(shí)現(xiàn)一個(gè)分布式定時(shí)任務(wù)
3.1 分時(shí)方案

  • 嚴(yán)格劃分時(shí)間片,交替運(yùn)行計(jì)劃任務(wù),當(dāng)主系統(tǒng)宕機(jī)后,備用系統(tǒng)仍然工作,但是處理初期被拉長了。
  • 缺點(diǎn):周期延長了。
untitled.png

3.2 HA高可用方案:

  • 正常情況下主系統(tǒng)工作,備用系統(tǒng)守候,心跳檢測發(fā)現(xiàn)主系統(tǒng)出現(xiàn)故障備用系統(tǒng)啟動(dòng)。
  • 缺點(diǎn):單一系統(tǒng),不能做負(fù)載均衡,只能垂直擴(kuò)展,也就是硬件層面的升級(jí),無法做水平擴(kuò)展。
untitled1.png

3.3 多路心跳方案:

  • 采用多路心跳,做服務(wù)級(jí),進(jìn)程級(jí)的,IP和端口級(jí)別的心跳檢測,正常情況是主系統(tǒng)工作,備用系統(tǒng)守候,心跳檢測主系統(tǒng)出現(xiàn)故障,備用系統(tǒng)啟動(dòng),當(dāng)再次檢測到主系統(tǒng)工作,則將執(zhí)行權(quán)交回主系統(tǒng)。
  • 缺點(diǎn):開發(fā)比較復(fù)雜,程序健壯性要求高。
untitled2.png

3.4 任務(wù)搶占方案:

  • A,B兩臺(tái)服務(wù)器同時(shí)工作,啟動(dòng)需要存在一前一后,誰先啟動(dòng)誰率先加鎖,其他服務(wù)器只能等待,他們同時(shí)對互斥鎖進(jìn)行監(jiān)控,一旦發(fā)現(xiàn)鎖被釋放,其他服務(wù)那個(gè)先搶到,那個(gè)運(yùn)行,運(yùn)行前加排他鎖。
  • 優(yōu)點(diǎn):可以進(jìn)一步實(shí)現(xiàn)多服務(wù)器橫向擴(kuò)展。
  • 缺點(diǎn):開發(fā)復(fù)雜,程序健壯性要求高,有時(shí)候會(huì)出現(xiàn)不釋放鎖的問題。
untitled4.png

3.5 任務(wù)輪詢或任務(wù)輪詢+搶占排隊(duì)方案

  • 每個(gè)服務(wù)器首次啟動(dòng)時(shí)加入隊(duì)列;
  • 每次任務(wù)運(yùn)行首先判斷自己是否是當(dāng)前可運(yùn)行任務(wù),如果是便運(yùn)行;
  • 如果不是當(dāng)前運(yùn)行的任務(wù),檢查自己是否在隊(duì)列中,如果在,便推出,如果不在隊(duì)列中,便鍵入隊(duì)列。
untitled5.png

通過以上這些方案,可以看出3.5的方案才是優(yōu)先選擇的,擴(kuò)展性好,開發(fā)復(fù)雜度不是很高。那么這種方案需要的需要的技術(shù)原理是什么呢,那就是分布式互斥鎖和隊(duì)列。

3.6 原理

  • 分布式互斥鎖:
    互斥鎖也叫排他鎖,用于并發(fā)時(shí)管理多進(jìn)程和多進(jìn)程同一時(shí)刻只能有一個(gè)進(jìn)程或者線程操作一個(gè)功能。我們將進(jìn)程,線程中的鎖延伸到互聯(lián)網(wǎng)上,實(shí)現(xiàn)對一個(gè)節(jié)點(diǎn)運(yùn)行的進(jìn)程或線程加 鎖,解鎖操作。這樣便能控制節(jié)點(diǎn)上的進(jìn)程或線程的并發(fā)。如下圖:
untitled7.png

有兩臺(tái)服務(wù)器運(yùn)行定時(shí)任務(wù),其中serverA的T2做了加鎖操作,其他程序必須等它釋放鎖了才能運(yùn)行。 那么如果serverA在加鎖的過程中,出現(xiàn)宕機(jī)怎么辦,是否會(huì)一直處于別鎖狀態(tài)。那么我們可以在每個(gè)鎖都設(shè)置一個(gè)超時(shí)閾值,一旦超時(shí)便自動(dòng)解鎖。這樣就不會(huì)因?yàn)殄礄C(jī)導(dǎo)致鎖一直不被釋 放。另外我們還要考慮命名空間的問題,主要是防止出現(xiàn)同名鎖,導(dǎo)致被覆蓋。

  • 隊(duì)列:
    在上面的基礎(chǔ)上,排隊(duì)運(yùn)行任務(wù)。
untitled8.png

從上圖中可以看出,TaskQueue中排隊(duì)情況,運(yùn)行是自上而下的,當(dāng)然這個(gè)順序可以自己設(shè)置規(guī)則,只需要先進(jìn)先出的遠(yuǎn)程即可。另外,Task Queue我們需要做至少兩個(gè)節(jié)點(diǎn),他們遵循主 從結(jié)構(gòu)的原則,主節(jié)點(diǎn)需要實(shí)時(shí)向從節(jié)點(diǎn)同步數(shù)據(jù),保證在主節(jié)點(diǎn)不可用,從節(jié)點(diǎn)可以替代。當(dāng)然,這里可以使用權(quán)重輪詢的方式,加上數(shù)據(jù)異步同步,讓所有節(jié)點(diǎn)都可以做主從的切換, 根據(jù)運(yùn)行狀況來分配,可能會(huì)更好,但是這樣開發(fā)難度也有所提高,但是大大增加了高可用性。

3.7 總結(jié):

  • 最后,我們要根據(jù)我們實(shí)際的情況,需要提供數(shù)據(jù)庫和緩存方面的一些配套服務(wù),這里就不做詳解;

  • 這樣我們整體的一個(gè)分布式定時(shí)任務(wù)平臺(tái)就可以實(shí)現(xiàn)了,就可以保證計(jì)劃任務(wù)的分布式運(yùn)行。

4,當(dāng)前比較流行的分布式定時(shí)任務(wù)框架:
4.1 Quartz:

  • Quartz是Java領(lǐng)域最著名的開源任務(wù)調(diào)度工具。Quartz提供了極為廣泛的特性如持久化任務(wù),集群和分布式任務(wù)
  • 特點(diǎn):
    • 完全由Java寫成,同時(shí)可以很方便的和java的另外一個(gè)框架spring集成;
    • 強(qiáng)大的調(diào)度功能:支持豐富多樣的調(diào)度方法,可以滿足各種常規(guī)及特殊需求;
    • 靈活的應(yīng)用方式:支持任務(wù)和調(diào)度的多種組合方式,支持調(diào)度數(shù)據(jù)的多種存儲(chǔ)方式;
    • 分布式和集群能力,負(fù)載均衡和高可用性;

4.2 Elastic-job:

  • Elastic-Job是ddframe中dd-job的作業(yè)模塊中分離出來的分布式彈性作業(yè)框架。去掉了和dd-job中的監(jiān)控和ddframe接入規(guī)范部分。該項(xiàng)目基于成熟的開源產(chǎn)品Quartz和 Zookeeper及其客戶端Curator進(jìn)行二次開發(fā)

  • 項(xiàng)目開源地址:https://github.com/dangdangdotcom/elastic-job

  • 特點(diǎn):

    • 定時(shí)任務(wù):基于成熟的定時(shí)任務(wù)作業(yè)框架Quartz cron表達(dá)式執(zhí)行定時(shí)任務(wù);
    • 作業(yè)注冊中心:基于Zookeeper和其客戶端Curator實(shí)現(xiàn)全局作業(yè)注冊控制中心。用于注冊,控制和協(xié)調(diào)分布式作業(yè)執(zhí)行。
    • 作業(yè)分片:將要給任務(wù)分片成多個(gè)小任務(wù)項(xiàng)到多服務(wù)器上同時(shí)執(zhí)行;
    • 彈性擴(kuò)容縮容:運(yùn)行中的作業(yè)服務(wù)器崩潰,或新增N臺(tái)作業(yè)服務(wù)器,作業(yè)框架將在下次作業(yè)執(zhí)行前重新分片,不影響當(dāng)前作業(yè)執(zhí)行;
  • 支持多種作業(yè)執(zhí)行模式:支持OneOff,Perpetual和SequenecePerpetual三種作業(yè)模式;

  • 失效轉(zhuǎn)移:運(yùn)行中的作業(yè)服務(wù)器崩潰不會(huì)導(dǎo)致重新分片,只會(huì)在下次作業(yè)啟動(dòng)時(shí)分片。啟用失效轉(zhuǎn)移功能可以在本次作業(yè)執(zhí)行過程中,監(jiān)測其他作業(yè)服務(wù)器空閑,抓取未完成的孤兒分片項(xiàng) 執(zhí)行;

  • 運(yùn)行時(shí)狀態(tài)收集:監(jiān)控作業(yè)運(yùn)行時(shí)狀態(tài),統(tǒng)計(jì)最近一段時(shí)間處理的數(shù)據(jù)成功和失敗數(shù)量,記錄作業(yè)上次運(yùn)行開始時(shí)間,結(jié)束時(shí)間和下次運(yùn)行時(shí)間;

  • 作業(yè)停止,恢復(fù)和禁用:用于操作作業(yè)啟動(dòng)和停止,并可以禁止某作業(yè)運(yùn)行,一般在上線時(shí)常用;

  • 被錯(cuò)過執(zhí)行的作業(yè)重觸發(fā):自動(dòng)記錄錯(cuò)過執(zhí)行的作業(yè),并在上次作業(yè)完成后自動(dòng)觸發(fā)。

  • 多線程快速處理數(shù)據(jù):使用多線程處理抓取到的數(shù)據(jù),提升吞吐量;

  • 冪等性:重復(fù)作業(yè)任務(wù)項(xiàng)判定,不重復(fù)執(zhí)行已運(yùn)行的作業(yè)任務(wù)項(xiàng);

  • 容錯(cuò)處理:作業(yè)服務(wù)器和Zookeeper服務(wù)器通信失敗后則立即停止作業(yè)運(yùn)行,防止作業(yè)注冊中心將失效的分片分項(xiàng)配給其他作業(yè)服務(wù)器,而當(dāng)前作業(yè)服務(wù)器任在執(zhí)行任務(wù),導(dǎo)致重復(fù)執(zhí)行。

  • Spring支持:支持Spring容器,自定義命名空間,支持占位符;

  • 運(yùn)維平臺(tái):提供了運(yùn)維平臺(tái),可以管理作業(yè)和注冊中心。

從以上可以看出Elastic-job是在Quartz的基礎(chǔ)上又做了一次全面的升級(jí),做了配套的周邊基礎(chǔ)服務(wù)工作,完全成為了一個(gè)成熟的分布式定時(shí)任務(wù)框架。后面會(huì)分別介紹Quartz和 Elastic-job的詳細(xì)原理和具體的使用方法。

關(guān)于quartz分布式定時(shí)任務(wù),可以參考
分布式定時(shí)任務(wù)(二)
分布式定時(shí)任務(wù)(三)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容