文件系统创建和扩展
过去一周左右的时间,我一直在改进整个“mkfs”过程,以及调整数据分布所需的一些机制,当集群的大小增加一个数量级或更多时。基本问题是,数据分布是一个两步过程:对象首先静态映射到许多“放置组”(PG)之一,然后 PG 会随着存储的添加或删除、磁盘故障等,在存储节点之间进行某种动态移动。
点击标题以阅读更多…
首先,新 PG 的创建必须是一个可靠的过程,即使在数百或数千个设备上创建数千或数百万个 PG 时也是如此,并且像所有其他操作一样,必须能够在设备故障的情况下保持鲁棒性。为了确保以有序的方式发生这种情况,监控集群现在跟踪应该存在哪些 PG 及其当前状态(例如,它们包含多少数据、是否已完全复制等),包括哪些 PG 正在等待创建。然后,监控程序将 PGCreate 消息发送到 OSD 以启动新 PG 的创建。如果创建成功,则通过标准的 PG 状态报告机制(用于磁盘空间“df”统计)将通知发送到监控程序。
PG 创建有点棘手,因为 OSD 需要确定 PG 是否已经存在(可能包含一些数据),然后才能在本地创建 PG 并声明它为空。为了确保这一点,监控程序会记录 PG 在逻辑上创建时 OSD 映射的 epoch,并在 PGCreate 消息中将其传递给 OSD。OSD 确定自该 epoch 以来 PG 将映射到哪些其他 OSD(如果有),并首先显式查询它们,以确保 PG 尚未存在。当确定可以安全进行时,PG 会在本地创建,副本会收到通知,并且任何等待 PG 的读/写操作都可以继续。监控程序会定期重新发送 PGCreate 消息,以处理 OSD 在响应之前失败的情况。
这处理了初始文件系统创建 (mkfs) 过程期间 PG 的初始创建。但是,随着文件系统的增长,PG 也可能会在稍后创建。例如,如果存储集群最初由 8 个存储节点 (OSD) 和 800 个 PG 组成,那么每个节点大约有 100 个 PG,这是设备利用率方差和设备对等之间良好平衡的粗略目标。但是,如果集群最终增长到 80 个节点,那么每个设备只剩下 10 个(非常大)PG,这可能不是最佳的。
在这种情况下,我们希望通过“拆分”现有的 PG 为更小的部分来增加 PG 的数量。这通过增加 OSD 映射中的 pg_num 参数来完成。但是,由于我们希望最初将新的 PG 与其父 PG 放置在同一位置(以使“拆分”过程简单),因此我们保持 pgp_num(第二个 p 用于放置)不变。随着映射更新的传播,集群中的 OSD 通过重新计算对象到 PG 的映射来拆分现有的 PG。这基本上就像一个位掩码(哈希函数输出的最低有效位确定 PG),但有一些小的智能,允许 pg_num 和 pgp_num 具有任何值(不只是 2 的幂)。
无论如何,一旦现有的 PG 被拆分形成新的总计 pg_num 个 PG,pgp_num 就可以增加到与 pg_num 匹配,从而允许将新的 PG 独立映射到存储节点。由于此过程由管理员启动,因此也可以逐步完成(因为拆分和迁移步骤都会给集群带来负载)。例如,在我们的 8 个 OSD 和 80 个 PG 的示例中,我们可能会缓慢地将 PG 计数增加到 128,每次增加 16 个(PG 16-63 将拆分为 PG 80-127)。完成后,我们现在有了所需的 PG 计数,但由于 pgp_num 未更改,数据仍然像我们只有 80 个 PG 一样在设备之间分布。然后,我们可以缓慢地将 pgp_num 增加到 128,每次增加一小步,以便一次只迁移少量 PG 在设备之间。
缓慢地增加这些值是自动化的一些示例,但目前,我只是在努力将所有基本功能都到位。像往常一样,重新设计 PG 创建以使其更加健壮,也愉快地导致了一些清理和 OSD 对等和恢复代码中的一些错误修复。进展!
接下来,调整控制如何为每个 PG 选择 OSD 的 CRUSH 映射…
