3.4.2 放置组的计算方法
CRUSH会为每个对象计算放置组,但实际上不知道该放置组所在的每个OSD中存储了多少数据,因此放置组数与OSD数之比可能会影响数据的分布。例如,如果3个副本存储池中只有一个放置组,而Ceph集群有N个OSD,则Ceph只使用3个OSD来存储数据。因为CRUSH别无选择,只能使用唯一的放置组。当有更多的放置组可用时,CRUSH有可能在OSD上均匀分布数据。
OSD与放置组数量的比例调整不能解决数据分布不均问题,因为CRUSH没有考虑对象的大小。使用Librados接口存储一些容量相对较小的对象和一些容量非常大的对象可能会导致数据分布不均。例如,在10个OSD上的1000个放置组中平均分配100万个4KB对象,空间总计4GB,每个OSD上使用400MB的存储空间。如果将这100万个对象中的1个对象大小调整为400MB,则存放该对象的放置组对应的3个OSD上的对象数据大小都是800MB,而其余7个OSD上的对象数据大小还是400MB,这就导致数据分布不均匀。Ceph使用RBD时,默认对象的大小为固定值4MB,将一个块设备以4MB为单位切割,最后写入底层时都按照4MB的基本单位操作。按照放置组均匀分布,就能保证集群数据在集群内均匀分布。Ceph文件存储和对象存储的对象没有固定4MB的大小限制。
注意 推荐一个OSD中配置的放置组数量为100~200,否则影响计算性能。
以上讲述了很多关于放置组数量的问题,那么在一个已知容量规模的Ceph集群中如何计算出合理的放置组数量呢?计算Ceph集群总放置组的公式如下:
举两个示例说明:
1)一个Ceph集群有100个OSD(可理解为100块盘,通常一块盘启动1个OSD进程),推荐每个OSD配置100~200个放置组。假设放置组数取值100,集群采用3副本进行数据冗余,那么集群放置组需配置3333(100×100/3)个。注意,此值要取2的幂次方(要取大于3333的2的幂次方),距离3333最近的2的幂次方数为4096,因此集群最大的放置组数为4096。
2)一个Ceph集群有100个OSD(可理解为100块盘,通常一块盘启动1个OSD进程),推荐每个OSD配置100~200个放置组。假设放置组数取值100,采用4+2纠删码方式进行数据冗余,那么集群放置组需配置1666(100×100/(4+2))个。注意,此值要取大于1666的2的幂次方数,距离1666最近的2的幂次方数为2048,因此集群最大的放置组数为2048。
知道了集群中一共可以有多少个放置组,那么放置组如何分给存储池呢?你可以按照集群中存储池的数量进行数据存储百分比规划,然后将放置组数量乘以此百分比算出每个存储池中的放置组数量。
以上面的例子为例继续分析,对于100个OSD、3副本集群,最多配置4096个放置组,假设你规划了两个存储池,其中存储池A预计存储量占整个集群存储量的75%,那么存储池A的放置组数为3072。存储池B预计存储量占整个集群存储量的25%,那么存储池B的放置组数为1024。通常,存储池的放置组数要设置为2的幂次方,如果存储池A的放置组数向上调整,那么集群总的放置组数将大于之前计算的值。如果这样强制设置放置组,集群会报告too many PGs per OSD,因此要向下调整存储池A的放置组数,即调整为2048。
Ceph也提供了参数mon_target_pg_per_osd对OSD上放置组数量进行限制。target_size_bytes参数可以对存储池的容量进行硬限制,即限制存储池最大使用容量。