Ceph学习之Crush算法—— Bucket

来源:互联网 发布:水利工程概预算软件 编辑:程序博客网 时间:2024/04/29 16:57

Ceph使用Bucket将系统的存储资源按照层级结构组织完成两个目标:映射算法的高效性和可扩展性,以及当集群状态发生变化时(比如设备的增加或者删除)数据的迁移量要尽可能的少。CRUSH定义了四种bucket类型(Uniform Bucket、List Bucket、Tree Bucket、Straw Bucket)来表示层级结构的中间节点,叶子节点就是对应的OSD。每一种类型的bucket使用不同的数据结构来组织它包含的内容,可以是其他Bucket或者OSD,它们是在性能和效率间的折中。接下来将详细介绍一下这四种Bucket。

1 Uniform Bucket

这种bucket有一个严格的要求,bucket中所有的item都是同构的,如有相同的性能,相同大小的容量,而其余三种bucket允许包含不同权重的设备。这个主要是考虑到设备不会一个一个添加到系统里,而是批量添加的。它根据hash函数c(r,x)=(hash(x) + rp) mod m进行映射,映射的时间复杂度是O(1),所以它的查询速度是最快的。当然它也有明显的不足,当添加或删除item时,会导致大量的数据迁移。这是因为它的计算方法和bucket大小有关系,所以当bucket发生变化时所有的计算结果都会发生变化,也就是会有数据迁移。

2 List Bucket

它的结构是链表结构,所包含的item可以具有任意的权重。CRUSH从表头开始查找副本位置,它先得到表头item的权重Wh,然后和剩余所有节点权重之和Wr做比较,然后根据hash(x, r, item)得到一个[0~1]值v,如果v在[0~Wh/Wr],则副本在表头item中,并返回item的id,否则继续遍历剩余的链表。这个方法是从RUSHp算法中演变过来的,将数据分布问题转变为“most recently added item, or older items”。这种方法对于总是有新节点加入的情况很有好处,但当有节点从中间或者尾部删除时,就会带来一些数据迁移。这也和它的计算方法有关系,如果从尾部删除一个节点后,Wr的值回发生变化,所以ratio的值也会发生变化。使用这种bucket会使得数据要么存储在新加入的节点上,要么就还保留在原来老的地方。

List Bucket的查找复杂度为O(n),所以只适用于规模比较小的集群。

3 Tree Bucket

该方法是从RUSHt演化过来的,主要是为了解决规模比较大的环境,查找复杂度为O(logn)。Tree buckets中的元素被组织成一个加权的二叉查找树,所有的项都位于叶子节点。每一个内部节点都知道他左右子树的权重,并且按照固定的策略打上标签。

当需要从bucket众选出一项时,CRUSH从root节点开始查找副本的位置,它先得到节点的左子树的权重Wl,得到节点的权重Wn,然后根据hash(x, r, node_id)得到一个[0~1]的值v,假如这个值v在[0~Wl/Wn)中,则副本在左子树中,否者在右子树中。继续遍历节点,直到到达叶子节点。Tree Bucket的关键是当添加删除叶子节点时,决策树中的其他节点的node_id不变。二叉树中节点的node_id的标识是根据对二叉树的中序遍历来决定的(node_id不等于item的id,也不等于节点的权重)。

二叉树的节点的标签方法使用的是一个简单固定的方法以避免树中有节点增加或者节点减少而导致其他节点标签的变化。这个规则很简单:
1)树中最左侧的叶子节点永远是1
2)每次树增长的时候都会产生一个的新的根节点,之前的根节点会变成新根节点的左孩子。新的根节点的标签等于老的根节点的标签向左移一位(1,10,100,etc)。树的右侧的标签会复制左侧节点的标签并在最左侧在加上一个1。

tree bucket在查询性能上相比于list要好,而且数据迁移的控制也比较好。当一个节点发生变化时,只会导致节点所在子树上发生数据迁移。

4 Straw Bucket

这种类型让Bucket所包含的所有item公平的竞争(不像list和tree一样需要遍历)。这种算法就像抽签一样,所有的item都有机会被抽中(只有最长的签才能被抽中)。每个签的长度是由f(Wi)*hash(x, r, i) 决定的,Wi是item i的权重,i是item的id号。c(r, x) = MAX(f(Wi) * hash(x, r, i))。目前,这种Bucket是Ceph默认使用的Bucket,所以它也是经过大规模测试的,稳定性较好。虽然它的查询性能不如List和Tree,但它在控制数据迁移方面是最优的。

0 0
原创粉丝点击