Google
經歷的三代資源調度器的架構,分別是中央式調度器架構(類似於 Hadoop JobTracker
,但是支持多種類型作業調度)、雙層調度器架構(類似於 Apache Mesos 和 Hadoop YARN )和共享狀態架構(就是Omega
)。
2.1 中央式調度(Monolithic schedulers)
在同一個代碼模塊中實現調度策略,單個實例,沒有並行。Hadoop1,MapReduce 的宏調度架構如下圖所示。
常見於HPC(high-performancecomputing)世界中。【不了解 HPC】
master進程
的 JobTracker
是一個所有 MapReduce
任務的中心調度器。每一個 node
上面都運行一個 TaskTracker
進程來管理各自 node
上的任務進入。TaskTracker
要和 master
上 JobTracker
通信並接受 JobTracker
的控制。
以 JobTracker
為例,資源的調度和作業的管理功能全部放到一個進程中完成。這種設計方式的缺點是擴展性差:
- 首先,集群規模受限
- 其次,新的調度策略難以融入現有代碼中,比如之前僅支持
MapReduce
作業,現在要支持流式作業,而將流式作業的調度策略嵌入到中央式調度器中是一項很難的工作
Omega
論文中提到了一種對中央式調度器的優化方案:將每種調度策略放到單獨一個路徑(模塊)中,不同的作業由不同的調度策略進行調度。這種方案在作業量和集群規模比較小時,能大大縮短作業相應時間,但由於所有調度策略仍在一個集中式的組件中,整個系統擴展性沒有變得更好。
2.1.1 靜態分區(Statically partitioned schedulers)
中央式調度是靜態資源分區調度方式。也被成為雲計算中的調度,資源集合的全面控制。部署在專門的,靜態划分的集群的一個子集上。或者把集群划分為不同的部分,分別支持不同的行為。
靜態資源划分
優點:簡單,固定的硬件資源給固定的計算框架使用,各個框架各行其是,互不干擾。
缺點:整體資源利用率不高,經常出現集群計算系統資源不足。
2.1.2 動態資源管理抽象模型
資源管理與調度系統:YARN
、Mesos
、Corona
、Quincy
,從上述系統抽象兩個模型:
動態資源管理與調度的概念模型
概念模型 三要素:
- 資源組織模型:組織起來方便分配,如
all resource->group->pool
三級隊列,或平級多隊列或單隊列等 - 調度算法:熟知的
FIFO
、公平調度、能力調度、延遲調度等,說白了就是按照什么方式分配資源 - 任務組織:
job
分配,比如全局隊列、機架隊列、節點隊列等。說白了就是如何把任務組織起來
動態資源管理通用架構
- 每台機器都有節點管理器,負責收集它所在機器的資源使用情況,分配的任務放到不同容器執行,彼此隔離開,避免
job
彼此干擾。在這里它要給 資源收集器 匯報任務,這個 收集器 在把相關的信息反應給 資源池,資源池列出目前可用的資源。 - 通用調度器構成:資源收集器、資源調度策略,資源池,工作隊列。
- 調度策略:FIFO、公平調度、能力調度等,在這里系統應用者可根據具體情況設定符合業務狀況的調度策略,當用戶新提交作業時,其進入工作隊列,等着分配使其可啟動的資源。在這里系統應用者可根據具體情況設定符合業務狀況的調度策略,當用戶新提交作業時,其進入工作隊列,等着分配使其可啟動的資源。
動態與靜態對比
- 動態會根據任務即時需要分配資源,不會出現資源閑置且不可用,也不會出現任務忙且不可得資源的尷尬局面。總之增加資源利用率,降低硬件成本。
- 增加數據共享能力,共用的資源存儲一份就行啦,
- 說白了就是支持多類型計算框架和多版本計算框架,使用資源管理與調度平台可以實現兩者平滑切換,給運營帶來便利。
2.2 兩層調度(Two-level scheduling)
為了解決中央式調度器的不足,雙層調度器是一種很容易想到的解決之道(實際上是分而治之策略或者是策略下放機制)。雙層調度器仍保留一個經簡化的中央式調度器,但調度策略下放到各個應用程序調度器完成。這種調度器的典型代表是 Apache Mesos 和 Hadoop YARN。
各個框架調度器並不知道整個集群資源使用情況,只是被動的接收資源。Master
僅將可用的資源推送給各個框架,而框架自己選擇使用還是拒絕這些資源。一旦框架(比如 JobTracker
)接收到新資源后,再進一步將資源分配給其內部的各個應用程序(各個 MapReduce
作業),進而實現雙層調度。
兩層調度器有兩個缺點:
-
各個框架無法知道整個集群的實時資源使用情況;
很多框架不需要知道整個集群的實時資源使用情況就可以運行的很順暢,但是對於其他一些應用,為之提供實時資源使用情況可以為之提供潛在的優化空間,比如,當集群非常繁忙時,一個服務失敗了,是選擇換一個節點重新運行它呢,還是繼續在這個節點上運行?通常而言,換一個節點可能會更有利,但是,如果此時集群非常繁忙,所有節點只剩下小於
5GB
的內存,而這個服務需要10GB
內存,那么換一個節點可能意味着長時間等待資源釋放,而這個等待時間是無法確定的。 -
采用悲觀鎖,並發粒度小。
在數據庫領域,悲觀鎖與樂觀鎖爭論一直不休,悲觀鎖通常采用鎖機制控制並發,這會大大降低性能,而樂觀鎖則采用多版本並發控制(
MVCC
,Multi-Version Concurrency Control
),典型代表是MySQL innoDB
,這種機制通過多版本方式控制並發,可大大提升性能。例如,在Mesos
中,在任意一個時刻,Mesos
資源調度器只會將所有資源推送給任意一個框架,等到該框架返回資源使用情況后,才能夠將資源推動給其他框架,因此,Mesos
資源調度器中實際上有一個全局鎖,這大大限制了系統並發性。
備注:
悲觀鎖,總是假設最壞的情況,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。再比如
Java
里面的同步原語synchronized
關鍵字的實現也是悲觀鎖。樂觀鎖,顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫提供的類似於
write_condition
機制,其實都是提供的樂觀鎖。
2.2.1 YARN
背景
YARN
被稱之為 Apache Hadoop Next Generation Compute Platform
,是 hadoop1
和 hadoop2
之間最大的區別:
設計思想
Hadoop2
(MRv2
)的基礎思想就是把 JobTracker
的功能划分成兩個獨立的進程:全局的資源管理Resource Manager
和每個進程的監控和調度 Application Master
。 這個進程可以是 Map-Reduce
中一個任務或者是DAG
中一個任務。
Hadoop2
(MRv2
)的 API
是后向兼容的,支持 Map-Reduce
的任務只需要重新編譯一下就可以運行在Hadoop2
(MRv2
)上。
架構說明
在 YARN
的設計中, 集群中可以有多個 Application Masters
,每一個 ApplicationMasters
可以有多個Containers
(例如,圖中有兩個 Application Masters
,紅色和藍色。紅色的有三個 containers
,藍色的有一個 container
)。關鍵的一點是 Application Masters
不是 Resource Manager
的部分,這就減輕了中心調度器的壓力,並且,每一個 Application Masters
都可以動態的調整自己控制的 container
。
而 Resource Manager
是一個純粹的調度器(不監控和追蹤進程的執行狀態,也不負責重啟故障的進程),它唯一的目的就是在多個應用之間管理可用的資源(以 Containers
的粒度)。Resource Manager
是資源分配的終極權威。如果說 Resource Manager
是 master
,NodeManager
就是其 slave
。Resource Manager
並且支持調度策略的插件化:Capacity Scheduler
和 Fair Scheduler
就是這樣的插件。
Application Master
負責任務提交,通過協商和談判從 Resource Manager
那里以 Containers
的形式獲得資源(負責談判獲得適合其應用需要的 Containers
)。然后就 track
進程的運行狀態。Application Masters
是特定於具體的應用,可以根據不同的應用來編寫不同的 Application Masters
。另外,Application Master
提供自動重啟的服務。Application Master
可以理解為應用程序可以自己實現的接口庫。
Application Masters
請求和管理 Containers
。Containers
指定了一個應用在某一台主機上可以使用多少資源(包括 memory
,CPU
等)。Application Master
一旦從 Resource Manager
那里獲得資源,它就會聯系 Node Manager
來啟動某個特定的任務。例如如果使用 MapReduce
框架,這些任務可能就是 mapper
和 reducer
進程。不同的框架會有不同的進程。
Node Manager
是每一個機器上框架代理,負責該機上的 Containers
,並且監控可用的資源(CPU
,memory
,disk
,network
)。並且資源狀態報告給 Resource Manager
。
小結
YARN
是一個兩層調度,在 YARN
中,資源請求從 application masters
發出到一個中心的全局調度器上,中心調度器根據應用的需要在集群中的多個節點上分配資源。截止目前,YARN
只支持 CPU
和內存的調度。
2.2.2 Mesos
背景
大量分布式計算框架的出現:Hadoop
,Giraph
,MPI
,etc
。每一個計算框架管理自己的計算集群。這些應用框架往往把任務分割成很多小任務從而可以提高集群的利用率,讓計算靠近數據。但是這些框架都是獨立開發的,不可能在應用框架之間共享資源。形象的表示如下:
我們希望在同一個集群上可以運行多個應用框架。Mesos
是通過提供一個通用資源共享層,多個不同的應用框架可以運行在這個資源共享層之上。形象的表示如下:
但我們不希望使用簡單的靜態分區的方法(如下左圖):
優勢與挑戰
Mesos
好處如下:
- 最大的好處就是提高集群的利用率。
- 可以很好的隔離產品環境和實驗環境,可以同時並發運行多個框架。
- 可以在多個集群之間共享數據。
- 可以降低
Maintenance
成本。
Mesos
最大挑戰是如何支持大量的應用框架。因為每一個框架都有不同的調度需求:編程模型,通信范型,任務依賴和數據放置。另外 Mesos
的調度系統需要能夠擴展到數千個節點,運行數百萬個任務。由於集群中的所有任務都依賴於 Mesos
,調度系統必須是容錯和高可用的。
設計思想
Mesos
的設計決策:不采用中心化的、設計周全的(應用需求,可用資源,組織策略),適用於所有任務的全局調度策略;而采用委派調度任務給應用框架(把調度和執行的功能交給應用框架)。Mesos
聲稱:這樣的設計策略可能不會達到全局最優的調度,但在實際運行中出奇的好,可以使得應用框架的近乎完美的達到目標。還聲稱其優點有兩個:
- 應用框架的演化獨立。
- 保持
mesos
的簡潔。
架構說明
Mesos
的主要組件包括 master daemon
,slave daemons
和在 slaves
之上運行的 mesos applications
(也被稱為 frameworks
)。Master
根據相應的策略(公平調度,優先級調度等)決定給每一個應用分配多少資源。模塊化架構支持多種策略。
Resource offer
是資源的抽象表示,基於該資源,應用框架可以在集群中的某個 node
上實例化分配 offer
,並運行任務。每一個 Resource offer
就是一個分布在多個 node
上的空閑資源列表。Mesos
基於一定的算法策略(如公平調度)決定有多少資源可以分配給應用框架,而應用框架決定使用(接受)哪些資源,運行哪些任務。Mesos
上運行的應用框架由兩部分組成:應用調度器和 slave
上運行的代理。
應用調度器向 Mesos
注冊。Master
決定向注冊的框架提供多少資源,應用調度器決定 master
分配的資源中哪些來使用。調度完成之后,應用調度器把接受的資源發送給 Mesos
,從而決定了使用哪些 slave
。然后應用框架中的任務可以在 slave
上運行。當任務很小並且是短期任務(每個任務都頻繁的讓渡自己握着的資源的時候),Mesos
工作的很好。
在 Mesos
中,一個中央資源分配器動態的划分集群,分配資源給不同的調度框架(scheduler frameworks
)。資源可以在不同的調度框架之間以 “offers”
的形式任意分配,offers
表示了當前可用的資源。資源分配器為了避免不同調度框架對同一資源沖突申請,只允許一次只能分配給一個調度框架。在調度決策的過程中,資源分配器實質上起到了鎖的作用。因此 Mesos
中的並發調度是悲觀策略的。
Master
使用 resource offer
機制在多個框架之間細粒度的共享資源。每一個 resource offer
空閑資源列表,分布在多個 slave
上。Master
決定給每一個應用框架提供多少資源,依據是公平方法或者優先級方法(調度策略,可插拔的方式)。
Reject
機制:駁回 mesos
提供的資源方案。為了保持接口的簡單性,Mesos
不允許應用框架指定資源需求的限制信息,而是允許應用框架拒絕 mesos
提供的資源方案。應用框架如果遇到沒有滿足其需求的資源提供方案,則會拒絕等待。Mesos
聲稱拒絕機制可以支持任意復雜的資源限制,同時保持擴展性和簡單。
Reject
機制帶來的一個問題是在應用框架收到一個滿足其需求的方案之前可能需要等待很長時間。由於不知道應用框架的需求,mesos
可能會把同一個資源方案發給多個應用框架。因此,引入 fliter
機制:Mesos
中的一個調度框架使用 filter
來描述它期望被服務的資源類型(允許應用框架設置一個 filter
表示該應用框架會永遠的拒絕某類資源)。因此,它不需要訪問整個集群,它只需要訪問它被 offer
的節點即可。這種策略帶來的缺點是不能支持基於整個集群狀態的搶占和策略:一個調度框架不知道分配給其他調度框架的資源。Mesos
提供了一種資源儲存的策略來支持 gang
調度。例如,應用框架可以指定一個其可以運行 node
白名單列表。這不是動態的集群分區嗎?Mesos
進一步解釋 filter
機制:filter
只是一個資源分配模型的性能優化方案,應用框架有哪些任務運行在哪些 node
上最終決定權。
gang 調度:
作業的所有任務要么一起調度,要么沒有,調度器必須嘗試重新調度整個作業。
任務調度過程
Slave 1
向master
匯報它有4個CPUs
和4 GB
的空閑內存,master
的allocation
模塊會根據相應的分配策略通知framework 1
可以使用所有可用資源。master
把slave 1
上的可用資源發送給framework 1
(以resource offer
的方式)。framework
的調度器響應master
調度器,准備在slave
上運行兩個任務,使用的資源分別是:第一個任務<2 CPUs, 1 GB RAM>
,第二個任務<1 CPUs, 2 GB RAM>
。- 最后,
master
把任務發送給slave
,然后把相應的資源分配給framework
的執行器。然后執行器啟動兩個任務 。由於slave1
上還有1 CPU
和1 GB
的內存沒有分配,分配模塊可以把資源分配給framework 2
。
另外 Mesos master
的 Allocation module
是 pluggable
。使用 ZooKeeper
來實現 mesos master
的Failover
。
2.3 狀態共享調度(Shared-state scheduling)
每一個調度器都可以訪問整個集群狀態。當多個調度器同時更新集群狀態時使用樂觀鎖並發控制。Shared-state
調度可以解決兩層調度的兩個問題:悲觀並發控制所帶來的並行限制和調度框架對整個集群資源的可見性。
樂觀並發控制所帶來的問題是當樂觀假設不成立時,需要重新調度。
為了克服雙層調度器的以上兩個缺點(Omega paper
主要關注了這個問題),Google
開發了下一代資源管理系統 Omega
,Omega
是一種基於共享狀態的調度器,該調度器將雙層調度器中的集中式資源調度模塊簡化成了一些持久化的共享數據(狀態)和針對這些數據的驗證代碼,而這里的 共享數據
實際上就是整個集群的實時資源使用信息。一旦引入共享數據后,共享數據的並發訪問方式就成為該系統設計的核心,而 Omega
則采用了傳統數據庫中基於多版本的並發訪問控制方式(也稱為 樂觀鎖
,MVCC
,Multi-Version ConcurrencyControl
),這大大提升了 Omega
的並發性。在 Omega
中沒有中心的資源分配器,調度器自己作出資源分配的決策。
2.3.1 Omega
背景
中央式調度的缺點是難以增加調度策略和專門的實現,並且不能隨着集群的擴展而擴展。兩層調度確實可以提供靈活性和並行性,但是在實踐中他們的資源可見性卻是保守的,難以適應一些挑剔型的任務和一些需要訪問整個集群資源的任務。為了克服雙層調度器的缺點,Google
開發了下一代資源管理系統 Omega
設計思想
由於 Omega
不再有集中式的調度模塊,因此,不能像 Mesos
或者 YARN
那樣,在一個統一模塊中完成以下功能:對整個集群中的所有資源分組,限制每類應用程序的資源使用量,限制每個用戶的資源使用量等,這些全部由各個應用程序調度器自我管理和控制。
根據論文所述,Omega
只是將優先級這一限制放到了共享數據的驗證代碼中,即當同時由多個應用程序申請同一份資源時,優先級最高的那個應用程序將獲得該資源,其他資源限制全部下放到各個子調度器。
引入多版本並發控制后,限制該機制性能的一個因素是資源訪問沖突的次數,沖突次數越多,系統性能下降的越快,而 google
通過實際負載測試證明,這種方式的沖突次數是完全可以接受的。
Omega
論文中談到,Omega
是從Omega
的調度器架構,我們可推測它的整體架構類似於Mesos
,這樣,如果你了解Mesos
,那么可知道,我們可以通過僅修改Mesos
的Master
將之改造成一個Omega
。
架構說明
Omega
中沒有中心的資源分配器,所有的資源分配決策都是由應用的調度器自己完成的。Omega
維護了一個稱為 cell state
的資源分配狀態信息主拷貝。每一個應用的調度器都維護了一個本地私有的,頻繁更新的 cell state
拷貝,用來做調度決策。調度器可以看到全局的所有資源,並根據權限和優先級來自以為是的要求需要的資源。當調度器決定資源方案時,以原子的方式更新共享的 cell state
:大多數時候這樣 commit
將會成功(這就是樂觀方法)。當沖突發生時,調度決策將會以事務的方式失敗。無論調度成功還是失敗,調度器都會重新同步本地的 cell state
和共享的 cell state
。然后,如果需要,重啟調度過程。
Omega
的調度器完全是並行的,不需要等待其他調度器。為了避免沖突造成的飢餓,omega
調度器使用增量調度 —— 除了沖突的資源,其他都接受
,這樣可以避免資源囤積。如果使用 all or nothing
的策略可以使用 gang
調度。gang
調度要等待所有資源就緒,才 commit
整個任務,就造成了資源囤積。
每一個應用調度器都可以實現自己的調度策略。但是它們必須就資源分配和任務的優先級達成一致。兩層調度中中心資源管理器可以輕松實現這一點。公平性不是一個關鍵需求,只是滿足自己的業務需求。因此,需要限制每一個應用調度器資源上限和任務提交上限。
2.4 小結
集群調度的主要目標是提高集群的利用率和使用效率。
- Monolithic schedulers
為所有任務都使用一個中心調度算法。其缺點是不易增加新的調度策略,也不能隨着集群的擴展而擴展。
- Two-level schedulers
使用一個動態資源管理器提供計算資源或者存儲資源給到多個並行的調度框架。每一個調度框架所擁有的都是一個整個資源的一個子集。為什么是一個動態資源管理器呢?是相對於靜態的集群分區來說的。我們可以靜態的把集群分為幾個區,分別服務於不同的應用。上面的動態資源管理器完成工作就是把靜態的分區工作動態化。由於兩層調度無法處理難以調度的挑剔任務,且不能根據整個集群的狀態做出決策,google
引入下面的調度架構。
- Shared-state schedulers
使用無鎖的樂觀並發控制算法。那么對比起來,Two-level schedulers
本質上是悲觀調度算法。Omega
,google
的下一代調度系統中使用了該架構。
在 omega
看來,mesos
的 offer
的機制本質上是一個動態的過濾機制,這樣 mesos master
向應用框架提供的只是一個資源池的子集。當然可以把這個子集擴大為一個全集,也是 share state
的,但其接口依然是悲觀策略的。
附錄:參考資料
YARN中FIFO、Capacity以及Fari調度器的詳細介紹