放置组
将数百万个对象存储在集群中并单独管理这些对象是资源密集型的。 Ceph 使用布置组 (PGs) 来提高管理大量对象的效率。
PG 是用于包含对象集合的池的子集。 Ceph 将池分片到一系列 PGs 中。 然后, CRUSH 算法将集群映射和集群状态考虑在内,并将 PGs 均匀和伪随机分布到集群中的 OSD。
以下是其工作方式:
当系统管理员创建池时, CRUSH 会为池创建用户定义的 PGs 数。 通常, PGs 的数量应该是合理细颗粒度的数据子集。 例如,每个池每个 OSD 100 个 PGs 表示每个 PG 包含大约 1% 的池数据。
当 Ceph 需要将 PG 从一个 OSD 移动到另一个 OSD 时, PGs 的数量会影响性能。 如果池中的 PGs 太少,那么 Ceph 将同时移动很大百分比的数据,并且网络负载将对集群的性能产生负面影响。 如果池具有过多的 PGs ,那么 Ceph 在移动微小百分比的数据时将使用过多的 CPU 和 RAM ,从而对集群的性能产生负面影响。 有关计算 PGs 数量以实现最佳性能的详细信息,请参阅 PG 计数
Ceph 通过存储对象的副本或存储对象的擦除代码块来确保避免数据丢失。 由于 Ceph 将对象的对象或擦除代码块存储在 PGs 中,因此 Ceph 会为对象的每个副本或对象的每个擦除代码块复制一组 OSD (称为 代理集 ) 中的每个 PG。 系统管理员可以确定池中的 PGs 数以及副本或擦除代码块数。 但是, CRUSH 算法计算特定 PG 的作用集中有哪些 OSD。
CRUSH 算法和 PGs 使 Ceph 成为动态的。 集群映射或集群状态的更改可能会导致 Ceph 将 PGs 从一个 OSD 自动移动到另一个 OSD。
下面是几个示例:
展开集群: 将新主机及其 OSD 添加到集群时,集群映射会发生更改。 由于 CRUSH 均匀且伪随机地将 PGs 分发到整个集群中的 OSD ,因此添加新主机及其 OSD 意味着 CRUSH 会将池的部分放置组重新分配给这些新 OSD。 这意味着系统管理员不必手动重新均衡集群。 另外,这意味着新的 OSD 包含与其他 OSD 大致相同的数据量。 这也意味着新的 OSD 不包含新写入的 OSD ,从而阻止集群中的 热点 。
OSD 失败: 当 OSD 失败时,集群的状态会更改。 Ceph 暂时丢失其中一个副本或擦除代码块,需要制作另一个副本。 如果操作集中的主 OSD 失败,那么操作集中的下一个 OSD 将成为主 OSD ,并且 CRUSH 将计算新的 OSD 以存储额外的副本或擦除代码块。
通过在数百到数千个 PGs 的上下文中管理数百万个对象, Ceph 存储集群可以高效地增长,缩小和恢复故障。
对于 Ceph 客户机,通过 librados 的 CRUSH 算法使读取和写入对象的过程非常简单。 Ceph 客户机只是将对象写入池或从池中读取对象。 操作集中的主 OSD 可以代表 Ceph 客户机将对象的副本或对象的擦除代码块写入操作集中的辅助 OSD。
如果集群映射或集群状态更改,那么 OSD 存储 PG 的 CRUSH 计算也将更改。 例如, Ceph 客户机可能会将对象 foo 写入池 bar。 CRUSH 将对象分配给 PG 1.a,并将其存储在 OSD 5上,这将使副本分别位于 OSD 10 和 OSD 15 上。 如果 OSD 5 失败,那么集群状态会更改。 当 Ceph 客户机从池 bar读取对象 foo 时,客户机将通过 librados 自动从 OSD 10 将其作为新的主 OSD 动态检索。
通过 librados 的 Ceph 客户机在写入和读取对象时直接连接到操作集中的主 OSD。 由于 I/O 操作不使用集中代理,因此网络超额预订通常不是 Ceph 的问题。
下图描述了 CRUSH 如何将对象分配给 PGs ,以及将 PGs 分配给 OSD。 CRUSH 算法将 PGs 分配给 OSD ,以便代理集中的每个 OSD 都位于单独的故障域中,这通常意味着 OSD 将始终位于单独的服务器主机上,有时位于单独的机架中。
