1. 程式人生 > >Ceph架構剖析

Ceph架構剖析

e**分散式儲存系統——Ceph**
1.Ceph的結構
這裡寫圖片描述
從下到上將Ceph結構分為4層,分別介紹如下:
(1)基礎儲存系統——可靠的自動化分散式物件儲存(RADOS)
所有儲存在Ceph系統中的使用者資料都在該層進行管理,而Ceph的高可靠、高可擴充套件、高效能、高自動化等等特性本質上也是由這一層所提供的。因此,理解RADOS是理解Ceph的基礎與關鍵。RADOS在物理形態上由大量的儲存裝置節點組成,每個節點擁有自己的硬體資源(CPU、記憶體、硬碟、網路),並執行著作業系統和檔案系統。

(2)基礎庫Librados
對RADOS的封裝和抽象,向上層提供API,以便於直接基於RADOS進行開發。因為RADOS是一個物件儲存系統,則Librados實現的API也主要是針對物件儲存功能的。

(3)高階應用介面
這一層包括了三個部分:RADOS GW(RADOS Gateway)、 RBD(Reliable Block Device)和Ceph FS(Ceph File System),其作用是在librados庫的基礎上提供抽象層次更高、更便於應用或客戶端使用的上層介面。

RADOS GW是一個提供與亞馬遜S3和Swift相容的RESTful API的gateway,以供相應的物件儲存應用開發使用。RADOS GW提供的API抽象層次更高,但功能則不如librados強大。因此,開發者應針對自己的需求選擇使用。

RBD則提供了一個標準的塊裝置介面,常用於在虛擬化的場景下為虛擬機器建立volume。目前,Red Hat已經將RBD驅動整合在KVM/QEMU中,以提高虛擬機器訪問效能。

Ceph FS是一個POSIX相容的分散式檔案系統。

(4)應用層
這一層就是不同場景下對於Ceph各個應用介面的各種應用方式,例如基於librados直接開發的物件儲存應用,基於RADOS GW開發的物件儲存應用,基於RBD實現的雲硬碟等等。

本節將對Ceph的工作原理和若干關鍵工作流程進行介紹。由於Ceph的功能實現本質上依託於RADOS,因此,此處的介紹事實上也是針對RADOS進行。對於上層的部分,特別是RADOS GW和RBD,由於現有的文件中(包括Sage的論文中)並未詳細介紹,還請讀者多多包涵。

2.RADOS的結構
RADOS的結構主要包括ObjectStorage Device(OSD),Monitor和MDS。
這裡寫圖片描述

ObjectStorage Device(OSD)負責儲存資料,處理資料複製、資料恢復、資料再均衡以及通過心跳機制監測其它OSD狀況並報告給Ceph Monitors。

Monitor負責監控叢集狀態,包括監控自身狀態、叢集OSD狀態、Placement Group(儲存組織和位置對映PGs)狀態、CRUSH狀態(Controlled Replication Under Scalable Hashing,一種偽隨機資料分佈演算法)。同時,Monitor還會記錄它們的每一個歷史狀態改變版本資訊,以確定叢集該遵循哪個版本。

MDS負責檔案系統的元資料儲存和管理,塊儲存和物件儲存服務是不需要這個模組的。MDS負責提供標準的POSIX檔案訪問介面。

3.RADOS的定址機制
這裡寫圖片描述

(1)概念說明
File:此處的file就是使用者需要儲存或者訪問的檔案。對於一個基於Ceph開發的物件儲存應用而言,這個file也就對應於應用中的“物件“,也就是使用者直接操作的“物件”。

objects:​此處的object是RADOS所看到的“物件”。Object與上面提到的file的區別是,object的最大size由RADOS限定(通常為2MB或4MB),以便實現底層儲存的組織管理。因此,當上層應用向RADOS存入size很大的file時,需要將file切分成統一大小的一系列object(最後一個的大小可以不同)進行儲存。

PGs(Placement Group)​:即安置組,對object的儲存進行組織和位置對映。一個PG負責組織若干個object,但是一個object只能對映到一個PG中,即PG和object之間的關係是“一對多”。一個PG會被對映到多個OSD上,每個OSD上都會承載若干個PG,即PG和OSD之間的關係是“多對多”。

OSD(object storage device):OSD的數量事實上也關係到系統的資料分佈均勻性,因此其數量不應太少。在實踐當中,至少也應該是數十上百個的量級才有助於Ceph系統的設計發揮其應有的優勢,一般是10-1000個。

(2)定址的三層對映
<1>File -> object對映
這次對映的目的是,將使用者要操作的file,對映為RADOS能夠處理的object。其對映十分簡單,本質上就是按照object的最大size對file進行切分。這種切分的好處有兩點:一是讓大小不限的file變成與最大size一致,方便RADOS底層高效管理;二是讓對單一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的唯一性必須得到保證,否則後續對映無法正確進行。一般用MD5值作為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演算法的結果不是絕對不變的,而是受到其他因素的影響。其影響因素主要有兩個:

一是當前系統狀態,也就是上文邏輯結構中曾經提及的cluster map。當系統中的OSD狀態、數量發生變化時,cluster map可能發生變化,而這種變化將會影響到PG與OSD之間的對映。
二是儲存策略配置。這裡的策略主要與安全相關。利用策略配置,系統管理員可以指定承載同一個PG的3個OSD分別位於資料中心的不同伺服器乃至機架上,從而進一步改善儲存的可靠性。

因此,只有在系統狀態(cluster map)和儲存策略都不發生變化的時候,PG和OSD之間的對映關係才是固定不變的

之所以在此次對映中使用CRUSH演算法,而不是其他雜湊演算法,原因之一正是CRUSH具有可配置特性,可以根據管理員的配置引數決定OSD的物理位置對映策略;另一方面是因為CRUSH具有特殊的”穩定性”。當系統中加入新的OSD,導致系統規模增大時,大部分PG與OSD之間的對映關係不會發生改變,只有少部分PG的對映關係會發生變化並引發資料遷移。這種可配置性和穩定性都不是普通雜湊演算法所能提供的。因此,CRUSH演算法的設計也是Ceph的核心內容之一。

(3)思考:為什麼要設計第二次和三次對映?
關於這一點,Sage在其論文中解說不多,參考網上一些資料再加上自己的理解,我覺得有下面幾個原因:

反過來想一下,如果沒有PG這一層對映,會怎樣呢?
如果沒有PG這一層的對映,就需要採用某一演算法,直接將object對映到OSD上。

如果這一演算法是某個固定的雜湊演算法,也就意味著一個object將被固定的對映到一組OSD中,當其中一個或多個OSD損壞時,object無法被自動遷移至其他OSD上(因為對映函式不允許),當系統為了擴容新增了OSD時,object也無法被re-balance到新的OSD上(同樣因為對映函式不允許)。這些限制都違背了Ceph系統高可靠性、高自動化的設計初衷。

如果採用一個動態演算法(例如仍然採用CRUSH演算法)來完成這一對映,似乎是可以避免靜態對映導致的問題。但是,其結果將是各個OSD所處理的本地元資料量爆增,由此帶來的計算複雜度和維護工作量也是難以承受的。

綜上所述,引入PG一方面實現了object和OSD之間的動態對映,從而為Ceph的可靠性、自動化等特性的實現留下了空間;另一方面也有效簡化了資料的儲存組織,大大降低了系統的維護管理開銷。因此有了第二次(object->PG)和第三次(PG->OSD)的對映

4.資料操作流程——二次確認機制(強一致性)
這裡寫圖片描述

假設:file較小,不需要進行分塊,僅被對映為一個object,一個PG對映到3個OSD上。

(1)資料操作流程:

<1>file 先完成定址流程,將file變為object,然後再找到儲存該object的一組(3個)​OSD。
<2>​client 與主OSD(primary OSD)通訊,寫入資料。primary OSD在收到客戶端的請求後向Secondary OSD、 Tertiary OSD發起寫入資料的請求。
<3>​Secondary OSD、 Tertiary OSD寫入操作完成後向Primary OSD傳送操作完成的確認資訊。
<4>當primary OSD也完成操作後就向客戶端傳送操作完成的確認資訊。​檔案的寫操作完成。

之所以採用這樣的寫入流程,本質上是為了保證寫入過程中的可靠性,儘可能避免造成資料丟失。同時,由於client只需要向Primary OSD傳送資料,因此,在Internet使用場景下的外網頻寬和整體訪問延遲又得到了一定程度。

當然,這種可靠性機制必然導致較長的延遲,特別是,如果等到所有的OSD都將資料寫入磁碟後再向client傳送確認訊號,則整體延遲可能難以忍受。

因此,Ceph可以分兩次向client進行確認當各個OSD都將資料寫入記憶體緩衝區後,就先向client傳送一次確認,此時client即可以向下執行。待各個OSD都將資料寫入磁碟後,會向client傳送一個最終確認訊號,此時client可以根據需要刪除本地資料。

分析上述流程可以看出,在正常情況下,client可以獨立完成OSD定址操作,而不必依賴於其他系統模組。因此,大量的client可以同時和大量的OSD進行並行操作。同時,如果一個file被切分成多個object,這多個object也可被並行傳送至多個OSD。

若需要讀取資料,client只需完成同樣的定址過程,直接和Primary OSD聯絡。目前的Ceph設計中,被讀取的資料僅由Primary OSD提供。但目前也有分散讀取壓力以提高效能的討論。

5.叢集的維護

由若干個monitor共同負責整個Ceph叢集中所有OSD狀態的發現與記錄,並且共同形成cluster map的master版本,然後擴散至全體OSD以及client。OSD使用cluster map進行資料的維護,而client使用cluster map進行資料的定址。在叢集中,各個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發來的cluster map之後,這個新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過程。

cluster map有以下幾個特點:
(1)cluster map資訊是以增量形式擴散的。如果任意一次通訊的雙方發現其epoch不一致,則版本更新的一方將把二者所擁有的cluster map的差異傳送給另外一方。
(2)cluster map資訊是以非同步且lazy的形式擴散的。即monitor並不會在每一次cluster map版本更新後都將新版本廣播至全體OSD,而是在有OSD向自己上報資訊時,將更新回覆給對方。類似的,各個OSD也是在和其他OSD通訊時,將更新發送給版本低於自己的對方。

基於上述機制,Ceph避免了由於cluster map版本更新而引起的廣播風暴。這雖然是一種非同步且lazy的機制,但根據Sage論文中的結論,對於一個由n個OSD組成的Ceph叢集,任何一次版本更新能夠在O(log(n))時間複雜度內擴散到叢集中的任何一個OSD上。

思考:既然cluster map訊息擴散是一種非同步和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、故障探測和故障恢復,並不需要複雜的特殊設計。
6.Ceph的特點
(1)高擴充套件性
高度並行。沒有單箇中心控制組件。所有負載都能動態的劃分到各個伺服器上。把更多的功能放到OSD上,讓OSD更智慧。

自管理。容易擴充套件、升級、替換。當元件發生故障時,自動進行資料的重新複製。當元件發生變化時(新增/刪除),自動進行資料的重分佈。

(2)高效能
<1>Client和Server直接通訊,不需要代理和轉發
<2>多個OSD帶來的高併發度。objects是分佈在所有OSD上。
<3>負載均衡。每個OSD都有權重值(現在以容量為權重)。
​<4>client不需要負責副本的複製(由primary OSD負責),這降低了client的網路消耗。
(3)高可靠性
<1>資料多副本。可配置的per-pool副本策略和故障域佈局,支援強一致性。
<2>沒有單點故障。可以忍受許多種故障場景;防止腦裂;單個元件可以滾動升級並在線替換.
<3>所有故障的檢測和自動恢復。恢復不需要人工介入,在恢復期間,可以保持正常的資料訪問。
<4>並行恢復。並行的恢復機制極大的降低了資料恢復時間,提高資料的可靠性。