Ceph是統一分布式存儲系統,具有優異的性能、可靠性、可擴充性。Ceph的底層是RADOS(可靠、自動、分布式對象存儲),可以通過 LIBRADOS直接通路到RADOS的對象存儲系統。RBD(塊裝置接口)、RADOS Gateway(對象存儲接口)、Ceph File System(POSIX接口)都是基于RADOS的。
Ceph存儲系統的邏輯層次結構如下圖所示:
自下向上,可以将Ceph系統分為四個層次:
(1)基礎存儲系統RADOS(Reliable, Autonomic,Distributed Object Store,即可靠的、自動化的、分布式的對象存儲)
顧名思義,這一層本身就是一個完整的對象存儲系統,所有存儲在Ceph系統中的使用者資料事實上最終都是由這一層來存儲的。而Ceph的高可靠、高可擴充、高性能、高自動化等等特性本質上也是由這一層所提供的。是以,了解RADOS是了解Ceph的基礎與關鍵。實體上,RADOS由大量的儲存設備節點組層,每個節點擁有自己的硬體資源(CPU、記憶體、硬碟、網絡),并運作着作業系統和檔案系統。
(2)基礎庫librados
這一層的功能是對RADOS進行抽象和封裝,并向上層提供API,以便直接基于RADOS(而不是整個Ceph)進行應用開發。特别要注意的是,RADOS是一個對象存儲系統,是以,librados實作的API也隻是針對對象存儲功能的。RADOS采用C++開發,所提供的原生librados API包括C和C++兩種。實體上,librados和基于其上開發的應用位于同一台機器,因而也被稱為本地API。應用調用本機上的librados API,再由後者通過socket與RADOS叢集中的節點通信并完成各種操作。
(3)高層應用接口
這一層包括了三個部分:RADOS GW(RADOS Gateway)、 RBD(Reliable Block Device)和Ceph FS(Ceph File System),其作用是在librados庫的基礎上提供抽象層次更高、更便于應用或用戶端使用的上層接口。其中,RADOS GW是一個提供與Amazon S3和Swift相容的RESTful API的gateway,以供相應的對象存儲應用開發使用。RADOS GW提供的API抽象層次更高,但功能則不如librados強大。是以,開發者應針對自己的需求選擇使用。RBD則提供了一個标準的塊裝置接口,常用于在虛拟化的場景下為虛拟機建立volume。目前,Red Hat已經将RBD驅動內建在KVM/QEMU中,以提高虛拟機通路性能。Ceph FS是一個POSIX相容的分布式檔案系統。由于還處在開發狀态,因而Ceph官網并不推薦将其用于生産環境中。
(4)應用層
這一層就是不同場景下對于Ceph各個應用接口的各種應用方式,例如基于librados直接開發的對象存儲應用,基于RADOS GW開發的對象存儲應用,基于RBD實作的雲硬碟等等。在上文的介紹中,有一個地方可能容易引起困惑:RADOS自身既然已經是一個對象存儲系統,并且也可以提供librados API,為何還要再單獨開發一個RADOS GW?
了解這個問題,事實上有助于了解RADOS的本質,是以有必要在此加以分析。粗看起來,librados和RADOS GW的差別在于,librados提供的是本地API,而RADOS GW提供的則是RESTfulAPI,二者的程式設計模型和實際性能不同。而更進一步說,則和這兩個不同抽象層次的目标應用場景差異有關。換言之,雖然RADOS和S3、Swift同屬分布式對象存儲系統,但RADOS提供的功能更為基礎、也更為豐富。這一點可以通過對比看出。
由于Swift和S3支援的API功能近似,這裡以Swift舉例說明。Swift提供的API功能主要包括:
使用者管理操作:使用者認證、擷取賬戶資訊、列出容器清單等;
容器管理操作:建立/删除容器、讀取容器資訊、列出容器内對象清單等;
對象管理操作:對象的寫入、讀取、複制、更新、删除、通路許可設定、中繼資料讀取或更新等。
由此可見,Swift(以及S3)提供的API所操作的“對象”隻有三個:使用者賬戶、使用者存儲資料對象的容器、資料對象。并且,所有的操作均不涉及存儲系統的底層硬體或系統資訊。不難看出,這樣的API設計完全是針對對象存儲應用開發者和對象存儲應用使用者的,并且假定其開發者和使用者關心的内容更偏重于賬戶和資料的管理,而對底層存儲系統細節不感興趣,更不關心效率、性能等方面的深入優化。
而librados API的設計思想則與此完全不同。一方面,librados中沒有賬戶、容器這樣的高層概念;另一方面,librados API向開發者開放了大量的RADOS狀态資訊與配置參數,允許開發者對RADOS系統以及其中存儲的對象的狀态進行觀察,并強有力地對系統存儲政策進行控制。換言之,通過調用librados API,應用不僅能夠實作對資料對象的操作,還能夠實作對RADOS系統的管理和配置。這對于S3和Swift的RESTfulAPI設計是不可想像的,也是沒有必要的。
基于上述分析對比,不難看出,librados事實上更适合對于系統有着深刻了解,同時對于功能定制擴充和性能深度優化有着強烈需求的進階使用者。基于librados的開發可能更适合于在私有Ceph系統上開發專用應用,或者為基于Ceph的公有存儲系統開發背景資料管理、處理應用。而RADOS GW則更适合于常見的基于web的對象存儲應用開發,例如公有雲上的對象存儲服務。
########################################################################################################################
RADOS的系統邏輯結構如下圖所示
<a href="http://s1.51cto.com/wyfs02/M01/82/9E/wKioL1ddFY2ChmK3AABoRunbpzI131.jpg" target="_blank"></a>
在使用RADOS系統時,大量的用戶端程式通過與OSD或者monitor的互動擷取clustermap,然後直接在本地進行計算,得出對象的存儲位置後,便直接與對應的OSD通信,完成資料的各種操作。可見,在此過程中,隻要保證clustermap不頻繁更新,則用戶端顯然可以不依賴于任何中繼資料伺服器,不進行任何查表操作,便完成資料通路流程。在RADOS的運作過程中,cluster map的更新完全取決于系統的狀态變化,而導緻這一變化的常見事件隻有兩種:OSD出現故障,或者RADOS規模擴大。而正常應用場景下,這兩種事件發生的頻率顯然遠遠低于用戶端對資料進行通路的頻率。
根據定義,OSD可以被抽象為兩個組成部分,即系統部分和守護程序(OSDdeamon)部分。
OSD的系統部分本質上就是一台安裝了作業系統和檔案系統的計算機,其硬體部分至少包括一個單核的處理器、一定數量的記憶體、一塊硬碟以及一張網卡。
由于這麼小規模的x86架構伺服器并不實用(事實上也見不到),因而實際應用中通常将多個OSD集中部署在一台更大規模的伺服器上。在選擇系統配置時,應當能夠保證每個OSD占用一定的計算能力、一定量的記憶體和一塊硬碟。同時,應當保證該伺服器具備足夠的網絡帶寬。具體的硬體配置選擇可以參考。
在上述系統平台上,每個OSD擁有一個自己的OSD deamon。這個deamon負責完成OSD的所有邏輯功能,包括與monitor和其他OSD(事實上是其他OSD的deamon)通信以維護更新系統狀态,與其他OSD共同完成資料的存儲和維護,與client通信完成各種資料對象操作等等。
Ceph系統的邏輯結構就介紹到這裡。下篇文章将着重說明Ceph(主要是RADOS)的工作原理和操作流程。
如圖所示,RADOS叢集主要由兩種節點組成。一種是為數衆多的、負責完成資料存儲和維護功能的OSD(Object Storage Device),另一種則是若幹個負責完成系統狀态檢測和維護的monitor。OSD和monitor之間互相傳輸節點狀态資訊,共同得出系統的總體工作狀态,并形成一個全局系統狀态記錄資料結構,即所謂的cluster map。這個資料結構與RADOS提供的特定算法相配合,便實作了Ceph“無需查表,算算就好”的核心機制以及若幹優秀特性。
本節将對Ceph的工作原理和若幹關鍵工作流程進行扼要介紹。如前所述,由于Ceph的功能實作本質上依托于RADOS,因而,此處的介紹事實上也是針對RADOS進行。對于上層的部分,特别是RADOS GW和RBD,由于現有的文檔中(包括Sage的論文中)并未詳細介紹,還請讀者多多包涵。
首先介紹RADOS中最為核心的、基于計算的對象尋址機制,然後說明對象存取的工作流程,之後介紹RADOS叢集維護的工作過程,最後結合Ceph的結構和原理對其技術優勢加以回顧和剖析。
Ceph系統中的尋址流程如下圖所示:
<a href="http://s5.51cto.com/wyfs02/M00/82/9E/wKioL1ddFayyR7WjAABGDU_wFPM713.jpg" target="_blank"></a>
上圖左側的幾個概念說明如下:
1. File —— 此處的file就是使用者需要存儲或者通路的檔案。對于一個基于Ceph開發的對象存儲應用而言,這個file也就對應于應用中的“對象”,也就是使用者直接操作的“對象”。
2. Ojbect —— 此處的object是RADOS所看到的“對象”。Object與上面提到的file的差別是,object的最大size由RADOS限定(通常為2MB或4MB),以便實作底層存儲的組織管理。是以,當上層應用向RADOS存入size很大的file時,需要将file切分成統一大小的一系列object(最後一個的大小可以不同)進行存儲。為避免混淆,在本文中将盡量避免使用中文的“對象”這一名詞,而直接使用file或object進行說明。
3. PG(Placement Group)—— 顧名思義,PG的用途是對object的存儲進行組織和位置映射。具體而言,一個PG負責組織若幹個object(可以為數千個甚至更多),但一個object隻能被映射到一個PG中,即,PG和object之間是“一對多”映射關系。同時,一個PG會被映射到n個OSD上,而每個OSD上都會承載大量的PG,即,PG和OSD之間是“多對多”映射關系。在實踐當中,n至少為2,如果用于生産環境,則至少為3。一個OSD上的PG則可達到數百個。事實上,PG數量的設定牽扯到資料分布的均勻性問題。關于這一點,下文還将有所展開。
4. OSD —— 即object storage device,前文已經詳細介紹,此處不再展開。唯一需要說明的是,OSD的數量事實上也關系到系統的資料分布均勻性,是以其數量不應太少。在實踐當中,至少也應該是數十上百個的量級才有助于Ceph系統的設計發揮其應有的優勢。
基于上述定義,便可以對尋址流程進行解釋了。具體而言,Ceph中的尋址至少要經曆以下三次映射:
1. File -> object映射
這次映射的目的是,将使用者要操作的file,映射為RADOS能夠處理的object。其映射十分簡單,本質上就是按照object的最大size對file進行切分,相當于RAID中的條帶化過程。這種切分的好處有二:一是讓大小不限的file變成最大size一緻、可以被RADOS高效管理的object;二是讓對單一file實施的串行處理變為對多個object實施的并行化處理。
每一個切分後産生的object将獲得唯一的oid,即object id。其産生方式也是線性映射,極其簡單。圖中,ino是待操作file的中繼資料,可以簡單了解為該file的唯一id。ono則是由該file切分産生的某個object的序号。而oid就是将這個序号簡單連綴在該file id之後得到的。舉例而言,如果一個id為filename的file被切分成了三個object,則其object序号依次為0、1和2,而最終得到的oid就依次為filename0、filename1和filename2。
這裡隐含的問題是,ino的唯一性必須得到保證,否則後續映射無法正确進行。
2. Object -> PG映射
在file被映射為一個或多個object之後,就需要将每個object獨立地映射到一個PG中去。這個映射過程也很簡單,如圖中所示,其計算公式是:
hash(oid) & mask ->pgid
由此可見,其計算由兩步組成。首先是使用Ceph系統指定的一個靜态哈希函數計算oid的哈希值,将oid映射成為一個近似均勻分布的僞随機值。然後,将這個僞随機值和mask按位相與,得到最終的PG序号(pgid)。根據RADOS的設計,給定PG的總數為m(m應該為2的整數幂),則mask的值為m-1。是以,哈希值計算和按位與操作的整體結果事實上是從所有m個PG中近似均勻地随機選擇一個。基于這一機制,當有大量object和大量PG時,RADOS能夠保證object和PG之間的近似均勻映射。又因為object是由file切分而來,大部分object的size相同,因而,這一映射最終保證了,各個PG中存儲的object的總資料量近似均勻。
從介紹不難看出,這裡反複強調了“大量”。隻有當object和PG的數量較多時,這種僞随機關系的近似均勻性才能成立,Ceph的資料存儲均勻性才有保證。為保證“大量”的成立,一方面,object的最大size應該被合理配置,以使得同樣數量的file能夠被切分成更多的object;另一方面,Ceph也推薦PG總數應該為OSD總數的數百倍,以保證有足夠數量的PG可供映射。
3. PG -> OSD映射
第三次映射就是将作為object的邏輯組織單元的PG映射到資料的實際存儲單元OSD。如圖所示,RADOS采用一個名為CRUSH的算法,将pgid代入其中,然後得到一組共n個OSD。這n個OSD即共同負責存儲和維護一個PG中的所有object。前已述及,n的數值可以根據實際應用中對于可靠性的需求而配置,在生産環境下通常為3。具體到每個OSD,則由其上運作的OSD deamon負責執行映射到本地的object在本地檔案系統中的存儲、通路、中繼資料維護等操作。
和“object -> PG”映射中采用的雜湊演算法不同,這個CRUSH算法的結果不是絕對不變的,而是受到其他因素的影響。其影響因素主要有二:
一是目前系統狀态,也就是上文邏輯結構中曾經提及的clustermap。當系統中的OSD狀态、數量發生變化時,cluster map可能發生變化,而這種變化将會影響到PG與OSD之間的映射。
二是存儲政策配置。這裡的政策主要與安全相關。利用政策配置,系統管理者可以指定承載同一個PG的3個OSD分别位于資料中心的不同伺服器乃至機架上,進而進一步改善存儲的可靠性。
是以,隻有在系統狀态(cluster map)和存儲政策都不發生變化的時候,PG和OSD之間的映射關系才是固定不變的。在實際使用當中,政策一經配置通常不會改變。而系統狀态的改變或者是由于裝置損壞,或者是因為存儲叢集規模擴大。好在Ceph本身提供了對于這種變化的自動化支援,因而,即便PG與OSD之間的映射關系發生了變化,也并不會對應用造成困擾。事實上,Ceph正是需要有目的的利用這種動态映射關系。正是利用了CRUSH的動态特性,Ceph可以将一個PG根據需要動态遷移到不同的OSD組合上,進而自動化地實作高可靠性、資料分布re-blancing等特性。
之是以在此次映射中使用CRUSH算法,而不是其他雜湊演算法,原因之一正是CRUSH具有上述可配置特性,可以根據管理者的配置參數決定OSD的實體位置映射政策;另一方面是因為CRUSH具有特殊的“穩定性”,也即,當系統中加入新的OSD,導緻系統規模增大時,大部分PG與OSD之間的映射關系不會發生改變,隻有少部分PG的映射關系會發生變化并引發資料遷移。這種可配置性和穩定性都不是普通雜湊演算法所能提供的。是以,CRUSH算法的設計也是Ceph的核心内容之一,具體介紹可以參考。
至此為止,Ceph通過三次映射,完成了從file到object、PG和OSD整個映射過程。通觀整個過程,可以看到,這裡沒有任何的全局性查表操作需求。至于唯一的全局性資料結構cluster map,在後文中将加以介紹。可以在這裡指明的是,cluster map的維護和操作都是輕量級的,不會對系統的可擴充性、性能等因素造成不良影響。
一個可能出現的困惑是:為什麼需要同時設計第二次和第三次映射?難道不重複麼?關于這一點,Sage在其論文中解說不多,而筆者個人的分析如下:
我們可以反過來想像一下,如果沒有PG這一層映射,又會怎麼樣呢?在這種情況下,一定需要采用某種算法,将object直接映射到一組OSD上。如果這種算法是某種固定映射的雜湊演算法,則意味着一個object将被固定映射在一組OSD上,當其中一個或多個OSD損壞時,object無法被自動遷移至其他OSD上(因為映射函數不允許),當系統為了擴容新增了OSD時,object也無法被re-balance到新的OSD上(同樣因為映射函數不允許)。這些限制都違背了Ceph系統高可靠性、高自動化的設計初衷。
如果采用一個動态算法(例如仍然采用CRUSH算法)來完成這一映射,似乎是可以避免靜态映射導緻的問題。但是,其結果将是各個OSD所處理的本地中繼資料量爆增,由此帶來的計算複雜度和維護工作量也是難以承受的。
例如,在Ceph的現有機制中,一個OSD平時需要和與其共同承載同一個PG的其他OSD交換資訊,以确定各自是否工作正常,是否需要進行維護操作。由于一個OSD上大約承載數百個PG,每個PG内通常有3個OSD,是以,一段時間内,一個OSD大約需要進行數百至數千次OSD資訊交換。
然而,如果沒有PG的存在,則一個OSD需要和與其共同承載同一個object的其他OSD交換資訊。由于每個OSD上承載的object很可能高達數百萬個,是以,同樣長度的一段時間内,一個OSD大約需要進行的OSD間資訊交換将暴漲至數百萬乃至數千萬次。而這種狀态維護成本顯然過高。
綜上所述,筆者認為,引入PG的好處至少有二:一方面實作了object和OSD之間的動态映射,進而為Ceph的可靠性、自動化等特性的實作留下了空間;另一方面也有效簡化了資料的存儲組織,大大降低了系統的維護管理開銷。了解這一點,對于徹底了解Ceph的對象尋址機制,是十分重要的。
此處将首先以file寫入過程為例,對資料操作流程進行說明。
為簡化說明,便于了解,此處進行若幹假定。首先,假定待寫入的file較小,無需切分,僅被映射為一個object。其次,假定系統中一個PG被映射到3個OSD上。
基于上述假定,則file寫入流程可以被下圖表示:
<a href="http://s1.51cto.com/wyfs02/M02/82/9E/wKioL1ddFdPBsC9eAAAyy8pwuWk184.png" target="_blank"></a>
如圖所示,當某個client需要向Ceph叢集寫入一個file時,首先需要在本地完成5.1節中所叙述的尋址流程,将file變為一個object,然後找出存儲該object的一組三個OSD。這三個OSD具有各自不同的序号,序号最靠前的那個OSD就是這一組中的Primary OSD,而後兩個則依次是Secondary OSD和Tertiary OSD。
找出三個OSD後,client将直接和Primary OSD通信,發起寫入操作(步驟1)。Primary OSD收到請求後,分别向Secondary OSD和Tertiary OSD發起寫入操作(步驟2、3)。當Secondary OSD和Tertiary OSD各自完成寫入操作後,将分别向Primary OSD發送确認資訊(步驟4、5)。當Primary OSD确信其他兩個OSD的寫入完成後,則自己也完成資料寫入,并向client确認object寫入操作完成(步驟6)。
之是以采用這樣的寫入流程,本質上是為了保證寫入過程中的可靠性,盡可能避免造成資料丢失。同時,由于client隻需要向Primary OSD發送資料,是以,在Internet使用場景下的外網帶寬和整體通路延遲又得到了一定程度的優化。
當然,這種可靠性機制必然導緻較長的延遲,特别是,如果等到所有的OSD都将資料寫入磁盤後再向client發送确認信号,則整體延遲可能難以忍受。是以,Ceph可以分兩次向client進行确認。當各個OSD都将資料寫入記憶體緩沖區後,就先向client發送一次确認,此時client即可以向下執行。待各個OSD都将資料寫入磁盤後,會向client發送一個最終确認信号,此時client可以根據需要删除本地資料。
分析上述流程可以看出,在正常情況下,client可以獨立完成OSD尋址操作,而不必依賴于其他系統子產品。是以,大量的client可以同時和大量的OSD進行并行操作。同時,如果一個file被切分成多個object,這多個object也可被并行發送至多個OSD。
從OSD的角度來看,由于同一個OSD在不同的PG中的角色不同,是以,其工作壓力也可以被盡可能均勻地分擔,進而避免單個OSD變成性能瓶頸。
如果需要讀取資料,client隻需完成同樣的尋址過程,并直接和Primary OSD聯系。目前的Ceph設計中,被讀取的資料僅由Primary OSD提供。但目前也有分散讀取壓力以提高性能的讨論。
前面的介紹中已經提到,由若幹個monitor共同負責整個Ceph叢集中所有OSD狀态的發現與記錄,并且共同形成clustermap的master版本,然後擴散至全體OSD以及client。OSD使用cluster map進行資料的維護,而client使用cluster map進行資料的尋址。
在叢集中,各個monitor的功能總體上是一樣的,其互相間的關系可以被簡單了解為主從備份關系。是以,在下面的讨論中不對各個monitor加以區分。
略顯出乎意料的是,monitor并不主動輪詢各個OSD的目前狀态。正相反,OSD需要向monitor上報狀态資訊。常見的上報有兩種情況:一是新的OSD被加入叢集,二是某個OSD發現自身或者其他OSD發生異常。在收到這些上報資訊後,monitor将更新cluster map資訊并加以擴散。其細節将在下文中加以介紹。
Cluster map的實際内容包括:
(1) Epoch,即版本号。Cluster map的epoch是一個單調遞增序列。Epoch越大,則cluster map版本越新。是以,持有不同版本cluster map的OSD或client可以簡單地通過比較epoch決定應該遵從誰手中的版本。而monitor手中必定有epoch最大、版本最新的cluster map。當任意兩方在通信時發現彼此epoch值不同時,将預設先将cluster map同步至高版本一方的狀态,再進行後續操作。
(2)各個OSD的網絡位址。
(3)各個OSD的狀态。OSD狀态的描述分為兩個次元:up或者down(表明OSD是否正常工作),in或者out(表明OSD是否在至少一個PG中)。是以,對于任意一個OSD,共有四種可能的狀态:
—— Up且in:說明該OSD正常運作,且已經承載至少一個PG的資料。這是一個OSD的标準工作狀态;
—— Up且out:說明該OSD正常運作,但并未承載任何PG,其中也沒有資料。一個新的OSD剛剛被加入Ceph叢集後,便會處于這一狀态。而一個出現故障的OSD被修複後,重新加入Ceph叢集時,也是處于這一狀态;
—— Down且in:說明該OSD發生異常,但仍然承載着至少一個PG,其中仍然存儲着資料。這種狀态下的OSD剛剛被發現存在異常,可能仍能恢複正常,也可能會徹底無法工作;
—— Down且out:說明該OSD已經徹底發生故障,且已經不再承載任何PG。
(4)CRUSH算法配置參數。表明了Ceph叢集的實體層級關系(cluster hierarchy),位置映射規則(placement rules)。
根據cluster map的定義可以看出,其版本變化通常隻會由(3)和(4)兩項資訊的變化觸發。而這兩者相比,(3)發生變化的機率更高一些。這可以通過下面對OSD工作狀态變化過程的介紹加以反映。
一個新的OSD上線後,首先根據配置資訊與monitor通信。Monitor将其加入cluster map,并設定為up且out狀态,再将最新版本的cluster map發給這個新OSD。
收到monitor發來的clustermap之後,這個新OSD計算出自己所承載的PG(為簡化讨論,此處我們假定這個新的OSD開始隻承載一個PG),以及和自己承載同一個PG的其他OSD。然後,新OSD将與這些OSD取得聯系。如果這個PG目前處于降級狀态(即承載該PG的OSD個數少于正常值,如正常應該是3個,此時隻有2個或1個。這種情況通常是OSD故障所緻),則其他OSD将把這個PG内的所有對象和中繼資料複制給新OSD。資料複制完成後,新OSD被置為up且in狀态。而cluster map内容也将據此更新。這事實上是一個自動化的failure recovery過程。當然,即便沒有新的OSD加入,降級的PG也将計算出其他OSD實作failure recovery。
如果該PG目前一切正常,則這個新OSD将替換掉現有OSD中的一個(PG内将重新選出Primary OSD),并承擔其資料。在資料複制完成後,新OSD被置為up且in狀态,而被替換的OSD将退出該PG(但狀态通常仍然為up且in,因為還要承載其他PG)。而cluster map内容也将據此更新。這事實上是一個自動化的資料re-balancing過程。
如果一個OSD發現和自己共同承載一個PG的另一個OSD無法聯通,則會将這一情況上報monitor。此外,如果一個OSD deamon發現自身工作狀态異常,也将把異常情況主動上報給monitor。在上述情況下,monitor将把出現問題的OSD的狀态設為down且in。如果超過某一預訂時間期限,該OSD仍然無法恢複正常,則其狀态将被設定為down且out。反之,如果該OSD能夠恢複正常,則其狀态會恢複為up且in。在上述這些狀态變化發生之後,monitor都将更新cluster map并進行擴散。這事實上是自動化的failure detection過程。
由之前介紹可以看出,對于一個Ceph叢集而言,即便由數千個甚至更多OSD組成,cluster map的資料結構大小也并不驚人。同時,cluster map的狀态更新并不會頻繁發生。即便如此,Ceph依然對cluster map資訊的擴散機制進行了優化,以便減輕相關計算和通信壓力。
首先,cluster map資訊是以增量形式擴散的。如果任意一次通信的雙方發現其epoch不一緻,則版本更新的一方将把二者所擁有的cluster map的差異發送給另外一方。
其次,cluster map資訊是以異步且lazy的形式擴散的。也即,monitor并不會在每一次clustermap版本更新後都将新版本廣播至全體OSD,而是在有OSD向自己上報資訊時,将更新回複給對方。類似的,各個OSD也是在和其他OSD通信時,将更新發送給版本低于自己的對方。
基于上述機制,Ceph避免了由于cluster map版本更新而引起的廣播風暴。這雖然是一種異步且lazy的機制,但根據Sage論文中的結論,對于一個由n個OSD組成的Ceph叢集,任何一次版本更新能夠在O(log(n))時間複雜度内擴散到叢集中的任何一個OSD上。
一個可能被問到的問題是:既然這是一種異步和lazy的擴散機制,則在版本擴散過程中,系統必定出現各個OSD看到的cluster map不一緻的情況,這是否會導緻問題?答案是:不會。事實上,如果一個client和它要通路的PG内部的各個OSD看到的cluster map狀态一緻,則通路操作就可以正确進行。而如果這個client或者PG中的某個OSD和其他幾方的cluster map不一緻,則根據Ceph的機制設計,這幾方将首先同步cluster map至最新狀态,并進行必要的資料re-balancing操作,然後即可繼續正常通路。
通過上述介紹,我們可以簡要了解Ceph究竟是如果基于cluster map機制,并由monitor、OSD和client共同配合完成叢集狀态的維護與資料通路的。特别的,基于這個機制,事實上可以自然而然的完成自動化的資料備份、資料re-balancing、故障探測和故障恢複,并不需要複雜的特殊設計。這一點确實讓人印象深刻。
本文轉自Jacken_yang 51CTO部落格,原文連結:http://blog.51cto.com/linuxnote/1788294,如需轉載請自行聯系原作者