純手工打造每一篇開源資訊與技術(shù)干貨,數(shù)十萬程序員和Linuxer已經(jīng)關(guān)注。
導(dǎo)讀 |
這篇文章主要來描述下?Google?是如何實現(xiàn)一套可靠的分布式 Cron 服務(wù),服務(wù)于內(nèi)部那些需要絕大多數(shù)計算作業(yè)定時調(diào)度的團隊。 在這個系統(tǒng)的實踐過程中,我們收獲了很多,包括如何設(shè)計、如何實現(xiàn)使得它看上去像一個靠譜的基礎(chǔ)服務(wù)。 在這里,我們來討論下分布式 Cron 可能會遇到哪些問題,以及如何解決它。 |
Cron 是?UNIX?中一個常見的工具,用來定期執(zhí)行一些用戶指定的任意任務(wù)。我們先來分析下?Cron?的基本原則和它最常見的實現(xiàn),然后我們來回顧下像?Cron?這樣的服務(wù)應(yīng)該如何運行在一個大型的、分布式的環(huán)境中,這樣即使單機故障也不會對系統(tǒng)可用性造成影響。 我們將會介紹了一個建立在少量機器上的?Cron?系統(tǒng),然后結(jié)合數(shù)據(jù)中心的調(diào)度服務(wù),從而可以在整個數(shù)據(jù)中心中運行?Cron?任務(wù)。
在我們在描述如何運行一個靠譜的分布式 Cron 服務(wù)之前,讓我們先來從一個 SRE 的角度來回顧下 Cron。
Cron 是一個通用的工具,無論是管理員還是普通用戶都可以用它來在系統(tǒng)上運行指定的命令,以及指定何時運行命令,這些指定運行的命令可以是定期垃圾回收,也可以是定期數(shù)據(jù)分析。 最常見的時間指定格式被稱為 crontab,它不僅支持簡單的時間周期(如,每天中午一次,每個小時一次),也支持較復(fù)雜的時間周期,如每個周六、每個月的第 30 天等等。
Cron 通常只包含一個組件,被稱為?crond,它是一個后臺守護程序,加載所有需要運行的 cron 定時任務(wù),根據(jù)它們接下來的運行時間來進行排序,然后這個守護進程將會等待直到第一個任務(wù)開始執(zhí)行。在這個時刻,crond?將會加載執(zhí)行這個任務(wù),之后將它放入隊列等待下一次運行。
從可靠性的角度來看一個服務(wù),需要有很多注意的地方。
第一,比如 crond,它的故障域本質(zhì)上來說只是一臺機器,如果這個機器沒有運行,不論是 cron 調(diào)度還是加載的任務(wù)都是不可運行的。因此,考慮一個非常簡單的分布式的例子 ——— 我們使用兩臺機器,然后 cron 調(diào)度在其中一臺機器上運行任務(wù)(比如通過 ssh)。然后產(chǎn)生了一個故障域了:調(diào)度任務(wù)和目標服務(wù)器都可能失敗。
另外一個需要注意的地方是,即使是?crond?重啟(包括服務(wù)器重啟),上面部署的 crontab 配置也不應(yīng)該丟失。crond 執(zhí)行一個任務(wù)然后就‘忘記’了這個任務(wù)的狀態(tài),它并不會嘗試去跟蹤這個任務(wù)的執(zhí)行狀態(tài),包括是否該執(zhí)行是否已經(jīng)執(zhí)行。
anacron是一個例外,它是crontab的一個補充,它嘗試運行哪些因為服務(wù)器宕機而應(yīng)該執(zhí)行卻沒執(zhí)行的任務(wù)。這僅限于每日或者更小執(zhí)行頻率的任務(wù),但對于在工作站和筆記本電腦上運行維護工作非常有用。通過維護一個包括最后執(zhí)行時間的配置文件,使得運行這些特殊的任務(wù)更加方便。
Cron 的任務(wù)用來執(zhí)行定期任務(wù),但是除此之外,卻很難在進一步知道它們的功能。讓我們先把要討論的主題拋開一邊,現(xiàn)在先來就 Cron 任務(wù)本身來做下探討,因為只有理解了 Cron 任務(wù)的各種各樣的需求,才能知道它是如何影響我們需要的可靠性要求,而這一方面的探討也將貫穿接下來的文章。
有一些 Cron 任務(wù)是冪等性的,這樣在某些系統(tǒng)故障的情況下,可以很安全的執(zhí)行它們多次,比如,垃圾回收。然而有些 Cron 任務(wù)卻不應(yīng)該被執(zhí)行多次,比如某個發(fā)送郵件的任務(wù)。
還有更復(fù)雜的情況,有些 Cron 任務(wù)允許因為某些情況而“忘了”運行,而某些 Cron 任務(wù)卻不能容忍這些,比如,垃圾回收的 Cron 任務(wù)每 5 分鐘調(diào)度一次,即使某一次沒有執(zhí)行也不會有太大的問題,然而,一個月一次的支付薪水的任務(wù),卻絕對不允許有失誤。
Cron 任務(wù)的各種不同的類型使得不可能有一個通用的解決方案,使得它可以應(yīng)對各種各樣的失敗。所以,在本文中上面說的那些情況,我們更傾向于錯過某一次的運行,而不是運行它們兩次或者更多。Cron 任務(wù)的所有者應(yīng)該(也必須)監(jiān)控著它們的任務(wù),比如返回任務(wù)的調(diào)用結(jié)果,或者單獨發(fā)送運行的日志給所屬者等等,這樣,即使跳過了任務(wù)的某次執(zhí)行,也能夠很方便的采取對應(yīng)的補救動作。當任務(wù)失敗時,我們更傾向于將任務(wù)狀態(tài)置為 “fail closed” 來避免產(chǎn)生系統(tǒng)性的不良狀態(tài)。
當從單機到集群部署 Cron 時,需要重新思考如何使 Cron 在這種環(huán)境下良好的運行。在對 Google 的 Cron 進行解說之前,讓我們先來討論下單機以及多機之間的區(qū)別,以及針對這變化如何設(shè)計。
擴展基礎(chǔ)架構(gòu)
常規(guī)的 Cron 僅限于單個機器,而大規(guī)模部署的 Cron 解決方案不能僅僅綁定到一個單獨的機器。假設(shè)我們擁有一個 1000 臺服務(wù)器的數(shù)據(jù)中心,如果即使是 1/1000 的幾率造成服務(wù)器不可用都能摧毀我們整個 Cron 服務(wù),這明顯不是我們所希望的。
所以,為了解決這個問題,我們必須將服務(wù)與機器解耦。這樣如果想運行一個服務(wù),那么僅僅需要指定它運行在哪個數(shù)據(jù)中心即可,剩下的事情就依賴于數(shù)據(jù)中心的調(diào)度系統(tǒng)(當然前提是調(diào)度系統(tǒng)也應(yīng)該是可靠的),調(diào)度系統(tǒng)會負責(zé)在哪臺或者哪些機器上運行服務(wù),以及能夠良好的處理機器掛掉這種情況。 那么,如果我們要在數(shù)據(jù)中心中運行一個任務(wù),也僅僅是發(fā)送一條或多條 RPC 給數(shù)據(jù)中心的調(diào)度系統(tǒng)。
然而,這一過程顯然并不是瞬時完成的。比如,要檢查哪些機器掛掉了(機器健康檢查程序掛了怎么辦),以及在另外一些機器上重新運行任務(wù)(服務(wù)依賴重新部署重新調(diào)用任務(wù))都是需要花費一定時間的。
將程序轉(zhuǎn)移到另外一個機器上可能意味著損失一些存儲在老機器上的一些狀態(tài)信息(除非也采用動態(tài)遷移),重新調(diào)度運行的時間間隔也可能超過最小定義的一分鐘,所以,我們也必須考慮到上述這兩種情況。一個很直接的做法,將狀態(tài)文件放入分布式文件系統(tǒng),如 GFS,在任務(wù)運行的整個過程中以及重新部署運行任務(wù)時,都是用它來記錄使用相關(guān)狀態(tài)。 然而,這個解決方案卻不能滿足我們預(yù)期的時效性這個需求,比如,你要運行一個每五分鐘跑一次的 Cron 任務(wù),重新部署運行消耗的 1-2 分鐘對這個任務(wù)來說也是相當大的延遲了。
及時性的需求可能會促使各種熱備份技術(shù)的使用,這樣就能夠快速記錄狀態(tài)以及從原有狀態(tài)快速恢復(fù)。
需求擴展
將服務(wù)部署在數(shù)據(jù)中心和單服務(wù)器的另一個實質(zhì)性的區(qū)別是,如何規(guī)劃任務(wù)所需要的計算資源,如 CPU 或內(nèi)存等。
單機服務(wù)通常是通過進程來進行資源隔離,雖然現(xiàn)在 Docker 變得越來越普遍,但是使用它來隔離一切目前也不太是很通用的做法,包括限制crond以及它所要運行的任務(wù)。
大規(guī)模部署在數(shù)據(jù)中心經(jīng)常使用容器來進行資源隔離。隔離是必要的,因為我們肯定希望數(shù)據(jù)中心中運行的某個程序不會對其它程序產(chǎn)生不良影響。為了隔離的有效性,在運行前肯定得先預(yù)知運行的時候需要哪些資源——包括 Cron 系統(tǒng)本身和要運行的任務(wù)。這又會產(chǎn)生一個問題,即如果數(shù)據(jù)中心暫時沒有足夠的資源,那么這個任務(wù)可能會延遲運行。這就要求我們不僅要監(jiān)控 Cron 任務(wù)加載的情況,也要監(jiān)控 Cron 任務(wù)的全部狀態(tài),包括開始加載到終止運行。
現(xiàn)在,我們希望的 Cron 系統(tǒng)已經(jīng)從單機運行的情況下解耦,如之前描述的那樣,我們可能會遇到部分任務(wù)運行或加載失敗。這時候幸虧任務(wù)配置的通用性,在數(shù)據(jù)中心中運行一個新的 Cron 任務(wù)就可以簡單的通過 RPC 調(diào)用的方式來進行,不過不幸的是,這樣我們只能知道 RPC 調(diào)用是否成功,卻無法具體知道任務(wù)失敗的具體地方,比如,任務(wù)在運行的過程中失敗,那么恢復(fù)程序還必須將這些中間過程處理好。
在故障方面,數(shù)據(jù)中心遠比一臺單一的服務(wù)器復(fù)雜。Cron 從原來僅僅的一個單機二進制程序,到整個數(shù)據(jù)中心運行,其期間增加了很多明顯或不明顯的依賴關(guān)系。作為像 Cron 這樣的一個基礎(chǔ)服務(wù),我們希望得到保證的是,即使在數(shù)據(jù)中心中運行發(fā)生了一些 “Fail”(如,部分機器停電或存儲掛掉),服務(wù)依然能夠保證功能性正常運行。為了提高可靠性,我們應(yīng)該將數(shù)據(jù)中心的調(diào)度系統(tǒng)部署在不同的物理位置,這樣,即使一個或一部分電源掛掉,也能保證至少 Cron 服務(wù)不會全部不可用。
現(xiàn)在讓我們來解決這些問題,這樣才能在一個大規(guī)模的分布式集群中部署可靠的 Cron 服務(wù),然后在著重介紹下 Google 在分布式 Cron 方面的一些經(jīng)驗。
跟蹤 Cron 任務(wù)的狀態(tài)
向上面描述過的那樣,我們應(yīng)該跟蹤 Cron 任務(wù)的實時狀態(tài),這樣,即使失敗了,我們也更加容易恢復(fù)它。而且,這種狀態(tài)的一致性是至關(guān)重要的:相比錯誤的多運行 10 遍相同的 Cron 任務(wù),我們更能接受的是不去運行它。回想下,很多 Cron 任務(wù),它并不是冪等性的,比如發(fā)送通知郵件。
我們有兩個選項,將 Cron 任務(wù)的數(shù)據(jù)通通存儲在一個靠譜的分布式存儲中,或者僅僅保存任務(wù)的狀態(tài)。當我們設(shè)計分布式 Cron 服務(wù)時,我們采取的是第二種,有如下幾個原因:
分布式存儲,如 GFS 或 HDFS,往往用來存儲大文件(如 網(wǎng)頁爬蟲程序的輸出等),然后我們需要存儲的 Cron狀態(tài)卻非常非常小。將如此小的文件存儲在這種大型的分布式文件系統(tǒng)上是非常昂貴的,而且考慮到分布式文件系統(tǒng)的延遲,也不是很適合。
像 Cron 服務(wù)這種基礎(chǔ)服務(wù),它需要的依賴應(yīng)該是越少越好。這樣,即使部分數(shù)據(jù)中心掛掉,Cron 服務(wù)至少也能保證其功能性并持續(xù)一段時間。這并不意味著存儲應(yīng)該直接是 Cron 程序的一部分(這本質(zhì)上是一個實現(xiàn)細節(jié))。Cron 應(yīng)該是一個能夠獨立運作的下游系統(tǒng),以便供用戶操作使用。
使用 Paxos
我們部署多個實例的 Cron 服務(wù),然后通過 Paxos 算法來同步這些實例間的狀態(tài)。
Paxos 算法和它其它的替代算法(如 Zab,Raft 等)在分布式系統(tǒng)中是十分常見的。具體描述 Paxos 不在本文范圍內(nèi),它的基本作用就是使多個不可靠節(jié)點間的狀態(tài)保持一致,只要大部分 Paxos 組成員可用,那么整個分布式系統(tǒng),就能作為一個整體處理狀態(tài)的變化。
分布式 Cron 使用一個獨立的主任務(wù),見下圖,只有它才能更改共享的狀態(tài),也只有它才能加載 Cron 任務(wù)。我們這里使用了 Paxos 的一個變體—— Fast Paxos,這里 Fast Paxos 的主節(jié)點也是 Cron 服務(wù)的主節(jié)點。
如果主節(jié)點掛掉,Paxos 的健康檢查機制會在秒級內(nèi)快速發(fā)現(xiàn),并選舉出一個新的主節(jié)點。一旦選舉出新的主節(jié)點,Cron 服務(wù)也就隨著選舉出了一個新的 Cron 主節(jié)點,這個新的 Cron 主節(jié)點將會接手前一個主節(jié)點留下的所有的未完成的工作。在這里 Cron 的主節(jié)點和 Paxos 的主節(jié)點是一樣的,但是 Cron 的主節(jié)點需要處理一下額外的工作而已。快速選舉新的主節(jié)點的機制可以讓我們大致可以容忍一分鐘的故障時間。
我們使用 Paxos 算法保持的最重要的一個狀態(tài)是,哪些 Cron 任務(wù)在運行。對于每一個運行的 Cron 任務(wù),我們會將其加載運行的開始以及結(jié)束同步給一定數(shù)量的節(jié)點。
主節(jié)點和從節(jié)點角色
如上面描述的那樣,我們在 Cron 服務(wù)中使用 Paxos 并部署,其擁有兩個不同的角色,主節(jié)點以及從節(jié)點。讓我們來就每個角色來做具體的描述。
主節(jié)點
主節(jié)點用來加載 Cron 任務(wù),它有個內(nèi)部的調(diào)度系統(tǒng),類似于單機的crond,維護一個任務(wù)加載列表,在指定的時間加載任務(wù)。
當任務(wù)加載的時刻到來,主節(jié)點將會 “宣告” 它將會加載這個指定的任務(wù),并且計算這個任務(wù)下次的加載時間,就像?crond?的做法一樣。當然,就像?crond?那樣,一個任務(wù)加載后,下一次的加載時間可能人為的改變,這個變化也要同步給從節(jié)點。簡單的標識 Cron 任務(wù)還不夠,我們還應(yīng)該將這個任務(wù)與開始執(zhí)行時間相關(guān)聯(lián)綁定,以避免 Cron 任務(wù)在加載時發(fā)生歧義(特別是那些高頻的任務(wù),如一分鐘一次的那些)。這個“通告”通過 Paxos 來進行。下圖展示了這一過程。
保持 Paxos 通訊同步非常重要,只有 Paxos 法定數(shù)收到了加載通知,這個指定的任務(wù)才能被加載執(zhí)行。Cron 服務(wù)需要知道每個任務(wù)是否已經(jīng)啟動,這樣即使主節(jié)點掛掉,也能決定接下來的動作。如果不進行同步,意味著整個 Cron 任務(wù)運行在主節(jié)點,而從節(jié)點無法感知到這一切。如果發(fā)生了故障,很有可能這個任務(wù)就被再次執(zhí)行,因為沒有節(jié)點知道這個任務(wù)已經(jīng)被執(zhí)行過了。
Cron 任務(wù)的完成狀態(tài)通過 Paxos 通知給其它節(jié)點,從而保持同步,這里要注意一點,這里的“完成” 狀態(tài)并不是表示任務(wù)是成功或者失敗。我們跟蹤 Cron 任務(wù)在指定調(diào)用時間被執(zhí)行的情況,我們同樣需要處理一點情況是,如果 Cron 服務(wù)在加載任務(wù)進行執(zhí)行的過程中失敗后怎么辦,這點我們在接下來會進行討論。
主節(jié)點另一個重要的特性是,不管是出于什么原因主節(jié)點失去了其主控權(quán),它都必須立馬停止同數(shù)據(jù)中心調(diào)度系統(tǒng)的交互。主控權(quán)的保持對于訪問數(shù)據(jù)中心應(yīng)該是互斥了。如果不這樣,新舊兩個主節(jié)點可能會對數(shù)據(jù)中心的調(diào)度系統(tǒng)發(fā)起互相矛盾的操作請求。
從節(jié)點
從節(jié)點實時監(jiān)控從主節(jié)點傳來的狀態(tài)信息,以便在需要的時刻做出積極響應(yīng)。所有主節(jié)點的狀態(tài)變動信息,都通過 Paxos 傳到各個從節(jié)點。和主節(jié)點類似的是,從節(jié)點同樣維持一個列表,保存著所有的 Cron 任務(wù)。這個列表必須在所有的節(jié)點保持一致(當然還是通過 Paxos)。
當接到加載任務(wù)的通知后,從節(jié)點會將此任務(wù)的下次加載時間放入本地任務(wù)列表中。這個重要的狀態(tài)信息變化(這是同步完成的)保證了系統(tǒng)內(nèi)部 Cron 作業(yè)的時間表是一致的。我們跟蹤所有有效的加載任務(wù),也就是說,我們跟蹤任務(wù)何時啟動,而不是結(jié)束。
如果一個主節(jié)點掛掉或者因為某些原因失聯(lián)(比如,網(wǎng)絡(luò)異常等),一個從節(jié)點有可能被選舉成為一個新的主節(jié)點。這個選舉的過程必須在一分鐘內(nèi)運行,以避免 Cron 任務(wù)丟失的情況。一旦被選舉為主節(jié)點,所有運行的加載任務(wù)(或部分失敗的),必須被重新驗證其有效性。這個可能是一個復(fù)雜的過程,在 Cron 服務(wù)系統(tǒng)和數(shù)據(jù)中心的調(diào)度系統(tǒng)上都需要執(zhí)行這樣的驗證操作,這個過程有必要詳細說明。
故障恢復(fù)
如上所述,主節(jié)點和數(shù)據(jù)中心的調(diào)度系統(tǒng)之間會通過 RPC 來加載一個邏輯 Cron 任務(wù),但是,這一系列的 RPC 調(diào)用過程是有可能失敗的,所以,我們必須考慮到這種情況,并且處理好。
回想下,每個加載的 Cron 任務(wù)會有兩個同步點:開始加載以及執(zhí)行完成。這能夠讓我們區(qū)分開不同的加載任務(wù)。即使任務(wù)加載只需要調(diào)用一次 RPC,但是我們怎么知道 RPC 調(diào)用實際真實成功呢?我們知道任務(wù)何時開始,但是如果主節(jié)點掛了我們就不會知道它何時結(jié)束。
為了解決這個問題,所有在外部系統(tǒng)進行的操作,要么其操作是冪等性的(也就是說,我們可以放心的執(zhí)行它們多次),要么我們必須實時監(jiān)控它們的狀態(tài),以便能清楚的知道何時完成。
這些條件明顯增加了限制,實現(xiàn)起來也有一定的難度,但是在分布式環(huán)境中這些限制卻是保證 Cron 服務(wù)準確運行的根本,能夠良好的處理可能出現(xiàn)的 “fail”。如果不能妥善處理這些,將會導(dǎo)致 Cron 任務(wù)的加載丟失,或者加載多次重復(fù)的 Cron 任務(wù)。
大多數(shù)基礎(chǔ)服務(wù)在數(shù)據(jù)中心(比如 Mesos)加載邏輯任務(wù)時都會為這些任務(wù)命名,這樣方便了查看任務(wù)的狀態(tài),終止任務(wù),或者執(zhí)行其它的維護操作。解決冪等性的一個合理的解決方案是將執(zhí)行時間放在名字中?——這樣不會在數(shù)據(jù)中心的調(diào)度系統(tǒng)里造成任務(wù)異變操作 —— 然后在將它們分發(fā)給 Cron 服務(wù)所有的節(jié)點。如果 Cron 服務(wù)的主節(jié)點掛掉,那么新的主節(jié)點只需要簡單的通過預(yù)處理任務(wù)名字來查看其對應(yīng)的狀態(tài),然后加載遺漏的任務(wù)即可。
注意下,我們在節(jié)點間保持內(nèi)部狀態(tài)一致的時候,實時監(jiān)控調(diào)度加載任務(wù)的時間。同樣,我們也需要消除同數(shù)據(jù)中心調(diào)度交互時可能發(fā)生的不一致情況,所以這里我們以調(diào)度的加載時間為準。比如,有一個短暫但是頻繁執(zhí)行的 Cron 任務(wù),它已經(jīng)被執(zhí)行了,但是在準備把情況通告給其它節(jié)點時,主節(jié)點掛了,并且故障時間持續(xù)的特別長——長到這個 Cron 任務(wù)都已經(jīng)成功執(zhí)行完了。然后新的主節(jié)點要查看這個任務(wù)的狀態(tài),發(fā)現(xiàn)它已經(jīng)被執(zhí)行完成了,然后嘗試加載它。如果包含了這個時間,那么主節(jié)點就會知道,這個任務(wù)已經(jīng)被執(zhí)行過了,就不會重復(fù)執(zhí)行第二次。
在實際實施的過程中,狀態(tài)監(jiān)督是一個更加復(fù)雜的工作,它的實現(xiàn)過程和細節(jié)依賴與其它一些底層的基礎(chǔ)服務(wù),然而,上面并沒有包括相關(guān)系統(tǒng)的實現(xiàn)描述。根據(jù)你當前可用的基礎(chǔ)設(shè)施,你可能需要在冒險重復(fù)執(zhí)行任務(wù)和跳過執(zhí)行任務(wù)?之間做出折中選擇。
使用 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ù)器設(shè)置為 1000”來做替代。
如果日志丟失,我們也僅僅丟失當前狀態(tài)的一個快照而已。快照其實是最臨界的狀態(tài) —— 如果丟失了快照,我們基本上就得從頭開始了,因為我們丟失了上一次快照與丟失快照期間所有的內(nèi)部狀態(tài)。從另一方面說,丟失日志,也意味著,將 Cron 服務(wù)拉回到有記錄的上一次快照所標示的地方。
我們有兩個主要選擇來保存數(shù)據(jù): 存儲在外部的一個可用的分布式存儲服務(wù)中,或者,在內(nèi)部一個系統(tǒng)來存儲 Cron 服務(wù)的狀態(tài)。當我們設(shè)計系統(tǒng)時,這兩點都需要考慮。
我們將 Paxos 日志存儲在 Cron 服務(wù)節(jié)點所在服務(wù)器本地的磁盤中。默認的三個節(jié)點意味著,我們有三份日志的副本。我們同樣也將快照存儲在服務(wù)器本身,然而,因為其本身是非常重要的,我們也將它在分布式存儲服務(wù)中做了備份,這樣,即使小概率的三個節(jié)點機器都故障了,也能夠服務(wù)恢復(fù)。
我們并沒有將日志本身存儲在分布式存儲中,因為我們覺得,丟失日志也僅僅代表最近的一些狀態(tài)丟失,這個我們其實是可以接受的。而將其存儲在分布式存儲中會帶來一定的性能損失,因為它本身在不斷的小字節(jié)寫入不適用與分布式存儲的使用場景。同時三臺服務(wù)器全故障的概率太小,但是一旦這種情況發(fā)生了,我們也能自動的從快照中恢復(fù),也僅僅損失從上次快照到故障點的這部分而已。當然,就像設(shè)計 Cron 服務(wù)本身一樣,如何權(quán)衡,也要根據(jù)自己的基礎(chǔ)設(shè)施情況來決定。
將日志和快照存本地,以及快照在分布式存儲備份,這樣,即使一個新的節(jié)點啟動,也能夠通過網(wǎng)絡(luò)從其它已經(jīng)運行的節(jié)點處獲取這些信息。這意味著,啟動節(jié)點與服務(wù)器本身并沒有任何關(guān)系,重新安排一個新的服務(wù)器(比如重啟)來擔(dān)當某個節(jié)點的角色 其本質(zhì)上也是影響服務(wù)的可靠性的問題之一。
還有一些其它的、小型的,但是同樣有趣的一些情況或能影響部署一個大型的 Cron 服務(wù)。傳統(tǒng)的 Cron 規(guī)模很?。鹤疃喟瑪?shù)十個 Cron 任務(wù)。然而,如果在一個數(shù)據(jù)中心的超過千臺服務(wù)器來運行 Cron 服務(wù),那么你就會遇到各種各樣的問題。
一個比較大的問題是,分布式系統(tǒng)常常要面臨的一個經(jīng)典問題:驚群問題,在 Cron 服務(wù)的使用中會造成大量的尖峰情況。當要配置一個每天執(zhí)行的 Cron 任務(wù),大多數(shù)人第一時間想到的是在半夜執(zhí)行,然后它們就這么配置了。如果一個 Cron 任務(wù)在一臺機器上執(zhí)行,那沒有問題,但是如果你的任務(wù)是執(zhí)行一個涉及數(shù)千 worker 的 mapreduce 任務(wù),或者,有 30 個不同的團隊在數(shù)據(jù)中心中要配置這樣的一個每天運行的任務(wù),那么我們就必須要擴展下crontab的格式了。
傳統(tǒng)的crontab,用戶通過定義“分鐘”,“小時”,“每月(或每周)第幾天”,“月數(shù)”來指定 cron 任務(wù)運行的時間,或者通過星號(*)來代表每個對應(yīng)的值。如,每天凌晨運行,它的 crontab 格式為0 0 * * *,代表每天的 0 點 0 分運行。我們在此基礎(chǔ)之上還推出了問號(?)這個符號,它標示,在這個對應(yīng)的時間軸上,任何時間都可以,Cron 服務(wù)就會自由選擇合適的值,在指定的時間段內(nèi)隨機選擇對應(yīng)的值,這樣使任務(wù)運行更均衡。如?0 ? * * *,表示每天 0-23 點鐘,隨機一個小時的 0 分來運行這個任務(wù)。
盡管加了這項變化,由 Cron 任務(wù)所造成的 load 值仍然有明顯的尖峰,下圖表示了 Google 中 cron 任務(wù)加載的數(shù)量。尖峰值往往表示那些需要固定頻率在指定時間運行的任務(wù)。
Cron 服務(wù)作為 UNIX 的基礎(chǔ)服務(wù)已經(jīng)有接近 10 年。當前整個行業(yè)都朝著大型分布式系統(tǒng)演化,那時,表示硬件的最小單位將會是數(shù)據(jù)中心,那么大量的技術(shù)棧需要對應(yīng)改變,Cron 也不會是例外。仔細審視下 Cron 服務(wù)所需要的服務(wù)特性,以及 Cron 任務(wù)的需求,都會推動我們來進行新的設(shè)計。
基于 Google 的解決方案,我們已經(jīng)討論了 Cron 服務(wù)在一個分布式系統(tǒng)中對應(yīng)的約束和可能的設(shè)計。這個解決方案需要在分布式環(huán)境中的強一致性保證,它的實現(xiàn)核心是通過 Paxos 這樣一種通用的算法,在一個不可靠的環(huán)境中達成最終一致。使用 Paxos,正確對大規(guī)模環(huán)境下 Cron 任務(wù)失敗情況的分析,以及分布式的環(huán)境的使用,共同造就了在 Google 內(nèi)部使用的健壯的 Cron 服務(wù)。
原文來自:https://linux.cn:443/article-7860-1.html
本文地址:http://www.linuxprobe.com/stable-cron-service.html編輯:楊帆,審核員:馮琪
《Linux就該這么學(xué)》是由資深運維專家劉遄及全國多名紅帽架構(gòu)師(RHCA)基于最新RHEL7系統(tǒng)共同編寫的高質(zhì)量Linux技術(shù)自學(xué)教程,極其適合用于Linux技術(shù)入門教程或講課輔助教材。
? 劉遄老師QQ:5604241
? 學(xué)員助教QQ:5604674
? Linux技術(shù)交流A群(滿):560843
? Linux技術(shù)交流B群:340829
? Linux技術(shù)交流C群:463590
? 官方站點:www.linuxprobe.com
? 電腦在線閱讀效果更佳:
http://www.linuxprobe.com/chapter-00.html
按住圖片3秒,即可自動關(guān)注。
點擊左下角查看更多熱門技術(shù)