分布式任務(wù)調(diào)度探索

定時(shí)任務(wù)是大家在開發(fā)中一個(gè)不可避免的業(yè)務(wù),比如在一些電商系統(tǒng)中可能會定時(shí)給用戶發(fā)送生日券,一些對賬系統(tǒng)中可能會定時(shí)去對賬。如果服務(wù)只有一臺機(jī)子,那直接用ScheduledExecutorService就可以了,但是現(xiàn)在服務(wù)一般是集群部署,這個(gè)時(shí)候,ScheduledExecutorService很多時(shí)候就沒法解決問題,因?yàn)槲覀冃枰WC只執(zhí)行一次,同時(shí),我們還需要保證高可用,任務(wù)監(jiān)控等等。

因此,鑒于這些場景,出現(xiàn)了較多的分布式調(diào)度框架,本文將對也就主流的開源調(diào)度器進(jìn)行分析對比,然后總結(jié)出分布式調(diào)度器的系統(tǒng)設(shè)計(jì)關(guān)鍵點(diǎn)。

需求分析

設(shè)計(jì)一個(gè)分布式調(diào)度器,首先需要明確面臨哪些場景,以及需要解決哪些問題。按照需求特點(diǎn),我們將其分為功能性需求和非功能性需求。

功能性需求

調(diào)度器功能性需求.png

功能性需求,主要包括:

  • 任務(wù)觸發(fā)調(diào)度功能:支持單機(jī)調(diào)度、支持集群調(diào)度、支持精確觸發(fā)實(shí)踐調(diào)度、支持實(shí)踐表達(dá)式實(shí)踐調(diào)度、支持API調(diào)度
  • 任務(wù)編排功能:支持JOB依賴關(guān)系設(shè)置、支持JOB級聯(lián)關(guān)系觸發(fā)
  • 支持大任務(wù)拆分和并行處理功能:支持將大任務(wù)拆分成多級子任務(wù)、支持應(yīng)用集群并行執(zhí)行子任務(wù)。
  • 任務(wù)可視化管理

非功能性需求

調(diào)度器非功能性需求.png

對于調(diào)度器,一般需要滿足:高可用、高性能、支持水平處理等能力,我們將這些能力成為非功能性需求。

開源框架分析

Java Timer

在ScheduledExecutorService未出現(xiàn)前,在業(yè)務(wù)開發(fā)中如果遇到執(zhí)行一些簡單定時(shí)任務(wù)的需求,為了避免做一些看起來復(fù)雜的控制邏輯,一般考慮使用 Timer 來實(shí)現(xiàn)定時(shí)任務(wù)的執(zhí)行,下面給出一個(gè)最簡單用法的例子:

Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        // scheduledExecutionTime() 返回此任務(wù)最近開始執(zhí)行的時(shí)間
        Date date = new Date(this.scheduledExecutionTime());
        System.out.println("timeTask run " + date);
    }
};

// 從現(xiàn)在開始每間隔 1000 ms 計(jì)劃執(zhí)行一個(gè)任務(wù)
timer.schedule(timerTask, 0, 1000);

Timer現(xiàn)在已經(jīng)不建議使用了,推薦使用ScheduledExecutorService,為什么不建議使用Timer了?原因如下:

  • Timer底層是使用單線程來處理多個(gè)Timer任務(wù),這意味著所有任務(wù)實(shí)際上都是串行執(zhí)行,前一個(gè)任務(wù)的延遲會影響到之后的任務(wù)的執(zhí)行;
  • 由于單線程的緣故,一旦某個(gè)定時(shí)任務(wù)在運(yùn)行時(shí),產(chǎn)生未處理的異常,那么不僅當(dāng)前這個(gè)線程會停止,所有的定時(shí)任務(wù)都會停止;
  • Timer任務(wù)執(zhí)行是依賴于系統(tǒng)絕對時(shí)間,系統(tǒng)時(shí)間變化會導(dǎo)致執(zhí)行計(jì)劃的變更。

由于上述缺陷,盡量不要使用Timer, idea中也會明確提示,使用ScheduledThreadPoolExecutor替代Timer 。

Java ScheduledExecutorService

ScheduledExecutorService對于Timer的缺陷進(jìn)行了修補(bǔ),首先ScheduledExecutorService內(nèi)部實(shí)現(xiàn)是ScheduledThreadPool線程池,可以支持多個(gè)任務(wù)并發(fā)執(zhí)行。

對于某一個(gè)線程執(zhí)行的任務(wù)出現(xiàn)異常,也會處理,不會影響其他線程任務(wù)的執(zhí)行,另外ScheduledExecutorService是基于時(shí)間間隔的延遲,執(zhí)行不會由于系統(tǒng)時(shí)間的改變發(fā)生變化。

當(dāng)然,ScheduledExecutorService也有自己的局限性:只能根據(jù)任務(wù)的延遲來進(jìn)行調(diào)度,無法滿足基于絕對時(shí)間和日歷調(diào)度的需求。

Spring Task

spring task 是spring自主開發(fā)的輕量級定時(shí)任務(wù)框架,不需要依賴其他額外的包,配置較為簡單,此處使用注解配置:


image.png

Spring Task 本身不支持持久化,也沒有推出官方的分布式集群模式,只能靠開發(fā)者在業(yè)務(wù)應(yīng)用中自己手動擴(kuò)展實(shí)現(xiàn),無法滿足可視化,易配置的需求。

Quartz

Quartz框架是Java領(lǐng)域最著名的開源任務(wù)調(diào)度工具,也是目前事實(shí)上的定時(shí)任務(wù)標(biāo)準(zhǔn),幾乎全部的開源定時(shí)任務(wù)框架都是基于Quartz核心調(diào)度構(gòu)建而成。

image.png

關(guān)鍵概念

  • Scheduler:任務(wù)調(diào)度器,是執(zhí)行任務(wù)調(diào)度的控制器。本質(zhì)上是一個(gè)計(jì)劃調(diào)度容器,注冊了全部Trigger和對應(yīng)的JobDetail, 使用線程池作為任務(wù)運(yùn)行的基礎(chǔ)組件,提高任務(wù)執(zhí)行效率。
  • Trigger:觸發(fā)器,用于定義任務(wù)調(diào)度的時(shí)間規(guī)則,告訴任務(wù)調(diào)度器什么時(shí)候觸發(fā)任務(wù),其中CronTrigger是基于cron表達(dá)式構(gòu)建的功能強(qiáng)大的觸發(fā)器。
  • Calendar:日歷特定時(shí)間點(diǎn)的集合。一個(gè)trigger可以包含多個(gè)Calendar,可用于排除或包含某些時(shí)間點(diǎn)。
  • JobDetail:是一個(gè)可執(zhí)行的工作,用來描述Job實(shí)現(xiàn)類及其它相關(guān)的靜態(tài)信息,如Job的名稱、監(jiān)聽器等相關(guān)信息。
  • Job:任務(wù)執(zhí)行接口,只有一個(gè)execute方法,用于執(zhí)行真正的業(yè)務(wù)邏輯。
  • JobStore:任務(wù)存儲方式,主要有RAMJobStore和JDBCJobStore,RAMJobStore是存儲在JVM的內(nèi)存中,有丟失和數(shù)量受限的風(fēng)險(xiǎn),JDBCJobStore是將任務(wù)信息持久化到數(shù)據(jù)庫中,支持集群。

實(shí)現(xiàn)細(xì)節(jié)

1.Quartz如何保證任務(wù)只在一個(gè)節(jié)點(diǎn)運(yùn)行?
答案是使用了數(shù)據(jù)庫鎖。在quartz的集群解決方案里有張表scheduler_locks,quartz采用了悲觀鎖的方式對triggers表進(jìn)行行加鎖,以保證任務(wù)同步的正確性。一旦某一個(gè)節(jié)點(diǎn)上面的線程獲取了該鎖,那么這個(gè)Job就會在這臺機(jī)器上被執(zhí)行,同時(shí)這個(gè)鎖就會被這臺機(jī)器占用。同時(shí)另外一臺機(jī)器也會想要觸發(fā)這個(gè)任務(wù),但是鎖已經(jīng)被占用了,就只能等待,直到這個(gè)鎖被釋放。之后會看trigger狀態(tài),如果已經(jīng)被執(zhí)行了,則不會執(zhí)行了。

簡單地說,quartz的分布式調(diào)度策略是以數(shù)據(jù)庫為邊界資源的一種異步策略。各個(gè)調(diào)度器都遵守一個(gè)基于數(shù)據(jù)庫鎖的操作規(guī)則從而保證了操作的唯一性。同時(shí)多個(gè)節(jié)點(diǎn)的異步運(yùn)行保證了服務(wù)的可靠。但這種策略有自己的局限性:集群特性對于高CPU使用率的任務(wù)效果很好,但是對于大量的短任務(wù),各個(gè)節(jié)點(diǎn)都會搶占數(shù)據(jù)庫鎖,這樣就出現(xiàn)大量的線程等待資源。這種情況隨著節(jié)點(diǎn)的增加會越來越嚴(yán)重。

2.在集群的哪個(gè)節(jié)點(diǎn)上運(yùn)行,Quartz是如何進(jìn)行選取的?
隨緣的。集群中各個(gè)節(jié)點(diǎn)做到時(shí)間同步很重要。如果待觸發(fā)的任務(wù)少且運(yùn)行快,那么很可能一直在時(shí)間最早的那一個(gè)節(jié)點(diǎn)上執(zhí)行。

3.任務(wù)太多,而線程池中配置的線程太少時(shí)怎么辦?
沒事,反正選取Trigger的時(shí)候也會考慮空閑線程的數(shù)量,空閑線程少的話實(shí)例就少選取幾個(gè)Trigger來執(zhí)行。

Quartz不足

Quartz通過故障轉(zhuǎn)移和負(fù)載均衡實(shí)現(xiàn)了任務(wù)的高可用,通過數(shù)據(jù)庫的鎖機(jī)制來確保任務(wù)執(zhí)行的唯一性,但是集群特性僅僅只是用來HA,節(jié)點(diǎn)數(shù)量的增加并不會提升單個(gè)任務(wù)的執(zhí)行效率,不能實(shí)現(xiàn)水平擴(kuò)展。

總結(jié)起來,其缺陷和不足在于:
1)需要把任務(wù)信息持久化到業(yè)務(wù)數(shù)據(jù)表,和業(yè)務(wù)有耦合;
2)調(diào)度邏輯和執(zhí)行并存于同一個(gè)項(xiàng)目中,在機(jī)器性能固定的情況下,業(yè)務(wù)和調(diào)度之間不可避免的會相互影響;
3)quartz集群模式下,是通過數(shù)據(jù)庫獨(dú)占鎖來唯一獲取任務(wù),任務(wù)執(zhí)行并沒有實(shí)現(xiàn)完善的負(fù)載均衡;

輕量級神器 XXL-JOB

XXL-JOB是一個(gè)輕量級分布式任務(wù)調(diào)度平臺,主打特點(diǎn)是平臺化,易部署,開發(fā)迅速、學(xué)習(xí)簡單、輕量級、易擴(kuò)展,代碼仍在持續(xù)更新中。

“調(diào)度中心”是任務(wù)調(diào)度控制臺,平臺自身并不承擔(dān)業(yè)務(wù)邏輯,只是負(fù)責(zé)任務(wù)的統(tǒng)一管理和調(diào)度執(zhí)行,并且提供任務(wù)管理平臺, “執(zhí)行器” 負(fù)責(zé)接收“調(diào)度中心”的調(diào)度并執(zhí)行,可直接部署執(zhí)行器,也可以將執(zhí)行器集成到現(xiàn)有業(yè)務(wù)項(xiàng)目中。 通過將任務(wù)的調(diào)度控制和任務(wù)的執(zhí)行解耦,業(yè)務(wù)使用只需要關(guān)注業(yè)務(wù)邏輯的開發(fā)。

主要提供了任務(wù)的動態(tài)配置管理、任務(wù)監(jiān)控和統(tǒng)計(jì)報(bào)表以及調(diào)度日志幾大功能模塊,支持多種運(yùn)行模式和路由策略,可基于對應(yīng)執(zhí)行器機(jī)器集群數(shù)量進(jìn)行簡單分片數(shù)據(jù)處理。

功能特性

主要功能特性如下:

  • 簡單靈活
    提供Web頁面對任務(wù)進(jìn)行管理,管理系統(tǒng)支持用戶管理、權(quán)限控制; 支持容器部署;支持通過通用HTTP提供跨平臺任務(wù)調(diào)度;

  • 豐富的任務(wù)管理功能
    支持頁面對任務(wù)CRUD操作; 支持在頁面編寫腳本任務(wù)、命令行任務(wù)、Java代碼任務(wù)并執(zhí)行; 支持任務(wù)級聯(lián)編排,父任務(wù)執(zhí)行結(jié)束后觸發(fā)子任務(wù)執(zhí)行; 支持設(shè)置任務(wù)優(yōu)先級; 支持設(shè)置指定任務(wù)執(zhí)行節(jié)點(diǎn)路由策略,包括輪詢、隨機(jī)、廣播、故障轉(zhuǎn)移、忙碌轉(zhuǎn)移等; 支持Cron方式、任務(wù)依賴、調(diào)度中心API接口方式觸發(fā)任務(wù)執(zhí)行

  • 高性能
    調(diào)度中心基于線程池多線程觸發(fā)調(diào)度任務(wù),快任務(wù)、慢任務(wù)基于線程池隔離調(diào)度,提供系統(tǒng)性能和穩(wěn)定性; 任務(wù)調(diào)度流程全異步化設(shè)計(jì)實(shí)現(xiàn),如異步調(diào)度、異步運(yùn)行、異步回調(diào)等,有效對密集調(diào)度進(jìn)行流量削峰;

  • 高可用
    任務(wù)調(diào)度中心、任務(wù)執(zhí)行節(jié)點(diǎn)均 集群部署,支持動態(tài)擴(kuò)展、故障轉(zhuǎn)移 支持任務(wù)配置路由故障轉(zhuǎn)移策略,執(zhí)行器節(jié)點(diǎn)不可用是自動轉(zhuǎn)移到其他節(jié)點(diǎn)執(zhí)行 支持任務(wù)超時(shí)控制、失敗重試配置 支持任務(wù)處理阻塞策略:調(diào)度當(dāng)任務(wù)執(zhí)行節(jié)點(diǎn)忙碌時(shí)來不及執(zhí)行任務(wù)的處理策略,包括:串行、拋棄、覆蓋策略;

  • 易于監(jiān)控運(yùn)維
    支持設(shè)置任務(wù)失敗郵件告警,預(yù)留接口支持短信、釘釘告警; 支持實(shí)時(shí)查看任務(wù)執(zhí)行運(yùn)行數(shù)據(jù)統(tǒng)計(jì)圖表、任務(wù)進(jìn)度監(jiān)控?cái)?shù)據(jù)、任務(wù)完整執(zhí)行日志;

系統(tǒng)設(shè)計(jì)

設(shè)計(jì)思路

將調(diào)度行為抽象形成“調(diào)度中心”公共平臺,而平臺自身并不承擔(dān)業(yè)務(wù)邏輯,“調(diào)度中心”負(fù)責(zé)發(fā)起調(diào)度請求;將任務(wù)抽象成分散的JobHandler,交由“執(zhí)行器”統(tǒng)一管理,“執(zhí)行器”負(fù)責(zé)接收調(diào)度請求并執(zhí)行對應(yīng)的JobHandler中業(yè)務(wù)邏輯;因此,“調(diào)度”和“任務(wù)”兩部分可以相互解耦,提高系統(tǒng)整體穩(wěn)定性和擴(kuò)展性;

image.png

系統(tǒng)組成

  • 調(diào)度模塊(調(diào)度中心):負(fù)責(zé)管理調(diào)度信息,按照調(diào)度配置發(fā)出調(diào)度請求,自身不承擔(dān)業(yè)務(wù)代碼。調(diào)度系統(tǒng)與任務(wù)解耦,提高了系統(tǒng)可用性和穩(wěn)定性,同時(shí)調(diào)度系統(tǒng)性能不再受限于任務(wù)模塊;支持可視化、簡單且動態(tài)的管理調(diào)度信息,包括任務(wù)新建,更新,刪除,任務(wù)報(bào)警等,所有上述操作都會實(shí)時(shí)生效,同時(shí)支持監(jiān)控調(diào)度結(jié)果以及執(zhí)行日志,支持執(zhí)行器Failover

  • 執(zhí)行模塊(執(zhí)行器):負(fù)責(zé)接收調(diào)度請求并執(zhí)行任務(wù)邏輯。任務(wù)模塊專注于任務(wù)的執(zhí)行等操作,開發(fā)和維護(hù)更加簡單和高效;接收“調(diào)度中心”的執(zhí)行請求、終止請求和日志請求等

系統(tǒng)HA設(shè)計(jì)

1、調(diào)度中心高可用
調(diào)度中心支持多節(jié)點(diǎn)部署,基于數(shù)據(jù)庫行鎖保證同時(shí)只有一個(gè)調(diào)度中心節(jié)點(diǎn)觸發(fā)任務(wù)調(diào)度,參考com.xxl.job.admin.core.thread.JobScheduleHelper#start

2、任務(wù)調(diào)度高可用

  • 路由策略
    調(diào)度中心基于路由策略路由選擇一個(gè)執(zhí)行器節(jié)點(diǎn)執(zhí)行任務(wù),XXL-JOB提供了如下路由策略保證任務(wù)調(diào)度高可用;

  • 忙碌轉(zhuǎn)移策略
    下發(fā)任務(wù)前向執(zhí)行器節(jié)點(diǎn)發(fā)起rpc心跳請求查詢是否忙碌,如果執(zhí)行器節(jié)點(diǎn)返回忙碌則轉(zhuǎn)移到其他執(zhí)行器節(jié)點(diǎn)執(zhí)行(參考 com.xxl.job.admin.core.route.strategy.ExecutorRouteBusyover);

  • 阻塞處理策略
    當(dāng)執(zhí)行器節(jié)點(diǎn)存在多個(gè)相同任務(wù)id的任務(wù)未執(zhí)行完成,則需要基于阻塞策略對任務(wù)進(jìn)行取舍:
    串行策略:默認(rèn)策略,任務(wù)進(jìn)行排隊(duì)、丟棄舊任務(wù)策略、丟棄新任務(wù)策略(參考:com.xxl.job.core.biz.impl.ExecutorBizImpl#run)

  • 故障轉(zhuǎn)移策略
    下發(fā)任務(wù)前向執(zhí)行器節(jié)點(diǎn)發(fā)起rpc心跳請求查詢是否在線,如果執(zhí)行器節(jié)點(diǎn)沒返回或者返回不可用則轉(zhuǎn)移到其他執(zhí)行器節(jié)點(diǎn)執(zhí)行 (參考com.xxl.job.admin.core.route.strategy.ExecutorRouteFailover)

工作原理

XXL-JOB的工作原理如下如所示:


工作原理

Elastic-Job

Elastic-Job是一個(gè)分布式調(diào)度解決方案,由兩個(gè)相互獨(dú)立的子項(xiàng)目Elastic-Job-Lite和Elastic-Job-Cloud組成。Elastic-Job-Lite定位為輕量級無中心化解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù)。Elastic-Job-Cloud使用Mesos + Docker的解決方案,額外提供資源治理、應(yīng)用分發(fā)以及進(jìn)程隔離等服務(wù)。

原理解析

框架

Saturn

Saturn是唯品會開源的一個(gè)分布式任務(wù)調(diào)度平臺,在Elastic Job的基礎(chǔ)上進(jìn)行了改造。

SIA-TASK

是宜信開源的分布式任務(wù)調(diào)度平臺。

分布式調(diào)度關(guān)鍵點(diǎn)

分布式調(diào)度核心要素.png

分布式調(diào)度一般分為三部分,分別是:任務(wù)調(diào)度器、任務(wù)執(zhí)行器、任務(wù)。詳細(xì)如下:

  • 任務(wù)調(diào)度器不關(guān)心業(yè)務(wù)邏輯,只關(guān)心任務(wù)的觸發(fā)策略、失敗策略、路由策略、阻塞處理策略
  • 任務(wù)執(zhí)行器只需要監(jiān)聽任務(wù)觸發(fā)接口,按要求執(zhí)行任務(wù),成功或失敗時(shí)異步通知任務(wù)調(diào)度器
  • 任務(wù)的基本屬性需要包含任務(wù)ID、觸發(fā)策略、失敗策略、路由策略、阻塞處理策略、創(chuàng)建時(shí)間、創(chuàng)建用戶、任務(wù)參數(shù)、任務(wù)當(dāng)前搶占調(diào)度器、任務(wù)狀態(tài)(調(diào)度中、執(zhí)行中、執(zhí)行完成)

高可用

為了避免單點(diǎn)故障,任務(wù)調(diào)度系統(tǒng)通常需要通過集群實(shí)現(xiàn)系統(tǒng)高可用,同時(shí)通過擴(kuò)展提高系統(tǒng)的任務(wù)負(fù)載量上限。

鑒于任務(wù)調(diào)度系統(tǒng)的特殊性,“調(diào)度”和“執(zhí)行”兩個(gè)模塊需要均支持集群部署,由于職責(zé)不同,因此各自集群側(cè)重點(diǎn)也有有所不同。

“調(diào)度器”集群,目標(biāo)為避免調(diào)度模塊單點(diǎn)故障。同時(shí),集群節(jié)點(diǎn)需要通過鎖或命名服務(wù)保證單個(gè)任務(wù)的單次觸發(fā),只在其中一個(gè)節(jié)點(diǎn)上生效,以防止任務(wù)的重復(fù)觸發(fā)。

調(diào)度器為何采用集群而不是主從?
主從模式只能提供HA的特性,不能提高提高系統(tǒng)的任務(wù)負(fù)載量上限。
主從需要實(shí)現(xiàn)選舉算法,保證CP或者AP
集群只需要將狀態(tài)都遷移到全局的存儲器中(例如DB),任務(wù)可以采用搶占機(jī)制(全局鎖),搶占后在任務(wù)后標(biāo)識任務(wù)狀態(tài)即可。

“執(zhí)行器”集群:目標(biāo)為避免任務(wù)模塊單點(diǎn)故障。進(jìn)一步可以通過自定義路由策略實(shí)現(xiàn)Failover等高級功能,從而在執(zhí)行器某臺機(jī)器節(jié)點(diǎn)故障時(shí)自動轉(zhuǎn)移不會影響到任務(wù)的正常觸發(fā)執(zhí)行。

失敗處理

這里的失敗策略指的是業(yè)務(wù)發(fā)生失敗的處理策略,而不是因?yàn)楣?jié)點(diǎn)故障導(dǎo)致任務(wù)沒有執(zhí)行完成導(dǎo)致的失敗

任務(wù)失敗是一種很常見的情況,當(dāng)任務(wù)失敗時(shí)有兩點(diǎn)非常重要,一個(gè)是快速發(fā)現(xiàn)問題,另一個(gè)是及時(shí)解決問題。

任務(wù)業(yè)務(wù)邏輯千差萬別,如索引同步、pv統(tǒng)計(jì)、訂單超時(shí)處理等等。任務(wù)失敗可能會導(dǎo)致非常嚴(yán)重的后果,比如索引同步任務(wù)失敗可能導(dǎo)致搜索不匹配,pv統(tǒng)計(jì)失敗可能導(dǎo)致打點(diǎn)報(bào)表的生成,訂單超時(shí)處理任務(wù)的失敗可能導(dǎo)致商品庫存的大量無效占用等等。

針對上述情況,通常有幾種處理方案:

  • 失敗告警(快速發(fā)現(xiàn)問題):任務(wù)失敗時(shí),主動向任務(wù)負(fù)責(zé)人發(fā)送告警通知,如郵件、短信等方式。這是一種常用的處理方案,原理和實(shí)現(xiàn)都比較簡單。負(fù)責(zé)人接收的告警郵件時(shí),通過人工的方式進(jìn)行故障處理,如手動觸發(fā)一次任務(wù)執(zhí)行。
  • 失敗重試(快速解決問題):任務(wù)失敗時(shí),調(diào)度中心主動嘗試觸發(fā)一次重試任務(wù)。優(yōu)點(diǎn)在于不需要人為接入,重試在一定程度上可以大大提高任務(wù)的成功率。但是,失敗重試需要注意限制重試次數(shù),否則將會導(dǎo)致”失敗-重試-失敗”的死循環(huán),造成資源浪費(fèi)。

路由策略

由于任務(wù)執(zhí)行器存在多個(gè)實(shí)例,調(diào)度器如何選擇任務(wù)執(zhí)行器同樣是個(gè)問題。為每個(gè)任務(wù)配置不同的路由策略(為配置則使用默認(rèn)路由策略)常見的策略如下:

  • 隨機(jī)策略
  • 輪訓(xùn)策略
  • 任務(wù)IDHash策略
  • 背壓策略(需要調(diào)度器與執(zhí)行器通訊報(bào)告執(zhí)行器未執(zhí)行任務(wù)數(shù)量)
  • 阻塞處理策略

阻塞策略

在調(diào)度比較密集,而執(zhí)行器來不及處理的情況下,任務(wù)阻塞策略可以指導(dǎo)執(zhí)行器快速處理阻塞的觸發(fā)請求。常見的阻塞策略有以下幾種:

  • 單機(jī)串行(默認(rèn)):調(diào)度請求進(jìn)入執(zhí)行器后,調(diào)度請求進(jìn)入FIFO隊(duì)列并以串行方式運(yùn)行;
  • 丟棄后續(xù)調(diào)度:調(diào)度請求進(jìn)入執(zhí)行器后,發(fā)現(xiàn)執(zhí)行器存在運(yùn)行的調(diào)度任務(wù),本次請求將會被丟棄并標(biāo)記為失??;
  • 覆蓋之前調(diào)度:調(diào)度請求進(jìn)入執(zhí)行器后,發(fā)現(xiàn)執(zhí)行器存在運(yùn)行的調(diào)度任務(wù),將會終止運(yùn)行中的調(diào)度任務(wù)并清空隊(duì)列,然后運(yùn)行本地調(diào)度任務(wù);

分布式鎖實(shí)現(xiàn)

對于分布式定時(shí)任務(wù)系統(tǒng)來說,最重要的是分布式鎖,實(shí)現(xiàn)方式有三種:

  1. 基于數(shù)據(jù)庫的實(shí)現(xiàn)方式:唯一索引原理,比如一個(gè)定時(shí)任務(wù)一天執(zhí)行一次,我們就以日期作為唯一索引,誰第一個(gè)把當(dāng)天日期插入成功,誰就有資格執(zhí)行;
  2. 基于Redis的實(shí)現(xiàn)方式
  3. 基于zk的實(shí)現(xiàn)方式
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容