前言
上一篇文章談了單機(jī)的定時(shí)任務(wù)解決方案获洲,只能在單個(gè)JVM進(jìn)程中使用元潘;而我們的現(xiàn)在基本上是分布式場(chǎng)景,需要一套在分布式環(huán)境下高性能柴墩、高可用忙厌、可擴(kuò)展的分布式任務(wù)調(diào)度框架;是否將之前的單機(jī)解決方案部署到分布式就可以江咳?面臨的分布式場(chǎng)景如何實(shí)現(xiàn)分布式的任務(wù)調(diào)度逢净,如何解決單點(diǎn)故障問題實(shí)現(xiàn)高可用?接下來我們首先分析分布式任務(wù)調(diào)度框架相對(duì)單機(jī)的優(yōu)勢(shì)以及結(jié)合幾種任務(wù)調(diào)度框架分析是如何逐步實(shí)現(xiàn)分布式的高可用歼指、效率的爹土,最后綜合比較下業(yè)界比較流行的框架,在項(xiàng)目開發(fā)中方便選擇踩身。
Why 分布式任務(wù)調(diào)度框架
背景
1胀茵、單機(jī)單點(diǎn)故障
舉個(gè)例子,村里只有一口井惰赋,有口井突然被污染了宰掉,村里就都沒有井水喝了;分布式就是平時(shí)挖了多口井赁濒,一口井出問題照樣有水喝。
之前我們說到單機(jī)的定時(shí)任務(wù)可能機(jī)器存在異常孟害,如果沒有分布式任務(wù)調(diào)度拒炎,那這個(gè)機(jī)器上所有定時(shí)任務(wù)只能等到這個(gè)機(jī)器恢復(fù)后才可以執(zhí)行,這顯然可用性就很低挨务。
分布式任務(wù)調(diào)度就是在集群中多臺(tái)調(diào)度击你、多臺(tái)執(zhí)行玉组,一臺(tái)調(diào)度機(jī)器或者執(zhí)行機(jī)器出問題,能夠立刻故障轉(zhuǎn)移丁侄,不影響后續(xù)任務(wù)的執(zhí)行惯雳,提高整體的可用性。
2鸿摇、性能瓶頸
都知道一臺(tái)機(jī)器的CPU石景、內(nèi)存資源是有限的,像我們單機(jī)任務(wù)都直接寫在業(yè)務(wù)機(jī)器上拙吉,單機(jī)任務(wù)瓶頸立現(xiàn)潮孽;當(dāng)定時(shí)任務(wù)多,每秒執(zhí)行上W個(gè)定時(shí)任務(wù)筷黔,單機(jī)是難以支撐的往史,而且定時(shí)任務(wù)會(huì)影響到業(yè)務(wù)系統(tǒng)的資源,整個(gè)系統(tǒng)就會(huì)非常不可靠佛舱。單機(jī)靠多線程椎例,單機(jī)瓶頸達(dá)到后就要依靠分布式集群來水平擴(kuò)展,解決資源瓶頸問題请祖。
3粟矿、協(xié)同效率
每個(gè)定時(shí)任務(wù)調(diào)度的使用業(yè)務(wù)方都需要自己在業(yè)務(wù)系統(tǒng)構(gòu)造一套分布式定時(shí)任務(wù)調(diào)度框架嗎?這顯然是低效损拢?專業(yè)分工是必然的發(fā)展趨勢(shì)陌粹,這就需要分布式的任務(wù)調(diào)度框架的出現(xiàn),其他業(yè)務(wù)作為接入方福压,使用即可掏秩,不需要再考慮分布式調(diào)度的調(diào)度策略的高可用、異常故障恢復(fù)荆姆、控制臺(tái)配置等等問題蒙幻,只需要專注業(yè)務(wù)邏輯即可。
演進(jìn)過程
什么是分布式任務(wù)調(diào)度
分布式任務(wù)調(diào)度胆筒,三個(gè)關(guān)鍵詞:分布式邮破、任務(wù)調(diào)度、配置中心仆救。
分布式:平臺(tái)是分布式部署的抒和,各個(gè)節(jié)點(diǎn)之間可以無(wú)狀態(tài)和無(wú)限的水平擴(kuò)展(保證可擴(kuò)展);
任務(wù)調(diào)度:涉及到任務(wù)狀態(tài)管理彤蔽、任務(wù)調(diào)度請(qǐng)求的發(fā)送與接收摧莽、具體任務(wù)的分配、任務(wù)的具體執(zhí)行顿痪;(集群中哪些機(jī)器什么時(shí)候執(zhí)行什么任務(wù)镊辕,所以又需要一個(gè)可以感知整個(gè)集群運(yùn)行狀態(tài)的配置中心)
配置中心:可以感知整個(gè)集群的狀態(tài)油够、任務(wù)信息的注冊(cè)
常見的分布式任務(wù)調(diào)度框架一般有以下5個(gè)部分
1、控制臺(tái):負(fù)責(zé)調(diào)度任務(wù)的配置征懈、任務(wù)狀態(tài)石咬、信息展示
2、接入:將控制臺(tái)的任務(wù)轉(zhuǎn)化下發(fā)給調(diào)度器卖哎,并且向注冊(cè)中心注冊(cè)任務(wù)
3鬼悠、調(diào)度器:接收接入下發(fā)的調(diào)度任務(wù),進(jìn)行任務(wù)拆分下發(fā)棉饶,在注冊(cè)中心找執(zhí)行器厦章,然后把任務(wù)下發(fā)到執(zhí)行器執(zhí)行,同時(shí)也注冊(cè)到注冊(cè)中心
4照藻、執(zhí)行器:接收調(diào)度任務(wù)袜啃,并且上報(bào)狀態(tài)給注冊(cè)中心
5、注冊(cè)中心:機(jī)器幸缕、任務(wù)狀態(tài)的同步群发、協(xié)調(diào)
現(xiàn)在林林總總的框架,大部分都是在Quartz的基礎(chǔ)上進(jìn)行改進(jìn)发乔,我們先來看看經(jīng)典的Quartz怎么做的熟妓?
Quartz
Quartz是OpenSymphony開源組織在任務(wù)調(diào)度領(lǐng)域的一個(gè)開源項(xiàng)目,完全基于java實(shí)現(xiàn)栏尚。作為一個(gè)優(yōu)秀的開源框架起愈,Quartz具有以下特點(diǎn):強(qiáng)大的調(diào)度功能、靈活的應(yīng)用方式译仗、分布式和集群能力抬虽,另外作為spring默認(rèn)的調(diào)度框架,很容易實(shí)現(xiàn)與Spring集成纵菌,實(shí)現(xiàn)靈活可配置的調(diào)度功能阐污。
Quartz框架的核心對(duì)象
Scheduler – 核心調(diào)度器,就是任務(wù)調(diào)度咱圆、分配的控制器
Job – 任務(wù)笛辟,代表具體要執(zhí)行的任務(wù),是個(gè)接口序苏,里面有默認(rèn)方法手幢,開發(fā)者需要實(shí)現(xiàn)該接口,并且業(yè)務(wù)邏輯寫在默認(rèn)的execute方法中
JobDetail – 任務(wù)描述杠览,描述job的靜態(tài)消息弯菊,是調(diào)度器需要的數(shù)據(jù),跟Job區(qū)分開來踱阿,主要是為了一個(gè)Job可以在多臺(tái)機(jī)器并行管钳,每個(gè)調(diào)度器new一個(gè)Job的實(shí)現(xiàn)類
Trigger -- 觸發(fā)器,用于定義任務(wù)調(diào)度的時(shí)間規(guī)則
#對(duì)象之間的關(guān)系
這是單機(jī)Quartz最小的執(zhí)行單元的關(guān)系
集群部署
上圖3個(gè)節(jié)點(diǎn)在數(shù)據(jù)庫(kù)中都有同一份Job定義软舌,如果某一個(gè)節(jié)點(diǎn)失效才漆,那么Job會(huì)在其他節(jié)點(diǎn)上執(zhí)行。因?yàn)槊總€(gè)節(jié)點(diǎn)上的代碼都是一樣的佛点,那么如何保證只有一臺(tái)機(jī)器上觸發(fā)呢醇滥?答案是使用了數(shù)據(jù)庫(kù)鎖。在quartz集群解決方案了有張scheduler_locks超营,采用了悲觀鎖的方式對(duì)triggers表進(jìn)行了行加鎖鸳玩,以保證任務(wù)同步的正確性。
簡(jiǎn)單來說演闭,quartz的分布式調(diào)度策略是以數(shù)據(jù)庫(kù)為邊界的一種異步策略不跟。各個(gè)調(diào)度器都遵守一個(gè)基于數(shù)據(jù)庫(kù)鎖的操作規(guī)則從而保證了操作的唯一性,同時(shí)多個(gè)節(jié)點(diǎn)的異步運(yùn)行保證了服務(wù)的可靠米碰。(實(shí)際上是用數(shù)據(jù)庫(kù)鎖作為分布式鎖解決同步問題實(shí)現(xiàn)異步運(yùn)行窝革,跟redis、zk做分布式鎖時(shí)是一樣的)
但這種策略有自己的局限性:集群特性對(duì)于高CPU使用率的任務(wù)效果特別好吕座,但是對(duì)于大量的短任務(wù)虐译,各個(gè)節(jié)點(diǎn)都會(huì)搶占數(shù)據(jù)庫(kù)鎖,這樣就出現(xiàn)大量的線程等待資源吴趴。
因此Quartz的分布式只解決了任務(wù)高可用(減少單點(diǎn)故障)的問題漆诽,處理能力瓶頸會(huì)在數(shù)據(jù)庫(kù),而且沒有執(zhí)行層面的任務(wù)分片锣枝,無(wú)法最大化效率厢拭,只能依靠shedulex調(diào)度層面做分片,但是調(diào)度層做并行分片難以結(jié)合實(shí)際的運(yùn)行資源情況做最優(yōu)的分片。
quartz通過數(shù)據(jù)庫(kù)鎖的方式來保證分布式環(huán)境下定時(shí)任務(wù)調(diào)度的同步烤宙,解決了單點(diǎn)故障钞澳,只引入了數(shù)據(jù)庫(kù),整體的結(jié)構(gòu)簡(jiǎn)單回季;但是在效率上,由于數(shù)據(jù)庫(kù)鎖帶來的競(jìng)爭(zhēng)沖突正林,會(huì)使得在短任務(wù)較多時(shí)的低效泡一,并且沒有在執(zhí)行時(shí)對(duì)任務(wù)分片,無(wú)法充分利用集群性能觅廓,也就是說沒法真正的做到水平擴(kuò)展鼻忠,瓶頸被數(shù)據(jù)庫(kù)鎖限制住了。
Elastic-job
要解決這個(gè)分布式的水平擴(kuò)展杈绸、效率問題帖蔓,我們知道需要引入注冊(cè)中心進(jìn)行協(xié)調(diào)矮瘟,這里當(dāng)當(dāng)退出的Elastic-job就是Quartz的基礎(chǔ)上,引入ZK做注冊(cè)中心塑娇。并且在2.0版本后出現(xiàn)了兩個(gè)相互獨(dú)立的產(chǎn)品線:Elastic-job-lite和Elastic-job-cloud澈侠。Elastic-job-lite定位為輕量級(jí)無(wú)中心化的解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù)埋酬,外部依賴僅依賴于zookeeper哨啃。
這款輕量級(jí)的架構(gòu)做了很多的改進(jìn),這里只談到兩點(diǎn)写妥,
1拳球、無(wú)中心調(diào)度節(jié)點(diǎn)
Elastic-job-lite并無(wú)作業(yè)調(diào)度中心節(jié)點(diǎn),不像我們談到單機(jī)定時(shí)任務(wù)調(diào)度有統(tǒng)一的排序隊(duì)列珍特,它是基于部署作業(yè)框架的程序在到達(dá)相應(yīng)時(shí)間點(diǎn)時(shí)各自觸發(fā)調(diào)度祝峻。注冊(cè)中心僅用于作業(yè)注冊(cè)和監(jiān)控信息存儲(chǔ),而主作業(yè)節(jié)點(diǎn)僅用于處理分片和清理的功能次坡。
2呼猪、實(shí)現(xiàn)彈性擴(kuò)容
通過zookeeper來動(dòng)態(tài)給job節(jié)點(diǎn)分片。如果很大體量的用戶需要我們?cè)谔囟ǖ臅r(shí)間段內(nèi)計(jì)算完成砸琅,那么我們肯定是希望我們的任務(wù)可以通過集群達(dá)到水平的擴(kuò)展宋距,集群里的每個(gè)節(jié)點(diǎn)都處理部分的用戶,不管用戶的數(shù)量有多大症脂,我們只需要增加機(jī)器就可以了谚赎。
舉個(gè)例子:比如我們希望3臺(tái)機(jī)器跑job,我么將我們的任務(wù)分成3片诱篷,框架通過zk的協(xié)調(diào)壶唤,最終會(huì)讓3臺(tái)機(jī)器分配到0,1棕所,2的任務(wù)片闸盔,比如server0->0、server1->1琳省、server2->2迎吵,當(dāng)server0執(zhí)行時(shí),可以只查詢id%3==0的用戶针贬,server1可以只查詢id%3==1的用戶击费,server2可以只查詢id%3==2的用戶。
在以上的基礎(chǔ)上再增加一個(gè)server3桦他,此時(shí)蔫巩,server3分不到任何的分片,沒有分到任務(wù)分片的程序?qū)⒉粓?zhí)行。如果此時(shí)server2掛了圆仔,那么server2被分到的任務(wù)分片將會(huì)分配給server3垃瞧,所以server3就會(huì)代替server2執(zhí)行。如果此時(shí)server3也掛了荧缘,那么框架也會(huì)自動(dòng)的將server3的任務(wù)分片隨機(jī)分配到server0或者server1皆警,那么就可能成:server0->0拦宣、server1->1,2截粗。
這樣就沒有基于數(shù)據(jù)庫(kù)的鎖沖突問題,也可以實(shí)現(xiàn)水平擴(kuò)展
不過也是有問題的
1鸵隧、分片數(shù)是由業(yè)務(wù)代碼層決定绸罗,調(diào)度執(zhí)行協(xié)調(diào)時(shí)沒法進(jìn)一步優(yōu)化,比較靜態(tài)豆瘫,機(jī)器擴(kuò)容后其實(shí)沒法直接用到擴(kuò)容后的性能
2珊蟀、缺乏統(tǒng)一調(diào)度,每個(gè)調(diào)度任務(wù)有重復(fù)的調(diào)度開銷(檢測(cè)任務(wù)trigger)外驱,并且在實(shí)現(xiàn)復(fù)雜的dag調(diào)度時(shí)育灸,只能把所有業(yè)務(wù)調(diào)度寫在一個(gè)實(shí)現(xiàn)中,不夠靈活昵宇。
阿里的定時(shí)任務(wù)框架
1磅崭、早期是:TBSchedule
也是基于Zk做注冊(cè)中心
優(yōu)點(diǎn):是支持集群、分布式瓦哎,靈活的任務(wù)分片砸喻,并且有動(dòng)態(tài)的服務(wù)擴(kuò)容和資源回收
缺點(diǎn):使用的是Timer而不是線程池執(zhí)行任務(wù)調(diào)度。TBSchedule的作業(yè)類型比較單一蒋譬,只能是獲取/處理數(shù)據(jù)一種模式割岛,而且目前文檔偏少
2、目前推出了基于Akka架構(gòu)的Schedulerx2.0
新一代定時(shí)任務(wù)犯助,提供分布式執(zhí)行癣漆、多種任務(wù)類型、統(tǒng)一日志等框架剂买,用戶只要依賴schedulerx-worker這個(gè)jar包惠爽,通過schedulerx2.0提供的編程模型,簡(jiǎn)單幾行代碼就能實(shí)現(xiàn)一套高可靠可運(yùn)維的分布式執(zhí)行引擎雷恃。在海量數(shù)據(jù)并行任務(wù)疆股、復(fù)雜dag調(diào)度
可擴(kuò)展的執(zhí)行引擎
Worker總體架構(gòu)參考Yarn的架構(gòu),分為TaskMaster, Container, Processor三層:
- TaskMaster:類似于yarn的AppMaster倒槐,支持可擴(kuò)展的分布式執(zhí)行框架旬痹,進(jìn)行整個(gè)jobInstance的生命周期管理、container的資源管理,同時(shí)還有failover等能力两残。默認(rèn)實(shí)現(xiàn)StandaloneTaskMaster(單機(jī)執(zhí)行)永毅,BroadcastTaskMaster(廣播執(zhí)行),MapTaskMaster(并行計(jì)算人弓、內(nèi)存網(wǎng)格沼死、網(wǎng)格計(jì)算),MapReduceTaskMaster(并行計(jì)算崔赌、內(nèi)存網(wǎng)格意蛀、網(wǎng)格計(jì)算)。
- Container:執(zhí)行業(yè)務(wù)邏輯的容器框架健芭,支持線程/進(jìn)程/docker/actor等县钥。
- Processor:業(yè)務(wù)邏輯框架,不同的processor表示不同的任務(wù)類型慈迈。
以MapTaskMaster為例若贮,大概的原理如下圖所示:
其借鑒了MapReduce的模式,支持Map痒留、MapReduce模型谴麦,在海量數(shù)據(jù)分發(fā)多臺(tái)機(jī)器的效率上非常方便,支持分布跑批伸头,針對(duì)不同的跑批場(chǎng)景匾效,map模型作業(yè)還提供了并行計(jì)算、內(nèi)存網(wǎng)格熊锭、網(wǎng)格計(jì)算三種執(zhí)行方式:
并行計(jì)算:子任務(wù)300以下弧轧,有子任務(wù)列表。
內(nèi)存網(wǎng)格:子任務(wù)5W以下碗殷,無(wú)子任務(wù)列表精绎,速度快。
網(wǎng)格計(jì)算:子任務(wù)100W以下锌妻,無(wú)子任務(wù)列表代乃。
考拉的kSchedule
這里再說一個(gè)考拉的分布式定時(shí)任務(wù)框架kSchedule,大體與elastic-job類似仿粹,
這里說一點(diǎn)搁吓,kSchedule的無(wú)侵入性做的更好,對(duì)于簡(jiǎn)單任務(wù)不需要事先Job接口吭历,只需要把任務(wù)bean注冊(cè)成容器的Service的public方法即可堕仔,然后再配置界面配置調(diào)度任務(wù)的方法和參數(shù)即可,大大的方便的簡(jiǎn)單任務(wù)的開發(fā)和配置工作晌区;(其實(shí)就是實(shí)現(xiàn)了普通類的方法級(jí)別的定時(shí)任務(wù)配置摩骨,而一般的定時(shí)任務(wù)都是類繼承Job類通贞,重寫execute方法)
這點(diǎn)在其他框架中實(shí)現(xiàn)時(shí)需要寫個(gè)簡(jiǎn)單任務(wù)的調(diào)度分配任務(wù),然后把普通類的方法和入?yún)⒆鳛閯?dòng)態(tài)參數(shù)傳到調(diào)度分配任務(wù)恼五,然后利用反射昌罩,進(jìn)行動(dòng)態(tài)執(zhí)行。
綜合比較選型
簡(jiǎn)單幾條原則
1灾馒、業(yè)務(wù)起步階段:沒有自主研發(fā)運(yùn)維能力茎用,選擇業(yè)界使用最多最成熟的,最好是直接買睬罗,比如阿里云的Schedulerx2.0轨功,把技術(shù)、運(yùn)維都交給阿里云傅物,只開發(fā)業(yè)務(wù)邏輯即可夯辖;或者Elastic-job-cloud版本,在私有云上部署董饰,功能支持也比較完善,花錢都能解決
2圆米、業(yè)務(wù)發(fā)展階段:數(shù)據(jù)規(guī)模和任務(wù)規(guī)模都在擴(kuò)大卒暂,有一定的研發(fā)能力,可以考慮接入成熟開源框架娄帖,比如quartz或者Elastic-job-lite都是開源的也祠,幾臺(tái)機(jī)器搭建起來就可以跑,出問題了開源用解答的也比較多近速。每秒幾千個(gè)任務(wù)沒問題
3诈嘿、業(yè)務(wù)成熟階段:每秒任務(wù)擴(kuò)大到幾萬(wàn)、幾十萬(wàn)個(gè)削葱,而且業(yè)務(wù)個(gè)性化需要越來越多奖亚,比如各種調(diào)度策略,批處理任務(wù)的個(gè)性化支持析砸,這時(shí)候要選擇一個(gè)開源框架的基礎(chǔ)上進(jìn)行二次開發(fā)昔字,目前quartz或者Elastic-job-lite都是不錯(cuò)的選擇
具體的對(duì)比表格
各個(gè)框架對(duì)比文檔---轉(zhuǎn)自:分布式調(diào)度框架大集合
參考文章
分布式調(diào)度框架大集合
詳解應(yīng)對(duì)平臺(tái)高并發(fā)的分布式調(diào)度框架TBSchedule
Quartz架構(gòu)整理
開源的作業(yè)調(diào)度框架Quartz
考拉定時(shí)任務(wù)框架kSchedule
Schedulerx2.0分布式計(jì)算原理&最佳實(shí)踐