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。

相关文章
相关标签/搜索