Ceph+Openstack相關入門-Ceph工作原理及流程

   在之前的博文中有介紹CEPH的pool、pg等概念,學習了這篇工作流程,會有更清晰的瞭解。

Ceph+Openstack相關入門——Ceph的pool與PG

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

        本文將首先介紹RADOS中最爲核心的、基於計算的對象尋址機制,然後說明對象存取的工作流程,之後介紹RADOS集羣維護的工作過程,最後結合Ceph的結構和原理對其技術優勢加以回顧和剖析。

5.1    尋址流程

        Ceph系統中的尋址流程如下圖所示[1]。

“Ceph淺析”系列之(四)——Ceph的工作原理及流程
        上圖左側的幾個概念說明如下:

        File —— 此處的file就是用戶需要存儲或者訪問的文件。對於一個基於Ceph開發的對象存儲應用而言,這個file也就對應於應用中的“對象”,也就是用戶直接操作的“對象”。

        Ojbect —— 此處的object是RADOS所看到的“對象”。Object與上面提到的file的區別是,object的最大size由RADOS限定(通常爲 2MB或4MB),以便實現底層存儲的組織管理。因此,當上層應用向RADOS存入size很大的file時,需要將file切分成統一大小的一系列 object(最後一個的大小可以不同)進行存儲。爲避免混淆,在本文中將盡量避免使用中文的“對象”這一名詞,而直接使用file或object進行說 明。

        PG(Placement Group)—— 顧名思義,PG的用途是對object的存儲進行組織和位置映射。具體而言,一個PG負責組織若干個object(可以爲數千個甚至更多),但一個 object只能被映射到一個PG中,即,PG和object之間是“一對多”映射關係。同時,一個PG會被映射到n個OSD上,而每個OSD上都會承載 大量的PG,即,PG和OSD之間是“多對多”映射關係。在實踐當中,n至少爲2,如果用於生產環境,則至少爲3。一個OSD上的PG則可達到數百個。事 實上,PG數量的設置牽扯到數據分佈的均勻性問題。關於這一點,下文還將有所展開。

        OSD —— 即object storage device,前文已經詳細介紹,此處不再展開。唯一需要說明的是,OSD的數量事實上也關係到系統的數據分佈均勻性,因此其數量不應太少。在實踐當中, 至少也應該是數十上百個的量級才有助於Ceph系統的設計發揮其應有的優勢。

        Failure domain —— 這個概念在論文中並沒有進行定義,好在對分佈式存儲系統有一定概念的讀者應該能夠了解其大意。

        基於上述定義,便可以對尋址流程進行解釋了。具體而言, 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算法的結果不是絕對不變的,而是受到其他因素的影響。其影響因素主要有二:

        一是當前系統狀態,也就是在《“Ceph淺析”系列之四——邏輯結構》中曾經提及的cluster map。當系統中的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 的核心內容之一,具體介紹可以參考[2]。

        至 此爲止,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的對象尋址機制,是十分重要的。

5.2    數據操作流程

        此處將首先以file寫入過程爲例,對數據操作流程進行說明。

        爲簡化說明,便於理解,此處進行若干假定。首先,假定待寫入的file較小,無需切分,僅被映射爲一個object。其次,假定系統中一個PG被映射到3個OSD上。

        基於上述假定,則file寫入流程可以被下圖表示[3]:

“Ceph淺析”系列之(四)——Ceph的工作原理及流程

        如 圖所示,當某個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提供。但目前也有分散讀取壓力以提高性能的討論。

5.3    集羣維護

        前 面的介紹中已經提到,由若干個monitor共同負責整個Ceph集羣中所有OSD狀態的發現與記錄,並且共同形成cluster map的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發來的cluster map之後,這個新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並不會在每一次cluster map版本更新後都將新版本廣播至全體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、故障探測和故障恢復,並不需要複雜的特殊設計。這一點確實讓人印象深刻。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章