注意
本文档适用于 Ceph 的开发版本。
故障排除 PG
放置组永不处于 Clean 状态
放置组 (PG) 保持在 active 状态、active+remapped 状态或 active+degraded 状态,并且永远无法达到 active+clean 状态,这可能表明 Ceph 集群配置存在问题。
在这种情况下,请查看池、PG 和 CRUSH 配置参考中的设置并进行适当调整。
通常,您的集群应运行多个 OSD,并且池大小大于两个对象副本。
单节点集群
Ceph 不再提供有关在单个节点上操作的文档。顾名思义,专为分布式计算设计的系统不会在单个节点上运行。在包含 Ceph 守护程序的单个节点上挂载客户端内核模块可能会由于 Linux 内核本身的问题而导致死锁(除非使用 VM 作为客户端)。尽管有此处所述的限制,您仍然可以在单节点配置中试验 Ceph。
要在单个节点上创建集群,您必须在创建监视器和 OSD 之前,将 Ceph 配置文件中的 osd_crush_chooseleaf_type 设置从默认值 1(表示 host 或 node)更改为 0(表示 osd)。这会告诉 Ceph 允许 OSD 将另一个 OSD 放置在同一主机上。如果您尝试设置单节点集群,并且 osd_crush_chooseleaf_type 大于 0,Ceph 将尝试根据设置将一个 OSD 的 PG 放置在另一个节点、机箱、机架、行或数据中心上的另一个 OSD 的 PG 中。
提示
切勿将内核客户端直接挂载到与 Ceph 存储集群相同的节点上。可能会出现内核冲突。但是,您可以在单个节点上的虚拟机 (VM) 中挂载内核客户端。
如果您使用单个磁盘创建 OSD,则必须首先手动创建数据目录。
OSD 数量少于副本数
如果有两个 OSD 处于 up 和 in 状态,但放置组不处于 active + clean 状态,则您的 osd_pool_default_size 可能设置为大于 2。
有几种方法可以解决这种情况。如果您想在具有两个副本的情况下以 active + degraded 状态运行集群,则可以将 osd_pool_default_min_size 设置为 2,以便您可以在 active + degraded 状态下写入对象。您也可以将 osd_pool_default_size 设置为 2,这样您就只有两个存储副本(原始副本和一个副本)。在这种情况下,集群应该达到 active + clean 状态。
注意
您可以在集群运行时进行更改。如果您在 Ceph 配置文件中进行更改,则可能需要重新启动集群。
池大小 = 1
如果您将 osd_pool_default_size 设置为 1,则您将只有一个对象副本。OSD 依赖其他 OSD 告诉它们应该拥有哪些对象。如果一个 OSD 拥有一个对象的副本,但没有第二个副本,则没有第二个 OSD 来告诉第一个 OSD 它应该拥有该副本。对于映射到第一个 OSD 的每个放置组(请参阅 ceph pg dump),您可以通过运行以下形式的命令来强制第一个 OSD 注意它需要的放置组
ceph osd force-create-pg <pgid>
CRUSH Map 错误
如果集群中的任何放置组处于非 clean 状态,则您的 CRUSH map 中可能存在错误。
卡住的放置组
在组件发生故障后,放置组进入“degraded”或“peering”状态是正常的。通常,这些状态反映了故障恢复过程中的预期进展。但是,放置组长时间保持在这些状态之一可能表明存在更大的问题。因此,当放置组“卡住”在非最佳状态时,Ceph Monitor 将发出警告。具体来说,我们检查以下情况
inactive- 放置组处于非active状态时间过长(即,它无法处理读/写请求)。unclean- 放置组处于非clean状态时间过长(即,它无法从先前的故障中完全恢复)。stale- 放置组状态未被ceph-osd更新。这表明存储此放置组的所有节点可能都处于down状态。
通过运行以下命令之一列出卡住的放置组
ceph pg dump_stuck stale
ceph pg dump_stuck inactive
ceph pg dump_stuck unclean
卡住的
stale放置组通常表示关键的ceph-osd守护程序未运行。卡住的
inactive放置组通常表示存在 peering 问题(请参阅放置组 Down - Peering 失败)。卡住的
unclean放置组通常表示有东西阻止恢复完成,可能是未找到的对象(请参阅未找到对象);
放置组 Down - Peering 失败
在某些情况下,ceph-osd *peering* 过程可能会遇到问题,从而阻止 PG 变为 active 并可用。在这种情况下,运行命令 ceph health detail 将报告类似于以下内容
ceph health detail
HEALTH_ERR 7 pgs degraded; 12 pgs down; 12 pgs peering; 1 pgs recovering; 6 pgs stuck unclean; 114/3300 degraded (3.455%); 1/3 in osds are down
...
pg 0.5 is down+peering
pg 1.4 is down+peering
...
osd.1 is down since epoch 69, last address 192.168.106.220:6801/8651
通过运行以下形式的命令查询集群以确定 PG 被标记为 down 的确切原因
ceph pg 0.5 query
{ "state": "down+peering",
...
"recovery_state": [
{ "name": "Started\/Primary\/Peering\/GetInfo",
"enter_time": "2012-03-06 14:40:16.169679",
"requested_info_from": []},
{ "name": "Started\/Primary\/Peering",
"enter_time": "2012-03-06 14:40:16.169659",
"probing_osds": [
0,
1],
"blocked": "peering is blocked due to down osds",
"down_osds_we_would_probe": [
1],
"peering_blocked_by": [
{ "osd": 1,
"current_lost_at": 0,
"comment": "starting or marking this osd lost may let us proceed"}]},
{ "name": "Started",
"enter_time": "2012-03-06 14:40:16.169513"}
]
}
recovery_state 部分告诉我们 peering 因 ceph-osd 守护程序 down 而被阻止,特别是 osd.1。在这种情况下,我们可以启动该特定的 ceph-osd,恢复将继续进行。
或者,如果 osd.1 发生灾难性故障(例如,发生磁盘故障),可以通知集群该 OSD lost,并且可以指示集群尽其所能应对。
重要
通知集群 OSD 已丢失是危险的,因为集群无法保证数据的其他副本一致且最新。
要报告 OSD lost 并指示 Ceph 无论如何都继续尝试恢复,请运行以下形式的命令
ceph osd lost 1
恢复将继续进行。
未找到对象
在某些故障组合下,Ceph 可能会抱怨 unfound 对象,如本例所示
ceph health detail
HEALTH_WARN 1 pgs degraded; 78/3778 unfound (2.065%)
pg 2.4 is active+degraded, 78 unfound
这意味着存储集群知道某些对象(或现有对象的较新副本)存在,但它没有找到它们的副本。这是一个 PG 如何发生的示例,其数据位于两个 OSD 上,我们称之为“1”和“2”
1 down
2 独自处理一些写入
1 up
1 和 2 重新 peering,1 上丢失的对象排队等待恢复。
在新对象被复制之前,2 down。
此时,1 知道这些对象存在,但没有活动的 ceph-osd 拥有这些对象的副本。在这种情况下,对这些对象的 IO 将被阻塞,集群希望失败的节点能尽快恢复。这被认为优于向用户返回 IO 错误。
注意
上面描述的情况是将复制池上的 size=2 和纠删码池上的 m=1 设置为冒险数据丢失的原因之一。
通过运行以下形式的命令来识别未找到的对象
ceph pg 2.4 list_unfound [starting offset, in json]
{
"num_missing": 1,
"num_unfound": 1,
"objects": [
{
"oid": {
"oid": "object",
"key": "",
"snapid": -2,
"hash": 2249616407,
"max": 0,
"pool": 2,
"namespace": ""
},
"need": "43'251",
"have": "0'0",
"flags": "none",
"clean_regions": "clean_offsets: [], clean_omap: 0, new_object: 1",
"locations": [
"0(3)",
"4(2)"
]
}
],
"state": "NotRecovering",
"available_might_have_unfound": true,
"might_have_unfound": [
{
"osd": "2(4)",
"status": "osd is down"
}
],
"more": false
}
如果单个结果中要列出的对象太多,则 more 字段将为 true,您可以查询更多内容。(最终命令行工具会向您隐藏此内容,但现在还没有。)
现在您可以识别已探测或可能包含数据的 OSD。
在列表末尾(在 more: false 之前),当 available_might_have_unfound 为 true 时,会提供 might_have_unfound。这等同于 ceph pg #.# query 的输出。这消除了直接使用 query 的需要。给出的 might_have_unfound 信息与 query 的行为方式相同,如下所述。唯一的区别是状态为 already probed 的 OSD 被忽略。
使用 query
ceph pg 2.4 query
"recovery_state": [
{ "name": "Started\/Primary\/Active",
"enter_time": "2012-03-06 15:15:46.713212",
"might_have_unfound": [
{ "osd": 1,
"status": "osd is down"}]},
在这种情况下,集群知道 osd.1 可能有数据,但它处于 down 状态。以下是所有可能的完整状态范围
already probed
querying
OSD is down
not queried (yet)
有时集群只是需要一些时间来查询可能的位置。
可能存在未列出的对象可能存在的其他位置。例如:如果一个 OSD 停止并从集群中取出,然后集群完全恢复,然后通过随后的故障集,集群最终得到一个未找到的对象,集群将忽略被移除的 OSD。(然而,这种情况不太可能发生。)
如果所有可能的位置都已查询,但对象仍然丢失,您可能不得不放弃丢失的对象。同样,这只有在发生异常的故障组合时才有可能,这些组合允许集群了解在写入本身恢复之前执行的写入。要将“unfound”对象标记为“lost”,请运行以下形式的命令
ceph pg 2.5 mark_unfound_lost revert|delete
这里的最后一个参数 (revert|delete) 指定集群应如何处理丢失的对象。
delete 选项将导致集群完全忘记它们。
revert 选项(不适用于纠删码池)将回滚到对象的先前版本,或者(如果它是一个新对象)完全忘记该对象。谨慎使用 revert,因为它可能会使期望对象存在的应用程序感到困惑。
无家可归的放置组
可能存储给定放置组副本的每个 OSD 都失败了。如果发生这种情况,则包含这些放置组的对象存储子集将变得不可用,并且监视器将不会收到这些放置组的状态更新。监视器会将其主 OSD 失败的任何放置组标记为 stale。例如
ceph health
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
通过运行以下命令来识别哪些放置组是 stale 的以及哪些是最后存储 stale 放置组的 OSD
ceph health detail
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
...
pg 2.5 is stuck stale+active+remapped, last acting [2,0]
...
osd.10 is down since epoch 23, last address 192.168.106.220:6800/11080
osd.11 is down since epoch 13, last address 192.168.106.220:6803/11539
osd.12 is down since epoch 24, last address 192.168.106.220:6806/11861
此输出表明放置组 2.5 (pg 2.5) 最后由 osd.0 和 osd.2 管理。重新启动这些 OSD 以允许集群恢复该放置组。
只有少数 OSD 接收数据
如果集群中只有少数节点正在接收数据,请按照放置组文档中的说明检查池中放置组的数量。由于放置组映射到 OSD 的操作涉及将集群中放置组的数量除以集群中 OSD 的数量,因此少量放置组(此操作中的余数)有时不会分布在整个集群中。在这种情况下,请创建一个放置组计数是 OSD 数量倍数的池。有关详细信息,请参阅放置组。有关更改用于确定分配给每个池的放置组数量的默认值的说明,请参阅池、PG 和 CRUSH 配置参考。
无法写入数据
如果集群已启动,但某些 OSD 已关闭且您无法写入数据,请确保池中运行的 OSD 数量达到最低要求。如果您运行的 OSD 数量未达到池中的最低要求,Ceph 将不允许您向其写入数据,因为无法保证 Ceph 可以复制您的数据。有关详细信息,请参阅池、PG 和 CRUSH 配置参考中的 osd_pool_default_min_size。
PG 不一致
如果命令 ceph health detail 返回 active + clean + inconsistent 状态,这可能表示 scrubbing 期间发生错误。通过运行以下命令来识别不一致的放置组
ceph health detail
HEALTH_ERR 1 pgs inconsistent; 2 scrub errors
pg 0.6 is active+clean+inconsistent, acting [0,1,2]
2 scrub errors
或者,如果您更喜欢以编程方式检查输出,请运行此命令
rados list-inconsistent-pg rbd
["0.6"]
只有一种一致状态,但在最坏的情况下,我们可能会在多个透视图中发现多个对象中的不同不一致。如果 PG 0.6 中的名为 foo 的对象被截断,则 rados list-inconsistent-pg rbd 的输出将如下所示
rados list-inconsistent-obj 0.6 --format=json-pretty
{
"epoch": 14,
"inconsistents": [
{
"object": {
"name": "foo",
"nspace": "",
"locator": "",
"snap": "head",
"version": 1
},
"errors": [
"data_digest_mismatch",
"size_mismatch"
],
"union_shard_errors": [
"data_digest_mismatch_info",
"size_mismatch_info"
],
"selected_object_info": "0:602f83fe:::foo:head(16'1 client.4110.0:1 dirty|data_digest|omap_digest s 968 uv 1 dd e978e67f od ffffffff alloc_hint [0 0 0])",
"shards": [
{
"osd": 0,
"errors": [],
"size": 968,
"omap_digest": "0xffffffff",
"data_digest": "0xe978e67f"
},
{
"osd": 1,
"errors": [],
"size": 968,
"omap_digest": "0xffffffff",
"data_digest": "0xe978e67f"
},
{
"osd": 2,
"errors": [
"data_digest_mismatch_info",
"size_mismatch_info"
],
"size": 0,
"omap_digest": "0xffffffff",
"data_digest": "0xffffffff"
}
]
}
]
}
在这种情况下,输出指示以下内容
唯一不一致的对象名为
foo,并且其 head 具有不一致性。不一致性分为两类
errors: 这些错误指示分片之间的不一致性,没有指示哪个分片是坏的。检查shards数组中的errors(如果可用)以查明问题。data_digest_mismatch: 从OSD.2读取的副本的摘要与从OSD.0和OSD.1读取的副本的摘要不同size_mismatch: 从OSD.2读取的副本的大小为0,但OSD.0和OSD.1报告的大小为968。
union_shard_errors:shards数组中所有特定于分片的errors的并集。为有问题分片设置errors。这些错误包括read_error和其他类似错误。以oi结尾的errors表示与selected_object_info进行比较。检查shards数组以确定哪个分片具有哪个或哪些错误。data_digest_mismatch_info: 存储在object-info中的摘要不是0xffffffff,后者是从OSD.2读取的分片计算得出的size_mismatch_info: 存储在object-info中的大小与从OSD.2读取的大小不同。后者为0。
警告
如果分片的 errors 属性中列出了 read_error,则不一致很可能是由于物理存储错误造成的。在这种情况下,请检查该 OSD 使用的存储。
在尝试修复驱动器之前,检查 dmesg 和 smartctl 的输出。
要修复不一致的放置组,请运行以下形式的命令
ceph pg repair {placement-group-ID}
例如
ceph pg repair 1.4
注意
PG ID 的形式为 N.xxxxx,其中 N 是包含 PG 的池的编号。命令 ceph osd listpools 和命令 ceph osd dump | grep pool 返回池编号列表。
如果您由于时钟偏差而定期收到 active + clean + inconsistent 状态,请考虑配置监视器主机上的 NTP 守护程序以充当对等体。有关详细信息,请参阅 网络时间协议和 Ceph 时钟设置。
有关 PG 修复的更多信息
Ceph 存储并更新存储在集群中的对象的校验和。当对 PG 执行 scrub 时,主 OSD 会尝试从其副本中选择一个权威副本。只有一种可能的情况是一致的。执行 deep scrub 后,Ceph 会计算从磁盘读取的每个对象的校验和,并将其与先前记录的校验和进行比较。如果当前校验和与先前记录的校验和不匹配,则该不匹配被视为不一致。对于复制池,任何对象的任何副本的校验和与权威副本的校验和之间的不匹配都意味着存在不一致性。发现这些不一致性会导致 PG 的状态设置为 inconsistent。
pg repair 命令尝试修复各种类型的不一致性。当 pg repair 找到不一致的 PG 时,它会尝试使用权威副本的摘要覆盖不一致副本的摘要。当 pg repair 在复制池中找到不一致的副本时,它会将不一致的副本标记为 missing。对于复制池,恢复超出了 pg repair 的范围。
对于纠删码和 BlueStore 池,如果 osd_scrub_auto_repair(默认 false)设置为 true 且发现的错误不超过 osd_scrub_auto_repair_num_errors(默认 5),Ceph 将自动执行修复。
pg repair 命令无法解决所有问题。当发现 PG 包含不一致性时,Ceph 不会自动修复 PG。
RADOS 对象或 omap 的校验和并不总是可用。校验和是增量计算的。如果复制对象非顺序更新,则更新涉及的写入操作会更改对象并使其校验和失效。在重新计算校验和时,不会读取整个对象。即使在没有校验和可用的情况下(例如 Filestore),pg repair 命令也能够进行修复。使用复制 Filestore 池的用户可能更喜欢手动修复而不是 ceph pg repair。
此材料与 Filestore 相关,但与 BlueStore 无关,BlueStore 有其自己的内部校验和。匹配记录校验和和计算的校验和无法证明任何特定副本实际上是权威的。如果没有可用的校验和,pg repair 会倾向于主副本上的数据,但这可能不是未损坏的副本。由于这种不确定性,当发现不一致性时,需要人工干预。这种干预有时涉及使用 ceph-objectstore-tool。
PG 修复演练
https://ceph.net.cn/geen-categorie/ceph-manually-repair-object/ - 此页面包含 PG 修复的演练。如果您想修复 PG 但从未这样做过,建议阅读此内容。
纠删码 PG 不处于 active+clean 状态
如果 CRUSH 无法找到足够的 OSD 来映射到 PG,它将显示为 2147483647,即 ITEM_NONE 或 no OSD found。例如
[2,1,6,0,5,8,2147483647,7,4]
OSD 数量不足
如果 Ceph 集群只有八个 OSD,而纠删码池需要九个 OSD,则集群将显示“Not enough OSDs”。在这种情况下,您可以创建另一个需要较少 OSD 的纠删码池,方法是运行以下形式的命令
ceph osd erasure-code-profile set myprofile k=5 m=3
ceph osd pool create erasurepool erasure myprofile
或添加新的 OSD,PG 将自动使用它们。
无法满足 CRUSH 约束
如果集群有足够的 OSD,则 CRUSH 规则可能施加了无法满足的约束。如果两个主机上有十个 OSD,并且 CRUSH 规则要求同一主机中没有两个 OSD 用于同一 PG,则映射可能会失败,因为只能找到两个 OSD。通过显示(“dumping”)规则来检查约束,如下所示
ceph osd crush rule ls
[
"replicated_rule",
"erasurepool"]
$ ceph osd crush rule dump erasurepool
{ "rule_id": 1,
"rule_name": "erasurepool",
"type": 3,
"steps": [
{ "op": "take",
"item": -1,
"item_name": "default"},
{ "op": "chooseleaf_indep",
"num": 0,
"type": "host"},
{ "op": "emit"}]}
通过创建新池来解决此问题,在该池中允许 PG 拥有驻留在同一主机上的 OSD,方法是运行以下命令
ceph osd erasure-code-profile set myprofile crush-failure-domain=osd
ceph osd pool create erasurepool erasure myprofile
CRUSH 过早放弃
如果 Ceph 集群有刚好足够的 OSD 来映射 PG(例如,总共有九个 OSD 的集群和一个每个 PG 需要九个 OSD 的纠删码池),则 CRUSH 可能会在找到映射之前放弃。可以通过以下方式解决此问题
降低纠删码池要求,每个 PG 使用更少的 OSD(这需要创建另一个池,因为纠删码配置文件无法动态修改)。
向集群添加更多 OSD(这不需要修改纠删码池,因为它会自动变为 clean)
使用手工制作的 CRUSH 规则,该规则会尝试更多次以找到好的映射。可以通过将
set_choose_tries设置为大于默认值的值来为现有 CRUSH 规则修改此设置。
首先,通过从集群中提取 crushmap 后使用 crushtool 来验证问题。这可确保您的实验不会修改 Ceph 集群,并且仅在本地文件上操作
ceph osd crush rule dump erasurepool
{ "rule_id": 1,
"rule_name": "erasurepool",
"type": 3,
"steps": [
{ "op": "take",
"item": -1,
"item_name": "default"},
{ "op": "chooseleaf_indep",
"num": 0,
"type": "host"},
{ "op": "emit"}]}
$ ceph osd getcrushmap > crush.map
got crush map from osdmap epoch 13
$ crushtool -i crush.map --test --show-bad-mappings \
--rule 1 \
--num-rep 9 \
--min-x 1 --max-x $((1024 * 1024))
bad mapping rule 8 x 43 num_rep 9 result [3,2,7,1,2147483647,8,5,6,0]
bad mapping rule 8 x 79 num_rep 9 result [6,0,2,1,4,7,2147483647,5,8]
bad mapping rule 8 x 173 num_rep 9 result [0,4,6,8,2,1,3,7,2147483647]
此处,--num-rep 是纠删码 CRUSH 规则需要的 OSD 数量,--rule 是 ceph osd crush rule dump 显示的 rule_id 字段的值。此测试将根据 CRUSH map 模拟多个 PG 放置。确切的计数基于 [--min-x,--max-x]。PG 放置彼此独立,仅基于哈希和存储桶算法。任何放置都可能自行失败。如果此测试没有输出任何内容,则所有映射都成功了,表明问题不是 CRUSH 映射。如果它确实输出了错误的映射,如上所示,则 Ceph 无法在当前拓扑中一致地放置 PG。只要并非所有映射都被认为是坏的,就可以配置 CRUSH 规则以搜索更长时间以找到可行的放置。
更改 set_choose_tries 的值
通过运行以下命令反编译 CRUSH map 以编辑 CRUSH 规则
crushtool --decompile crush.map > crush.txt为了说明目的,本例中将使用简化的 CRUSH map,模拟具有四个磁盘(3x1TiB 和 1x200GiB)的单个主机。下面的设置是专门为本例选择的,并且将与生产集群中通常找到的CRUSH Map 可调参数有所不同。由于默认值可能会更改,请参阅适用于您的 Ceph 版本的正确文档。
_
tunable choose_local_tries 0 tunable choose_local_fallback_tries 0 # artificially low total tries, for illustration tunable choose_total_tries 10 tunable chooseleaf_descend_once 1 tunable chooseleaf_vary_r 1 tunable chooseleaf_stable 1 tunable straw_calc_version 1 tunable allowed_bucket_algs 54 # devices device 0 osd.0 device 1 osd.1 device 2 osd.2 device 3 osd.3 # types type 0 osd type 1 host type 2 chassis type 3 rack type 4 row type 5 pdu type 6 pod type 7 room type 8 datacenter type 9 zone type 10 region type 11 root # buckets host example { id -2 alg straw2 hash 0 # rjenkins1 item osd.0 weight 1.00000 item osd.1 weight 1.00000 item osd.2 weight 1.00000 item osd.3 weight 0.20000 } root default { id -1 alg straw2 hash 0 # rjenkins1 item example weight 3.20000 } # rules rule ec { id 0 type erasure step set_chooseleaf_tries 5 # artificially low tries, for illustration step set_choose_tries 5 step take default step choose indep 0 type osd step emit }
将以下行添加到规则中
step set_choose_tries 100
如果该行已经存在,如本例所示,则只修改值。确保
crush.txt中的规则在更改后类似于此rule ec { id 0 type erasure step set_chooseleaf_tries 5 step set_choose_tries 100 step take default step choose indep 0 type osd step emit }
重新编译并重新测试 CRUSH 规则
crushtool --compile crush.txt -o better-crush.map当所有映射都成功时,通过使用
crushtool命令的--show-choose-tries选项显示查找所有映射所需的尝试次数的直方图,如以下示例所示crushtool -i better-crush.map --test --show-bad-mappings \ --show-choose-tries \ --rule 0 \ --num-rep 3 \ --min-x 1 --max-x 100: 0 1: 0 2: 4 3: 3 4: 1 5: 1 6: 1 7: 0 8: 0 9: 0
注意
显示的行总数等于 CRUSH map 的 choose_total_tries 值。但是,crushtool 所做的计算不会受到该设置的影响,只有输出会被截断。--set-choose-total-tries 标志可用于修改该值而无需修改 CRUSH map。
输出是每个放置所需的尝试次数的直方图。对于 --min-x 1 和 --max-x 10,这总共是 10 个 PG 放置。所有这些放置都已成功,这从缺少错误映射诊断消息中可以明显看出。此输出表明可以在两次尝试内放置四个 PG,而一个 PG 仅在四次尝试后才放置。任何失败的放置组都将被计入失败的存储桶中,例如,在原始 crush.txt 中,第八个放置在第五次尝试后失败,并将与在第五次尝试中成功的另一个映射一起计入第五个存储桶中,这在更新后的 map 的直方图中可见,显示了恰好一个条目用于五次和六次尝试。如上所述,PG 放置仅基于 CRUSH 拓扑以及哈希和存储桶算法。使用 --x 8 而不是范围运行原始 crush.txt 将确定性地失败。这意味着对于评估生产中适当值,应使用更大的范围,例如先前示例中的 1024 * 1024。
要找到适当的尝试值,或者要确定这是否是放置的根本问题,可以设置一个非常高的值(例如 500)并使用大样本量(大 x 范围)进行测试,以显示总体分布。从统计的角度来看,将最后一个非零值作为最大值在实践中极不可能导致任何放置失败,但是如果需要较低的值,则可以使用较低的值,但有可能会遇到放置失败的罕见情况,需要人工干预。