修改环分区能力¶
环分区能力决定了数据文件在磁盘上的位置,并在创建新环时选择。在正常操作中,它是一个固定值。这是因为不同的分区能力会导致所有数据文件在磁盘上的位置都不同。
但是,可以通过选择位于同一磁盘上的位置来将分区能力增加 1。因此,我们可以为新旧位置创建硬链接,在不影响可用性的情况下避免数据移动。
为了在不中断用户访问的情况下启用分区能力更改,对象服务器需要提前知道它。因此,分区能力更改需要分多个步骤进行。
注意
不要在账户和容器环上增加分区能力。增加分区能力仅支持对象环。尝试增加账户和容器环的 part_power 将会导致不可用,甚至可能导致数据丢失。
注意事项¶
在增加分区能力之前,请考虑可能的缺点。增加分区能力时有一些注意事项
集群中的几乎所有磁盘文件都需要重新链接然后清理,并且所有分区目录都需要重新哈希。这会对对象服务器施加显著的 I/O 负载,可能会影响客户端请求。请考虑使用 cgroups、
ionice,甚至只是内置的--files-per-second速率限制来减少对客户端的影响。对象复制器和重构器将在分区能力增加期间跳过受影响的策略。复制器不知道硬链接,只会简单地复制内容;这将导致大量数据移动,最坏的情况是所有数据都存储两次。
由于每个对象现在将从两个位置进行硬链接,因此会暂时使用更多的 inode - 预计大约是两倍。您需要在增加分区能力之前检查空闲 inode 计数。即使在增加完成并且额外的硬链接被清理后,也预计 inode 使用量会增加,因为会有两倍多的分区和后缀目录。
此外,对象审计器在清理删除第二个硬链接之前,可能会读取每个对象两次。
由于新的 inode,需要更多的内存来缓存它们,并且您的对象服务器应该有足够的可用内存来避免耗尽 inode 缓存。将
vfs_cache_pressure设置为 1 可能会有所帮助。集群中的所有节点都必须运行 Swift 2.13.0 或更高版本。
由于这些注意事项,您应该仅在真正需要时增加分区能力,例如,如果每个磁盘上的分区数极低并且数据在磁盘上分布不均匀。
1. 准备分区能力增加¶
swift-ring-builder 用于准备环以进行即将到来的分区能力增加。它将存储一个名为 next_part_power 的新变量,其值为当前分区能力 + 1。对象服务器识别到这一点,并且会在每次 PUT 或 DELETE 操作时创建(或删除)到新位置的硬链接。这将能够使用未来的分区能力访问新写入的对象
swift-ring-builder <builder-file> prepare_increase_partition_power
swift-ring-builder <builder-file> write_ring
现在您需要将更新后的 .ring.gz 复制到所有节点。已经存在的数据也需要重新链接;因此,操作员必须在此阶段在所有对象服务器上运行一个重新链接命令
swift-object-relinker relink
注意
在所有服务器重新读取修改后的环文件后开始重新链接,这通常在写入修改后的环文件后 15 秒内发生。此外,请确保将修改后的环推送到所有运行对象服务的节点(复制器、重构器和调解器)- 它们必须在重新链接期间跳过该策略。
注意
重新链接命令必须以与守护进程相同的用户身份运行(通常是 swift)。它将创建文件和目录,这些文件和目录必须可由守护进程(服务器、审计器、复制器等)操作。如果需要,可以使用 --user 选项来降低权限。
重新链接可能需要一些时间;虽然没有数据被复制或实际移动,但该工具仍然需要遍历整个文件系统并根据需要创建新的硬链接。
2. 增加分区能力¶
现在所有现有数据都可以使用新位置找到,是时候实际增加分区能力了
swift-ring-builder <builder-file> increase_partition_power
swift-ring-builder <builder-file> write_ring
现在您需要再次将更新后的 .ring.gz 复制到所有节点。对象服务器现在正在使用新的、增加的分区能力,并且不再创建额外的硬链接。
注意
对象服务器将为每个修改或新对象创建额外的硬链接,这需要更多的 inode。
注意
如果您决定不想增加分区能力,则应改为取消增加。一旦开始,就无法撤销此操作。要中止分区能力增加,请执行以下命令,将更新后的 .ring.gz 文件复制到所有节点,然后继续执行 3. 清理
swift-ring-builder <builder-file> cancel_increase_partition_power
swift-ring-builder <builder-file> write_ring
3. 清理¶
旧位置的现有硬链接需要删除,并提供了一个清理工具来执行此操作。在每个存储节点上运行以下命令
swift-object-relinker cleanup
注意
清理必须在您的对象服务器的 reclaim_age 期间内完成(默认情况下为 1 周)。否则,在步骤 #1 和步骤 #2 之间被覆盖然后删除的对象将无法再清理。您可能需要在重新链接之前或期间增加您的 reclaim_age。
之后,需要最后一次更新环,以告知服务器所有增加分区能力的步骤都已完成,并且复制器应恢复其工作
swift-ring-builder <builder-file> finish_increase_partition_power
swift-ring-builder <builder-file> write_ring
现在您需要再次将更新后的 .ring.gz 复制到所有节点。
背景¶
当前位于分区 X 上的现有对象在增加分区能力后将放置在分区 2*X 或 2*X+1 上。原因是 Ring.get_part() 方法,它执行右移位运算。
为了避免实际的数据移动到不同的磁盘甚至节点,需要更改分区到节点的分配。分配是成对的,因为上述新的分区方案。因此,设备的分配方式如下,分区是索引,值是设备 ID
old new
part dev part dev
---- --- ---- ---
0 0 0 0
1 0
1 3 2 3
3 3
2 7 4 7
5 7
3 5 6 5
7 5
4 2 8 2
9 2
5 1 10 1
11 1
有一个辅助方法来计算新的路径,以下示例显示了旧位置和新位置之间的映射
>>> from swift.common.utils import replace_partition_in_path
>>> old='objects/16003/a38/fa0fcec07328d068e24ccbf2a62f2a38/1467658208.57179.data'
>>> replace_partition_in_path('', '/sda/' + old, 14)
'objects/16003/a38/fa0fcec07328d068e24ccbf2a62f2a38/1467658208.57179.data'
>>> replace_partition_in_path('', '/sda/' + old, 15)
'objects/32007/a38/fa0fcec07328d068e24ccbf2a62f2a38/1467658208.57179.data'
使用原始分区能力 (14),它返回了相同的路径;但是,增加到 15 后,它返回新的路径,并且新的分区是 2*X+1。