归置组是如何使用的?

    存储池内的归置组( PG )把对象汇聚在一起,因为跟踪每一个对象的位置及其元数据需要大量计算——即一个拥有数百万对象的系统,不可能在对象这一级追踪位置。

    Ceph 客户端会计算某一对象应该位于哪个归置组里,它是这样实现的,先给对象 ID 做哈希操作,然后再根据指定存储池里的 PG 数量、存储池 ID 做一个运算。

    PG 映射到 OSD
    每个存储池都有很多归置组, CRUSH 动态的把它们映射到 OSD 。 Ceph 客户端要存对象时, CRUSH 将把各对象映射到某个归置组。

    把对象映射到归置组在 OSD 和客户端间创建了一个间接层。由于 Ceph 集群必须能增大或缩小、并动态地重均衡。如果让客户端“知道”哪个 OSD 有哪个对象,就会导致客户端和 OSD 紧耦合;相反, CRUSH 算法把对象映射到归置组、然后再把各归置组映射到一或多个 OSD ,这一间接层可以让 Ceph 在 OSD 守护进程和底层设备上线时动态地重均衡。下列图表描述了 CRUSH 如何将对象映射到归置组、再把归置组映射到 OSD 。

    计算 PG ID
    Ceph 客户端绑定到某监视器时,会索取最新的集群运行图副本,有了此图,客户端就能知道集群内的所有监视器、 OSD 、和元数据服务器。然而它对对象的位置一无所知。

    对象位置是计算出来的。
    客户端只需输入对象 ID 和存储池,此事简单: Ceph 把数据存在某存储池(如 liverpool )中。当客户端想要存命名对象(如 john 、 paul 、 george 、 ringo 等等)时,它用对象名,一个哈希值、 存储池中的归置组数、存储池名计算归置组。 Ceph 按下列步骤计算 PG ID 。

    客户端输入存储池 ID 和对象 ID (如 pool=”liverpool” 和 object-id=”john” );
    CRUSH 拿到对象 ID 并哈希它;
    CRUSH 用 PG 数(如 58 )对哈希值取模,这就是归置组 ID ;
    CRUSH 根据存储池名取得存储池 ID (如liverpool = 4 );
    CRUSH 把存储池 ID 加到PG ID(如 4.58 )之前。
    计算对象位置远快于查询定位, CRUSH 算法允许客户端计算对象应该存到哪里,并允许客户端连接主 OSD 来存储或检索对象。

    1. (OSDs * 100)
    2. Total PGs = ------------
    3. pool size

    其结果汇总后应该接近 2 的幂。汇总并非强制的,如果你想确保所有归置组内的对象数大致相等,最好检查下。

    比如,一个配置了 200 个 OSD 且副本数为 3 的集群,你可以这样估算归置组数量:

    1. (200 * 100)
    2. ----------- = 6667. Nearest power of 2: 8192
    3. 3

    当用了多个数据存储池来存储数据时,你得确保均衡每个存储池的归置组数量、且归置组数量分摊到每个 OSD ,这样才能达到较合理的归置组总量,并因此使得每个 OSD 无需耗费过多系统资源或拖慢连接进程就能实现较小变迁。