ceph的數據存儲之路(3) ----- pg選擇osd的過程(crush 算法)

       0. 學會使用解析ceph的cluster map工具:node

ceph osd getcrushmap -o crush.map
crushtool -d crush.map >> crush.txt

        這時將一個ceph集羣的 cluster map導入到crush.txt的文件中,這時能夠cat這個文件看一下文件中保存了哪些內容,幫助理解下面的內容算法

 

 1. 說明:這裏首先要說明的是  一個object要保存三個副本,也就是要保存到三個osd上,當前的ceph集羣能夠存在N個osd節點,那麼怎麼來記錄這個object保存到哪裏了? 這裏就要講述這個僞隨機的選擇osd過程-----crush。        shell

pg OSD的映射的過程算法叫作crush 算法,這個算法是一個僞隨機的過程,他能夠從全部的OSD中,隨機性選擇一個OSD集合,可是同一個PG每次隨機選擇的結果是不變的,也就是映射的OSD集合是固定的。數組

2. crush 因子工具

OSDMap管理當前ceph中全部的OSDOSDMap規定了crush算法的一個範圍,在這個範圍中選擇OSD結合。那麼影響crush算法結果的有兩種因素,一個就是OSDMap的結構,另一個就是crush rulespa

OSDMap其實就是一個樹形的結構,葉子節點是device(也就是osd),其餘的節點稱爲bucket節點,這些bucket都是虛構的節點,能夠根據物理結構進行抽象,固然樹形結構只有一個最終的根節點稱之爲root節點,中間虛擬的bucket節點能夠是數據中心抽象、機房抽象、機架抽象、主機抽象等如圖。code

 

1-4  osd組成的邏輯樹形結構orm

 

上圖中紅色框內的節點都是bucket節點,這些節點都是根據實際狀況進行抽象得來的。其實也就是實際中整個物理拓撲結構。這個拓撲裏的每一個節點都有一個權重值,這個權重值等於全部子節點的權重之和,葉子節點的重量由osd的容量決定,通常設定1T的權重爲1。這個權重值在crush算法中也有很重要的地位。遞歸

3.bucket類型解釋:get

對於bucket節點不僅是虛設的節點,bucket一樣有typebuckettype有四種類型結構,uniformlisttreestraw。這四種bucket有着不一樣的特性,buckettype設定一樣也影響着crush算法。

3.1 uniform 類型:先來介紹下uniform bucket如何來定位數據在哪一個子節點的過程。

1-5 uniform 定位子節點過程

先來講明一下uniform的要素。bucket的全部子節點都保存在item[]數組之中。perm_x 是記錄此次隨機排布時 x的值,perm[]是在perm_x時候對item隨機排列後的結果。r則是選擇第幾個副本。

定位子節點過程。這時咱們從新來看uniform定位子節點的過程。根據輸入的x值判斷是否爲perm_x,若是不是,則須要從新排列perm[]數組,而且記錄perm_x=x。若是x==perm_x時,這時算R = r%size,算後獲得R,最後返回 perm[R]

uniform bucket 適用的狀況:

a.適用於全部子節點權重相同的狀況。由於uniformbucket在選擇子節點時是不考慮權重的問題,所有隨機選擇。因此在權重上不會進行特別的照顧,爲了公平起見最好是相同的權重節點。

b.適用於子節點變化機率小的狀況。當子節點的數量進行變化時,size發生改變,在隨機組合perm數組時,即便x相同,則perm數組須要徹底從新排列,也就意味着已經保存在子節點的數據要所有發生重排,形成不少數據的遷移。因此uniform不適合子節點變化的bucket,不然會產生大量已經保存的數據發生移動,全部的item上的數據均可能會發生相互之間的移動。

3.2 list 類型:list bucket的造成過程。list  bucket 不是真的將全部的item都穿成一個鏈表,bucketitem仍然保存在item數組之中。這時的list bucket 每一個item 不只要保存的權重(根據容量換算而來)weight,還要記錄前全部節點的重量之和sum_weight如圖,list bucket的每一個item的權重能夠不相同,也不須要按順序排列。

1-6 list bucket 造成過程

list bucket定位數據在子節點的方法。從head開始,會逐個的查找子節點是否保存數據。

      如何判斷當前子節點是否保存了數據呢?首先取了一個節點以後,根據xr itemid 進行crush_hash獲得一個w值。這個值與sum_weight之積,最後這個w再向右移16位,最後判斷這個值與weight的大小,若是小於weight時,則選擇當前的這個item,不然進行查找下一個item

1-7 list bucket 定位數據過程

list bucket使用的狀況:

a.適用於集羣拓展類型。當增長item時,會產生最優的數據移動。由於在list bucket中增長一個item節點時,都會增長到head部,這時其餘節點的sum_weight都不會發生變化,只須要將old_head 上的sum_weightweight之和添加到new_headsum_weight就行了。這樣時其餘item之間不須要進行數據移動,其餘的item上的數據 只須要和 head上比較就好,若是算的w值小於headweight,則須要移動到head上,不然還保存在原來的item上。這樣就得到了最優最少的數據移動。

b.list bucket存在一個缺點,就是在查找item節點時,只能順序查找 時間複雜度爲O(n)

3.3 tree 類型:tree bucket 會藉助一個叫作node_weight[ ]的數組來進行幫助搜索定位item。首先是node_weight[ ]的造成,nodeweight[ ]中不只包含了item,並且增長了不少中間節點,item都做爲葉子節點。父節點的重量等於左右子節點的重量之和,遞歸到根節點以下圖。

1-8 tree bucket的造成過程

tree bucket的搜索過程,經過必定的方法造成node tree。這tree的查找從根節點開始直到找到葉子節點。當前節點的重量weight使用crush_hash(x,r)修正後,與左節點的重量left_weight比較,若是比左節點輕 則繼續遍歷左節點,不然遍歷右節點以下圖。因此該類型的bucket適合於查找的,對於變更的集羣就沒那麼合適了。

1-9 tree bucket選擇過程

3.4 straw類型:這種類型是一種抽籤類型的bucket,他選擇子節點是公平的,strawuniform的區別在於,straw算法考慮了子節點的權重,因此是最公平的bucket類型。

1-10 straw bucket的造成過程

straw bucket首先根據每一個節點的重量生成的straw,最後組成straw[] 數組。在straw定位副本的過程當中,每個定位都須要遍歷全部的item,長度draw = crush(x,r,item_id)*straw[i]。找出那個最長的,最後選擇這個最長,定位到副本。

 

4. crush rule介紹:

crush rule主要有3個重點:a.OSDMap中的哪一個節點開始查找,b.使用那個節點做爲故障隔離域,c.定位副本的搜索模式(廣度優先 or 深度優先)。

# rules

 

 rule replicated_ruleset                            #規則集的命名,建立pool時能夠指定rule集
{
    ruleset 0                                      #rules集的編號,順序編便可
    type replicated                                #定義pool類型爲replicated(還有esurecode模式)
    min_size 1                                     #pool中最小指定的副本數量不能小1\

max_size 10                                    #pool中最大指定的副本數量不能大於10    

step take default                              #定義pg查找副本的入口點

 step chooseleaf  firstn  0  type  host         #選葉子節點、深度優先、隔離host

    step emit        #結束

}

5. 總結:

pg 選擇osd的過程,首先要知道在rules中 指明從osdmap中哪一個節點開始查找,入口點默認爲default也就是root節點,而後隔離域爲host節點(也就是同一個host下面不能選擇兩個子節點)。由default到3個host的選擇過程,這裏由default根據節點的bucket類型選擇下一個子節點,由子節點再根據自己的類型繼續選擇,知道選擇到host,而後在host下選擇一個osd。

相關文章
相關標籤/搜索