在生产环境里,一个ceph的pool里有大量数据,当添加一些新的osd到集群里时,总是报告WARNING信息,这时为了消除这个告警信息, 就使用一下命令来增加该pool的pg的数量。
ceph osd pool set ${pool_name} pg_num
这里就有一个疑问,当pg的数量增加后,对于对象的寻址怎么处理?
ceph的对象的寻址是分两步:
1) 通过对象的oid 的 hash值,求余数
hash(oid) % pg_num --> pg_id
2)根据crush算法, 获取pg 到 osd列表
crush( pg_id, osdmap) --> osd_list( osd1, osd2, osd3)
实际上,在寻找操作的第一步中,对象映射到pg是静态hash映射的过程。当增加一个pool里的pg的数量,也就是公式里的 pg_num 增大时, 读取已经存在的对象时,可能映射到不同的pg里,从而导致读取错误。
PG split
其实,pg的增加,并不是简单的修改pg_num 就可以了。PG的增加,导致旧的PG的分裂,并且以2的幂次方分裂。这种分裂方式类似于Extensible Hash。在旧的pg分裂出一个新的个pg后,两个pg 的 acting osd列表是完全一致的。
当pg分裂后,会导致对象在一个osd内,旧pg会把一半的数据迁移到新的pg,这种pg的迁移是在同一个osd内迁移,也就是在同一个本地问及系统上,只是用rename操作而已,仅仅是本地文件系统的元数据操作,所以可以比较快的完成。