且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Ceph分布式存储实战3.3 CRUSH关系分析

更新时间:2022-09-08 10:25:38

3.3 CRUSH关系分析


从本质上讲,CRUSH算法是通过存储设备的权重来计算数据对象的分布的。在计算过程中,通过Cluster Map(集群映射)、Data Distribution Policy(数据分布策略)和给出的一个随机数共同决定数据对象的最终位置。

1. Cluster Map

Cluster Map记录所有可用的存储资源及相互之间的空间层次结构(集群中有多少个机架、机架上有多少服务器、每个机器上有多少磁盘等信息)。所谓的Map,顾名思义,就是类似于我们生活中的地图。在Ceph存储里,数据的索引都是通过各种不同的Map来实现的。另一方面,Map 使得Ceph集群存储设备在物理层作了一层防护。例如,在多副本(常见的三副本)的结构上,通过设置合理的Map(故障域设置为Host级),可以保证在某一服务器死机的情况下,有其他副本保留在正常的存储节点上,能够继续提供服务,实现存储的高可用。设置更高的故障域级别(如Rack、Row等)能保证整机柜或同一排机柜在掉电情况下数据的可用性和完整性。

(1)Cluster Map的分层结构

Cluster Map由Device和Bucket构成。它们都有自己的ID和权重值,并且形成一个以Device为叶子节点、Bucket为躯干的树状结构,如图3-3所示。

 

图3-3 CRUSH架构图

Bucket拥有不同的类型,如Host、Row、Rack、Room等,通常我们默认把机架类型定义为Rack,主机类型定义为Host,数据中心(IDC机房)定义为Data Center。Bucket的类型都是虚拟结构,可以根据自己的喜好设计合适的类型。Device节点的权重值代表了存储设备的容量与性能。其中,磁盘容量是权重大小的关键因素。

OSD 的权重值越高,对应磁盘会被分配写入更多的数据。总体来看,数据会被均匀写入分布于群集所有磁盘,从而提高整体性能和可靠性。无论磁盘的规格容量,总能够均匀使用。

关于OSD权重值的大小值的配比,官方默认值设置为1TB容量的硬盘,对应权重值为1。

可以在/etc/init.d/ceph 原码里查看相关的内容。

363             get_conf osd_weight "" "osd crush initial weight"

364             defaultweight="$(df -P -k $osd_data/. | tail -1 | awk '{ print sprintf("%.2f",$2/1073741824) }')"  ###此处就是ceph默认权重的设置值

            get_conf osd_keyring "$osd_data/keyring" "keyring"

366             do_cmd_okfail "timeout 30 $BINDIR/ceph -c $conf --name=osd.$id --keyring=$osd_keyring     osd crush create-or-move -- $id ${osd_weight:-${defaultweight:-1}} $osd_location"

(2)恢复与动态平衡

在默认设置下,当集群里有组件出现故障时(主要是OSD,也可能是磁盘或者网络等),Ceph会把OSD标记为down,如果在300s内未能回复,集群就会开始进行恢复状态。这个“300s”可以通过“mon osd down out interval”配置选项修改等待时间。PG(Placement  Groups)是Ceph数据管理(包括复制、修复等动作)单元。当客户端把读写请求(对象单元)推送到Ceph时,通过CRUSH提供的Hash算法把对象映射到PG。PG在CRUSH策略的影响下,最终会被映射到OSD上。

2. Data Distribution Policy

Data Distribution Policy由Placement Rules组成。Rule决定了每个数据对象有多少个副本,这些副本存储的限制条件(比如3个副本放在不同的机架中)。一个典型的rule如下所示。

rule replicated_ruleset {    ##rule名字

    ruleset 0         # rule的Id

    type replicated   ## 类型为副本模式,另外一种模式为纠删码(EC)

    min_size 1        ## 如果存储池的副本数大于这个值,此rule不会应用

    max_size 10       ## 如要存储池的副本数大于这个值,此rule不会应用

    step take default  ## 以default root为入口

    step chooseleaf firstn 0 type host  ## 隔离域为host级,即不同副本在不同的主机上

    step emit        ## 提交

}

根据实际的设备环境,可以定制出符合自己需求的Rule,详见第10章。

3. CRUSH中的伪随机

先来看一下数据映射到具体OSD的函数表达形式。

CRUSH(x) -> (osd1, osd2, osd3.....osdn)  

CRUSH使用了多参数的Hash函数在Hash之后,映射都是按既定规则选择的,这使得从x到OSD的集合是确定的和独立的。CRUSH只使用Cluster Map、Placement Rules、X。CRUSH是伪随机算法,相似输入的结果之间没有相关性。关于伪随机的确认性和独立性,以下我们以一个实例来展示。

 [root@host-192-168-0-16 ~]# ceph osd tree

ID WEIGHT  TYPE NAME               UP/DOWN  REWEIGHT  PRIMARY-AFFINITY

-1 0.35999 root default                                                 

-3 0.09000     host host-192-168-0-17                                   

 2 0.09000         osd.2                   up  1.00000          1.00000

-4 0.09000     host host-192-168-0-18                                   

 3 0.09000         osd.3                   up  1.00000          1.00000

-2 0.17999     host host-192-168-0-16                                   

 0 0.09000         osd.0                   up  1.00000          1.00000

 1 0.09000         osd.1                   up  1.00000          1.00000

以上是某个Ceph集群的存储的CRUSH结构。在此集群里我们手动创建一个pool,并指定为8个PG和PGP。

[root@host-192-168-0-16 ~]# ceph  osd pool create  crush  8   8

pool 'crush' created

PGP是PG的逻辑承载体,是CRUSH算法不可缺少的部分。在Ceph集群里,增加PG数量,PG到OSD的映射关系就会发生变化,但此时存储在PG里的数据并不会发生迁移,只有当PGP的数量也增加时,数据迁移才会真正开始。关于PG和PGP的关系,假如把PG比作参加宴会的人,那么PGP就是人坐的椅子,如果人员增加时,人的座位排序就会发生变化,只有增加椅子时,真正的座位排序变更才会落实。因此,人和椅子的数量一般都保持一致。所以,在Ceph里,通常把PGP和PG设置成一致的。

可以查看PG映射OSD的集合,即PG具体分配到OSD的归属。

 [root@host-192-168-0-16 ~]# ceph pg dump | grep ^22\. | awk '{print $1 "\t"   $17}'    ## 22 表示 Pool id ##

dumped all in format plain

22.1 [1,2,3]    

22.0   [1,2,3]

22.3 [3,1,2]

22.2 [3,2,0]

22.5 [1,3,2]

22.4 [3,1,2]

22.7 [2,1,3]

22.6 [3,0,2]

上面示例中,第一列是PG的编号(其中22表示的Pool的ID),共计8个,第二列是PG映射到了具体的OSD集合。如“22.1 [1,2,3]”表示PG 22.1分别在OSD1、OSD2和OSD3分别存储副本。

在Ceph集群里,当有数据对象要写入集群时,需要进行两次映射。第一次从object→PG,第二次是PG→OSD set。每一次的映射都是与其他对象无相关的。以上充分体现了CRUSH的独立性(充分分散)和确定性(可确定的存储位置)。