如何設計穩(wěn)定性橫跨全球的?Cron?服務


純手工打造每一篇開源資訊與技術干貨贸辈,數(shù)十萬程序員和Linuxer已經(jīng)關注。

導讀

這篇文章主要來描述下?Google?是如何實現(xiàn)一套可靠的分布式 Cron 服務盹舞,服務于內(nèi)部那些需要絕大多數(shù)計算作業(yè)定時調(diào)度的團隊眷唉。 在這個系統(tǒng)的實踐過程中,我們收獲了很多旅敷,包括如何設計生棍、如何實現(xiàn)使得它看上去像一個靠譜的基礎服務。 在這里媳谁,我們來討論下分布式 Cron 可能會遇到哪些問題涂滴,以及如何解決它。

Cron 是?UNIX?中一個常見的工具晴音,用來定期執(zhí)行一些用戶指定的任意任務柔纵。我們先來分析下?Cron?的基本原則和它最常見的實現(xiàn),然后我們來回顧下像?Cron?這樣的服務應該如何運行在一個大型的锤躁、分布式的環(huán)境中搁料,這樣即使單機故障也不會對系統(tǒng)可用性造成影響。 我們將會介紹了一個建立在少量機器上的?Cron?系統(tǒng)系羞,然后結合數(shù)據(jù)中心的調(diào)度服務郭计,從而可以在整個數(shù)據(jù)中心中運行?Cron?任務。

在我們在描述如何運行一個靠譜的分布式 Cron 服務之前椒振,讓我們先來從一個 SRE 的角度來回顧下 Cron拣宏。

Cron 是一個通用的工具,無論是管理員還是普通用戶都可以用它來在系統(tǒng)上運行指定的命令杠人,以及指定何時運行命令,這些指定運行的命令可以是定期垃圾回收宋下,也可以是定期數(shù)據(jù)分析嗡善。 最常見的時間指定格式被稱為 crontab,它不僅支持簡單的時間周期(如学歧,每天中午一次罩引,每個小時一次),也支持較復雜的時間周期枝笨,如每個周六袁铐、每個月的第 30 天等等。

Cron 通常只包含一個組件横浑,被稱為?crond剔桨,它是一個后臺守護程序,加載所有需要運行的 cron 定時任務徙融,根據(jù)它們接下來的運行時間來進行排序洒缀,然后這個守護進程將會等待直到第一個任務開始執(zhí)行。在這個時刻,crond?將會加載執(zhí)行這個任務树绩,之后將它放入隊列等待下一次運行萨脑。


可靠性


從可靠性的角度來看一個服務,需要有很多注意的地方饺饭。

第一渤早,比如 crond,它的故障域本質(zhì)上來說只是一臺機器瘫俊,如果這個機器沒有運行鹊杖,不論是 cron 調(diào)度還是加載的任務都是不可運行的。因此军援,考慮一個非常簡單的分布式的例子 ——— 我們使用兩臺機器仅淑,然后 cron 調(diào)度在其中一臺機器上運行任務(比如通過 ssh)。然后產(chǎn)生了一個故障域了:調(diào)度任務和目標服務器都可能失敗胸哥。

另外一個需要注意的地方是涯竟,即使是?crond?重啟(包括服務器重啟),上面部署的 crontab 配置也不應該丟失空厌。crond 執(zhí)行一個任務然后就‘忘記’了這個任務的狀態(tài)庐船,它并不會嘗試去跟蹤這個任務的執(zhí)行狀態(tài),包括是否該執(zhí)行是否已經(jīng)執(zhí)行嘲更。

anacron是一個例外筐钟,它是crontab的一個補充,它嘗試運行哪些因為服務器宕機而應該執(zhí)行卻沒執(zhí)行的任務赋朦。這僅限于每日或者更小執(zhí)行頻率的任務篓冲,但對于在工作站和筆記本電腦上運行維護工作非常有用。通過維護一個包括最后執(zhí)行時間的配置文件宠哄,使得運行這些特殊的任務更加方便壹将。


Cron 的任務和冪等性


Cron 的任務用來執(zhí)行定期任務,但是除此之外毛嫉,卻很難在進一步知道它們的功能诽俯。讓我們先把要討論的主題拋開一邊,現(xiàn)在先來就 Cron 任務本身來做下探討承粤,因為只有理解了 Cron 任務的各種各樣的需求暴区,才能知道它是如何影響我們需要的可靠性要求,而這一方面的探討也將貫穿接下來的文章辛臊。

有一些 Cron 任務是冪等性的仙粱,這樣在某些系統(tǒng)故障的情況下,可以很安全的執(zhí)行它們多次彻舰,比如缰盏,垃圾回收。然而有些 Cron 任務卻不應該被執(zhí)行多次,比如某個發(fā)送郵件的任務口猜。

還有更復雜的情況负溪,有些 Cron 任務允許因為某些情況而“忘了”運行,而某些 Cron 任務卻不能容忍這些济炎,比如川抡,垃圾回收的 Cron 任務每 5 分鐘調(diào)度一次,即使某一次沒有執(zhí)行也不會有太大的問題须尚,然而崖堤,一個月一次的支付薪水的任務,卻絕對不允許有失誤耐床。

Cron 任務的各種不同的類型使得不可能有一個通用的解決方案密幔,使得它可以應對各種各樣的失敗。所以撩轰,在本文中上面說的那些情況胯甩,我們更傾向于錯過某一次的運行,而不是運行它們兩次或者更多堪嫂。Cron 任務的所有者應該(也必須)監(jiān)控著它們的任務偎箫,比如返回任務的調(diào)用結果,或者單獨發(fā)送運行的日志給所屬者等等皆串,這樣淹办,即使跳過了任務的某次執(zhí)行,也能夠很方便的采取對應的補救動作恶复。當任務失敗時怜森,我們更傾向于將任務狀態(tài)置為 “fail closed” 來避免產(chǎn)生系統(tǒng)性的不良狀態(tài)。


大規(guī)模部署 Cron


當從單機到集群部署 Cron 時谤牡,需要重新思考如何使 Cron 在這種環(huán)境下良好的運行塔插。在對 Google 的 Cron 進行解說之前,讓我們先來討論下單機以及多機之間的區(qū)別拓哟,以及針對這變化如何設計。

擴展基礎架構

常規(guī)的 Cron 僅限于單個機器伶授,而大規(guī)模部署的 Cron 解決方案不能僅僅綁定到一個單獨的機器断序。假設我們擁有一個 1000 臺服務器的數(shù)據(jù)中心,如果即使是 1/1000 的幾率造成服務器不可用都能摧毀我們整個 Cron 服務糜烹,這明顯不是我們所希望的违诗。

所以,為了解決這個問題疮蹦,我們必須將服務與機器解耦诸迟。這樣如果想運行一個服務,那么僅僅需要指定它運行在哪個數(shù)據(jù)中心即可,剩下的事情就依賴于數(shù)據(jù)中心的調(diào)度系統(tǒng)(當然前提是調(diào)度系統(tǒng)也應該是可靠的)阵苇,調(diào)度系統(tǒng)會負責在哪臺或者哪些機器上運行服務壁公,以及能夠良好的處理機器掛掉這種情況。 那么绅项,如果我們要在數(shù)據(jù)中心中運行一個任務紊册,也僅僅是發(fā)送一條或多條 RPC 給數(shù)據(jù)中心的調(diào)度系統(tǒng)。

然而快耿,這一過程顯然并不是瞬時完成的囊陡。比如,要檢查哪些機器掛掉了(機器健康檢查程序掛了怎么辦)掀亥,以及在另外一些機器上重新運行任務(服務依賴重新部署重新調(diào)用任務)都是需要花費一定時間的撞反。

將程序轉(zhuǎn)移到另外一個機器上可能意味著損失一些存儲在老機器上的一些狀態(tài)信息(除非也采用動態(tài)遷移),重新調(diào)度運行的時間間隔也可能超過最小定義的一分鐘搪花,所以遏片,我們也必須考慮到上述這兩種情況。一個很直接的做法鳍侣,將狀態(tài)文件放入分布式文件系統(tǒng)丁稀,如 GFS,在任務運行的整個過程中以及重新部署運行任務時倚聚,都是用它來記錄使用相關狀態(tài)线衫。 然而,這個解決方案卻不能滿足我們預期的時效性這個需求惑折,比如授账,你要運行一個每五分鐘跑一次的 Cron 任務,重新部署運行消耗的 1-2 分鐘對這個任務來說也是相當大的延遲了惨驶。

及時性的需求可能會促使各種熱備份技術的使用白热,這樣就能夠快速記錄狀態(tài)以及從原有狀態(tài)快速恢復。

需求擴展

將服務部署在數(shù)據(jù)中心和單服務器的另一個實質(zhì)性的區(qū)別是粗卜,如何規(guī)劃任務所需要的計算資源屋确,如 CPU 或內(nèi)存等。

單機服務通常是通過進程來進行資源隔離续扔,雖然現(xiàn)在 Docker 變得越來越普遍攻臀,但是使用它來隔離一切目前也不太是很通用的做法,包括限制crond以及它所要運行的任務纱昧。

大規(guī)模部署在數(shù)據(jù)中心經(jīng)常使用容器來進行資源隔離刨啸。隔離是必要的,因為我們肯定希望數(shù)據(jù)中心中運行的某個程序不會對其它程序產(chǎn)生不良影響识脆。為了隔離的有效性设联,在運行前肯定得先預知運行的時候需要哪些資源——包括 Cron 系統(tǒng)本身和要運行的任務善已。這又會產(chǎn)生一個問題,即如果數(shù)據(jù)中心暫時沒有足夠的資源离例,那么這個任務可能會延遲運行换团。這就要求我們不僅要監(jiān)控 Cron 任務加載的情況,也要監(jiān)控 Cron 任務的全部狀態(tài)粘招,包括開始加載到終止運行啥寇。

現(xiàn)在,我們希望的 Cron 系統(tǒng)已經(jīng)從單機運行的情況下解耦洒扎,如之前描述的那樣辑甜,我們可能會遇到部分任務運行或加載失敗。這時候幸虧任務配置的通用性袍冷,在數(shù)據(jù)中心中運行一個新的 Cron 任務就可以簡單的通過 RPC 調(diào)用的方式來進行磷醋,不過不幸的是,這樣我們只能知道 RPC 調(diào)用是否成功胡诗,卻無法具體知道任務失敗的具體地方邓线,比如,任務在運行的過程中失敗煌恢,那么恢復程序還必須將這些中間過程處理好骇陈。

在故障方面,數(shù)據(jù)中心遠比一臺單一的服務器復雜瑰抵。Cron 從原來僅僅的一個單機二進制程序你雌,到整個數(shù)據(jù)中心運行,其期間增加了很多明顯或不明顯的依賴關系二汛。作為像 Cron 這樣的一個基礎服務婿崭,我們希望得到保證的是,即使在數(shù)據(jù)中心中運行發(fā)生了一些 “Fail”(如肴颊,部分機器停電或存儲掛掉)氓栈,服務依然能夠保證功能性正常運行。為了提高可靠性婿着,我們應該將數(shù)據(jù)中心的調(diào)度系統(tǒng)部署在不同的物理位置授瘦,這樣,即使一個或一部分電源掛掉竟宋,也能保證至少 Cron 服務不會全部不可用提完。


Google 的 Cron 是如何建設的


現(xiàn)在讓我們來解決這些問題,這樣才能在一個大規(guī)模的分布式集群中部署可靠的 Cron 服務袜硫,然后在著重介紹下 Google 在分布式 Cron 方面的一些經(jīng)驗。

跟蹤 Cron 任務的狀態(tài)

向上面描述過的那樣挡篓,我們應該跟蹤 Cron 任務的實時狀態(tài)婉陷,這樣帚称,即使失敗了,我們也更加容易恢復它秽澳。而且闯睹,這種狀態(tài)的一致性是至關重要的:相比錯誤的多運行 10 遍相同的 Cron 任務,我們更能接受的是不去運行它担神÷コ裕回想下,很多 Cron 任務妄讯,它并不是冪等性的孩锡,比如發(fā)送通知郵件。

我們有兩個選項亥贸,將 Cron 任務的數(shù)據(jù)通通存儲在一個靠譜的分布式存儲中躬窜,或者僅僅保存任務的狀態(tài)。當我們設計分布式 Cron 服務時炕置,我們采取的是第二種荣挨,有如下幾個原因:

分布式存儲,如 GFS 或 HDFS朴摊,往往用來存儲大文件(如 網(wǎng)頁爬蟲程序的輸出等)默垄,然后我們需要存儲的 Cron狀態(tài)卻非常非常小。將如此小的文件存儲在這種大型的分布式文件系統(tǒng)上是非常昂貴的甚纲,而且考慮到分布式文件系統(tǒng)的延遲口锭,也不是很適合。

像 Cron 服務這種基礎服務贩疙,它需要的依賴應該是越少越好讹弯。這樣,即使部分數(shù)據(jù)中心掛掉这溅,Cron 服務至少也能保證其功能性并持續(xù)一段時間组民。這并不意味著存儲應該直接是 Cron 程序的一部分(這本質(zhì)上是一個實現(xiàn)細節(jié))。Cron 應該是一個能夠獨立運作的下游系統(tǒng)悲靴,以便供用戶操作使用臭胜。

使用 Paxos

我們部署多個實例的 Cron 服務,然后通過 Paxos 算法來同步這些實例間的狀態(tài)癞尚。

Paxos 算法和它其它的替代算法(如 Zab耸三,Raft 等)在分布式系統(tǒng)中是十分常見的。具體描述 Paxos 不在本文范圍內(nèi)浇揩,它的基本作用就是使多個不可靠節(jié)點間的狀態(tài)保持一致仪壮,只要大部分 Paxos 組成員可用,那么整個分布式系統(tǒng)胳徽,就能作為一個整體處理狀態(tài)的變化积锅。

分布式 Cron 使用一個獨立的主任務爽彤,見下圖,只有它才能更改共享的狀態(tài)缚陷,也只有它才能加載 Cron 任務适篙。我們這里使用了 Paxos 的一個變體—— Fast Paxos,這里 Fast Paxos 的主節(jié)點也是 Cron 服務的主節(jié)點箫爷。

如果主節(jié)點掛掉嚷节,Paxos 的健康檢查機制會在秒級內(nèi)快速發(fā)現(xiàn),并選舉出一個新的主節(jié)點虎锚。一旦選舉出新的主節(jié)點硫痰,Cron 服務也就隨著選舉出了一個新的 Cron 主節(jié)點,這個新的 Cron 主節(jié)點將會接手前一個主節(jié)點留下的所有的未完成的工作翁都。在這里 Cron 的主節(jié)點和 Paxos 的主節(jié)點是一樣的碍论,但是 Cron 的主節(jié)點需要處理一下額外的工作而已”浚快速選舉新的主節(jié)點的機制可以讓我們大致可以容忍一分鐘的故障時間鳍悠。

我們使用 Paxos 算法保持的最重要的一個狀態(tài)是,哪些 Cron 任務在運行坐搔。對于每一個運行的 Cron 任務藏研,我們會將其加載運行的開始以及結束同步給一定數(shù)量的節(jié)點。

主節(jié)點和從節(jié)點角色

如上面描述的那樣概行,我們在 Cron 服務中使用 Paxos 并部署蠢挡,其擁有兩個不同的角色,主節(jié)點以及從節(jié)點凳忙。讓我們來就每個角色來做具體的描述业踏。

主節(jié)點

主節(jié)點用來加載 Cron 任務,它有個內(nèi)部的調(diào)度系統(tǒng)涧卵,類似于單機的crond勤家,維護一個任務加載列表,在指定的時間加載任務柳恐。

當任務加載的時刻到來伐脖,主節(jié)點將會 “宣告” 它將會加載這個指定的任務,并且計算這個任務下次的加載時間乐设,就像?crond?的做法一樣讼庇。當然,就像?crond?那樣近尚,一個任務加載后蠕啄,下一次的加載時間可能人為的改變,這個變化也要同步給從節(jié)點戈锻。簡單的標識 Cron 任務還不夠歼跟,我們還應該將這個任務與開始執(zhí)行時間相關聯(lián)綁定却嗡,以避免 Cron 任務在加載時發(fā)生歧義(特別是那些高頻的任務,如一分鐘一次的那些)嘹承。這個“通告”通過 Paxos 來進行。下圖展示了這一過程如庭。

保持 Paxos 通訊同步非常重要叹卷,只有 Paxos 法定數(shù)收到了加載通知,這個指定的任務才能被加載執(zhí)行坪它。Cron 服務需要知道每個任務是否已經(jīng)啟動骤竹,這樣即使主節(jié)點掛掉,也能決定接下來的動作往毡。如果不進行同步蒙揣,意味著整個 Cron 任務運行在主節(jié)點,而從節(jié)點無法感知到這一切开瞭。如果發(fā)生了故障懒震,很有可能這個任務就被再次執(zhí)行,因為沒有節(jié)點知道這個任務已經(jīng)被執(zhí)行過了嗤详。

Cron 任務的完成狀態(tài)通過 Paxos 通知給其它節(jié)點个扰,從而保持同步,這里要注意一點葱色,這里的“完成” 狀態(tài)并不是表示任務是成功或者失敗递宅。我們跟蹤 Cron 任務在指定調(diào)用時間被執(zhí)行的情況,我們同樣需要處理一點情況是苍狰,如果 Cron 服務在加載任務進行執(zhí)行的過程中失敗后怎么辦办龄,這點我們在接下來會進行討論。

主節(jié)點另一個重要的特性是淋昭,不管是出于什么原因主節(jié)點失去了其主控權俐填,它都必須立馬停止同數(shù)據(jù)中心調(diào)度系統(tǒng)的交互。主控權的保持對于訪問數(shù)據(jù)中心應該是互斥了响牛。如果不這樣玷禽,新舊兩個主節(jié)點可能會對數(shù)據(jù)中心的調(diào)度系統(tǒng)發(fā)起互相矛盾的操作請求。

從節(jié)點

從節(jié)點實時監(jiān)控從主節(jié)點傳來的狀態(tài)信息呀打,以便在需要的時刻做出積極響應矢赁。所有主節(jié)點的狀態(tài)變動信息,都通過 Paxos 傳到各個從節(jié)點。和主節(jié)點類似的是箱靴,從節(jié)點同樣維持一個列表橙垢,保存著所有的 Cron 任務驶拱。這個列表必須在所有的節(jié)點保持一致(當然還是通過 Paxos)额获。

當接到加載任務的通知后够庙,從節(jié)點會將此任務的下次加載時間放入本地任務列表中。這個重要的狀態(tài)信息變化(這是同步完成的)保證了系統(tǒng)內(nèi)部 Cron 作業(yè)的時間表是一致的抄邀。我們跟蹤所有有效的加載任務耘眨,也就是說,我們跟蹤任務何時啟動境肾,而不是結束剔难。

如果一個主節(jié)點掛掉或者因為某些原因失聯(lián)(比如,網(wǎng)絡異常等)奥喻,一個從節(jié)點有可能被選舉成為一個新的主節(jié)點偶宫。這個選舉的過程必須在一分鐘內(nèi)運行,以避免 Cron 任務丟失的情況环鲤。一旦被選舉為主節(jié)點纯趋,所有運行的加載任務(或部分失敗的),必須被重新驗證其有效性冷离。這個可能是一個復雜的過程吵冒,在 Cron 服務系統(tǒng)和數(shù)據(jù)中心的調(diào)度系統(tǒng)上都需要執(zhí)行這樣的驗證操作,這個過程有必要詳細說明西剥。

故障恢復

如上所述桦锄,主節(jié)點和數(shù)據(jù)中心的調(diào)度系統(tǒng)之間會通過 RPC 來加載一個邏輯 Cron 任務,但是蔫耽,這一系列的 RPC 調(diào)用過程是有可能失敗的结耀,所以,我們必須考慮到這種情況匙铡,并且處理好图甜。

回想下,每個加載的 Cron 任務會有兩個同步點:開始加載以及執(zhí)行完成鳖眼。這能夠讓我們區(qū)分開不同的加載任務黑毅。即使任務加載只需要調(diào)用一次 RPC,但是我們怎么知道 RPC 調(diào)用實際真實成功呢钦讳?我們知道任務何時開始矿瘦,但是如果主節(jié)點掛了我們就不會知道它何時結束。

為了解決這個問題愿卒,所有在外部系統(tǒng)進行的操作缚去,要么其操作是冪等性的(也就是說,我們可以放心的執(zhí)行它們多次)琼开,要么我們必須實時監(jiān)控它們的狀態(tài)易结,以便能清楚的知道何時完成。

這些條件明顯增加了限制,實現(xiàn)起來也有一定的難度搞动,但是在分布式環(huán)境中這些限制卻是保證 Cron 服務準確運行的根本躏精,能夠良好的處理可能出現(xiàn)的 “fail”。如果不能妥善處理這些鹦肿,將會導致 Cron 任務的加載丟失矗烛,或者加載多次重復的 Cron 任務。

大多數(shù)基礎服務在數(shù)據(jù)中心(比如 Mesos)加載邏輯任務時都會為這些任務命名箩溃,這樣方便了查看任務的狀態(tài)高诺,終止任務,或者執(zhí)行其它的維護操作碾篡。解決冪等性的一個合理的解決方案是將執(zhí)行時間放在名字中?——這樣不會在數(shù)據(jù)中心的調(diào)度系統(tǒng)里造成任務異變操作 —— 然后在將它們分發(fā)給 Cron 服務所有的節(jié)點。如果 Cron 服務的主節(jié)點掛掉筏餐,那么新的主節(jié)點只需要簡單的通過預處理任務名字來查看其對應的狀態(tài)开泽,然后加載遺漏的任務即可。

注意下魁瞪,我們在節(jié)點間保持內(nèi)部狀態(tài)一致的時候穆律,實時監(jiān)控調(diào)度加載任務的時間。同樣导俘,我們也需要消除同數(shù)據(jù)中心調(diào)度交互時可能發(fā)生的不一致情況峦耘,所以這里我們以調(diào)度的加載時間為準。比如旅薄,有一個短暫但是頻繁執(zhí)行的 Cron 任務辅髓,它已經(jīng)被執(zhí)行了,但是在準備把情況通告給其它節(jié)點時少梁,主節(jié)點掛了洛口,并且故障時間持續(xù)的特別長——長到這個 Cron 任務都已經(jīng)成功執(zhí)行完了。然后新的主節(jié)點要查看這個任務的狀態(tài)凯沪,發(fā)現(xiàn)它已經(jīng)被執(zhí)行完成了第焰,然后嘗試加載它。如果包含了這個時間妨马,那么主節(jié)點就會知道挺举,這個任務已經(jīng)被執(zhí)行過了,就不會重復執(zhí)行第二次烘跺。

在實際實施的過程中湘纵,狀態(tài)監(jiān)督是一個更加復雜的工作,它的實現(xiàn)過程和細節(jié)依賴與其它一些底層的基礎服務滤淳,然而瞻佛,上面并沒有包括相關系統(tǒng)的實現(xiàn)描述。根據(jù)你當前可用的基礎設施,你可能需要在冒險重復執(zhí)行任務和跳過執(zhí)行任務?之間做出折中選擇伤柄。


狀態(tài)保存


使用 Paxos 來同步只是處理狀態(tài)中遇到的其中一個問題绊困。Paxos 本質(zhì)上只是通過一個日志來持續(xù)記錄狀態(tài)改變,并且隨著狀態(tài)的改變而進行將日志同步适刀。這會產(chǎn)生兩個影響:第一秤朗,這個日志需要被壓縮,防止其無限增長笔喉;第二取视,這個日志本身需要保存在一個地方。

為了避免其無限增長常挚,我們僅僅取狀態(tài)當前的快照作谭,這樣,我們能夠快速的重建狀態(tài)奄毡,而不用在根據(jù)之前所有狀態(tài)日志來進行重演折欠。比如,在日志中我們記錄一條狀態(tài) “計數(shù)器加 1”吼过,然后經(jīng)過了 1000 次迭代后锐秦,我們就記錄了 1000 條狀態(tài)日志,但是我們也可以簡單的記錄一條記錄 “將計數(shù)器設置為 1000”來做替代盗忱。

如果日志丟失酱床,我們也僅僅丟失當前狀態(tài)的一個快照而已√说瑁快照其實是最臨界的狀態(tài) —— 如果丟失了快照扇谣,我們基本上就得從頭開始了,因為我們丟失了上一次快照與丟失快照期間所有的內(nèi)部狀態(tài)闲昭。從另一方面說揍堕,丟失日志,也意味著汤纸,將 Cron 服務拉回到有記錄的上一次快照所標示的地方衩茸。

我們有兩個主要選擇來保存數(shù)據(jù): 存儲在外部的一個可用的分布式存儲服務中,或者贮泞,在內(nèi)部一個系統(tǒng)來存儲 Cron 服務的狀態(tài)楞慈。當我們設計系統(tǒng)時,這兩點都需要考慮啃擦。

我們將 Paxos 日志存儲在 Cron 服務節(jié)點所在服務器本地的磁盤中囊蓝。默認的三個節(jié)點意味著,我們有三份日志的副本令蛉。我們同樣也將快照存儲在服務器本身聚霜,然而狡恬,因為其本身是非常重要的,我們也將它在分布式存儲服務中做了備份蝎宇,這樣弟劲,即使小概率的三個節(jié)點機器都故障了,也能夠服務恢復姥芥。

我們并沒有將日志本身存儲在分布式存儲中兔乞,因為我們覺得,丟失日志也僅僅代表最近的一些狀態(tài)丟失凉唐,這個我們其實是可以接受的庸追。而將其存儲在分布式存儲中會帶來一定的性能損失,因為它本身在不斷的小字節(jié)寫入不適用與分布式存儲的使用場景台囱。同時三臺服務器全故障的概率太小淡溯,但是一旦這種情況發(fā)生了,我們也能自動的從快照中恢復簿训,也僅僅損失從上次快照到故障點的這部分而已咱娶。當然,就像設計 Cron 服務本身一樣煎楣,如何權衡,也要根據(jù)自己的基礎設施情況來決定车伞。

將日志和快照存本地择懂,以及快照在分布式存儲備份,這樣另玖,即使一個新的節(jié)點啟動困曙,也能夠通過網(wǎng)絡從其它已經(jīng)運行的節(jié)點處獲取這些信息。這意味著谦去,啟動節(jié)點與服務器本身并沒有任何關系慷丽,重新安排一個新的服務器(比如重啟)來擔當某個節(jié)點的角色 其本質(zhì)上也是影響服務的可靠性的問題之一。


運行一個大型的 Cron


還有一些其它的鳄哭、小型的要糊,但是同樣有趣的一些情況或能影響部署一個大型的 Cron 服務。傳統(tǒng)的 Cron 規(guī)模很凶鼻稹:最多包含數(shù)十個 Cron 任務锄俄。然而,如果在一個數(shù)據(jù)中心的超過千臺服務器來運行 Cron 服務勺拣,那么你就會遇到各種各樣的問題奶赠。

一個比較大的問題是,分布式系統(tǒng)常常要面臨的一個經(jīng)典問題:驚群問題药有,在 Cron 服務的使用中會造成大量的尖峰情況毅戈。當要配置一個每天執(zhí)行的 Cron 任務,大多數(shù)人第一時間想到的是在半夜執(zhí)行,然后它們就這么配置了苇经。如果一個 Cron 任務在一臺機器上執(zhí)行赘理,那沒有問題,但是如果你的任務是執(zhí)行一個涉及數(shù)千 worker 的 mapreduce 任務塑陵,或者感憾,有 30 個不同的團隊在數(shù)據(jù)中心中要配置這樣的一個每天運行的任務,那么我們就必須要擴展下crontab的格式了令花。

傳統(tǒng)的crontab阻桅,用戶通過定義“分鐘”,“小時”兼都,“每月(或每周)第幾天”嫂沉,“月數(shù)”來指定 cron 任務運行的時間,或者通過星號(*)來代表每個對應的值扮碧。如趟章,每天凌晨運行,它的 crontab 格式為0 0 * * *慎王,代表每天的 0 點 0 分運行蚓土。我們在此基礎之上還推出了問號(?)這個符號赖淤,它標示蜀漆,在這個對應的時間軸上,任何時間都可以咱旱,Cron 服務就會自由選擇合適的值确丢,在指定的時間段內(nèi)隨機選擇對應的值,這樣使任務運行更均衡吐限。如?0 鲜侥? * * *,表示每天 0-23 點鐘诸典,隨機一個小時的 0 分來運行這個任務描函。

盡管加了這項變化,由 Cron 任務所造成的 load 值仍然有明顯的尖峰狐粱,下圖表示了 Google 中 cron 任務加載的數(shù)量赘阀。尖峰值往往表示那些需要固定頻率在指定時間運行的任務。


總結


Cron 服務作為 UNIX 的基礎服務已經(jīng)有接近 10 年脑奠。當前整個行業(yè)都朝著大型分布式系統(tǒng)演化基公,那時,表示硬件的最小單位將會是數(shù)據(jù)中心宋欺,那么大量的技術棧需要對應改變轰豆,Cron 也不會是例外胰伍。仔細審視下 Cron 服務所需要的服務特性,以及 Cron 任務的需求酸休,都會推動我們來進行新的設計骂租。

基于 Google 的解決方案,我們已經(jīng)討論了 Cron 服務在一個分布式系統(tǒng)中對應的約束和可能的設計斑司。這個解決方案需要在分布式環(huán)境中的強一致性保證渗饮,它的實現(xiàn)核心是通過 Paxos 這樣一種通用的算法,在一個不可靠的環(huán)境中達成最終一致宿刮。使用 Paxos互站,正確對大規(guī)模環(huán)境下 Cron 任務失敗情況的分析,以及分布式的環(huán)境的使用僵缺,共同造就了在 Google 內(nèi)部使用的健壯的 Cron 服務胡桃。

原文來自:https://linux.cn:443/article-7860-1.html

本文地址:http://www.linuxprobe.com/stable-cron-service.html編輯:楊帆,審核員:馮琪


讓您學習到的每一節(jié)課都有所收獲

《Linux就該這么學》是由資深運維專家劉遄及全國多名紅帽架構師(RHCA)基于最新RHEL7系統(tǒng)共同編寫的高質(zhì)量Linux技術自學教程磕潮,極其適合用于Linux技術入門教程或講課輔助教材翠胰。

? 劉遄老師QQ:5604241

? 學員助教QQ:5604674

? Linux技術交流A群(滿):560843

? Linux技術交流B群:340829

? Linux技術交流C群:463590

? 官方站點:www.linuxprobe.com

? 電腦在線閱讀效果更佳:

http://www.linuxprobe.com/chapter-00.html

按住圖片3秒,即可自動關注自脯。

點擊左下角查看更多熱門技術




最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末之景,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子膏潮,更是在濱河造成了極大的恐慌锻狗,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戏罢,死亡現(xiàn)場離奇詭異屋谭,居然都是意外死亡脚囊,警方通過查閱死者的電腦和手機龟糕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悔耘,“玉大人讲岁,你說我怎么就攤上這事〕囊裕” “怎么了缓艳?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長看峻。 經(jīng)常有香客問我阶淘,道長,這世上最難降的妖魔是什么互妓? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任溪窒,我火速辦了婚禮坤塞,結果婚禮上,老公的妹妹穿的比我還像新娘澈蚌。我一直安慰自己摹芙,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布宛瞄。 她就那樣靜靜地躺著浮禾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪份汗。 梳的紋絲不亂的頭發(fā)上盈电,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音裸影,去河邊找鬼挣轨。 笑死,一個胖子當著我的面吹牛轩猩,可吹牛的內(nèi)容都是我干的卷扮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼均践,長吁一口氣:“原來是場噩夢啊……” “哼晤锹!你這毒婦竟也來了?” 一聲冷哼從身側響起彤委,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鞭铆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后焦影,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體车遂,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年斯辰,在試婚紗的時候發(fā)現(xiàn)自己被綠了舶担。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡彬呻,死狀恐怖衣陶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闸氮,我是刑警寧澤剪况,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蒲跨,受9級特大地震影響译断,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜或悲,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一孙咪、第九天 我趴在偏房一處隱蔽的房頂上張望藏姐。 院中可真熱鬧,春花似錦该贾、人聲如沸羔杨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兜材。三九已至,卻和暖如春逞力,著一層夾襖步出監(jiān)牢的瞬間曙寡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工寇荧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留举庶,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓揩抡,卻偏偏與公主長得像户侥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子峦嗤,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

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

  • 分布式系統(tǒng)面臨的第一個問題就是數(shù)據(jù)分布蕊唐,即將數(shù)據(jù)均勻地分布到多個存儲節(jié)點。另外烁设,為了保證可靠性和可用性替梨,需要將數(shù)據(jù)...
    olostin閱讀 4,550評論 2 26
  • 本文由廈門大學計算機系教師林子雨翻譯,翻譯質(zhì)量很高装黑,本人只對極少數(shù)翻譯得不太恰當?shù)牡胤竭M行了修改副瀑。 【摘要】:Sp...
    Jeffbond閱讀 3,922評論 1 42
  • 尋找一種易于理解的一致性算法(擴展版) 摘要 Raft 是一種為了管理復制日志的一致性算法。它提供了和 Paxos...
    枝葉君閱讀 2,627評論 0 15
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理恋谭,服務發(fā)現(xiàn)糠睡,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 尋找一種易于理解的一致性算法(擴展版) 摘要 Raft 是一種為了管理復制日志的一致性算法箕别。它提供了和 Paxos...
    yflau閱讀 942評論 0 1