注意
本文档适用于 Ceph 的开发版本。
last_epoch_started
info.last_epoch_started 记录区间 i 的激活纪元 e,使得在 i 或更早提交的所有写入都反映在本地 info/log 中,并且在 i 之后没有写入反映在本地 info/log 中。由于已提交的写入永远不会发散,即使我们获得一个具有较旧 info.last_epoch_started 的权威日志/信息,我们也可以保留我们的 info.last_epoch_started 不变,因为在任何干预区间内都不可能提交写入(参见 PG::proc_master_log)。
info.history.last_epoch_started 记录了 PG 作为一个整体激活并接受写入的最晚区间的一个下限。在特定的 OSD 上,它也是本地 PG 日志中发生写入的区间的激活纪元的上限:我们在接受写入之前更新它。因为所有已提交的写入都由所有 acting set OSD 提交,任何非发散的写入都确保 history.last_epoch_started 被该区间中的所有 acting set 成员记录。一旦 peering 查询了每个区间的一个 OSD,回到某个已见的 history.last_epoch_started,那么在最大 history.last_epoch_started 之后没有区间可以报告写入已提交(因为我们在区间中记录客户端写入之前记录它)。因此,所有具有 info.last_epoch_started >= MAX(history.last_epoch_started) 的 info 的最小 last_update 必须是报告给客户端的已提交写入的上限。
我们使用初始激活消息更新 info.last_epoch_started,但我们仅在新 info.last_epoch_started 被持久化(可能连同第一次写入)之后更新 history.last_epoch_started。这确保了我们不会要求具有最近 info.last_epoch_started 的 OSD,直到所有 acting set OSD 都已记录它。
在 find_best_info 中,我们在计算 max_last_epoch_started_found 时确实包含了 info.last_epoch_started 值,因为我们希望避免将先前区间中本应非发散的日志条目标记为发散,因为它可能已被用于服务读取。在 activate() 中,我们使用对等体的 last_epoch_started 值作为可以找到发散日志条目的回溯距离的界限。
然而,在像下面这样的情况下
calc_acting osd.0 1.4e( v 473'302 (292'200,473'302] local-les=473 n=4 ec=5 les/c 473/473 556/556/556
calc_acting osd.1 1.4e( v 473'302 (293'202,473'302] lb 0//0//-1 local-les=477 n=0 ec=5 les/c 473/473 556/556/556
calc_acting osd.4 1.4e( v 473'302 (120'121,473'302] local-les=473 n=4 ec=5 les/c 473/473 556/556/556
calc_acting osd.5 1.4e( empty local-les=0 n=0 ec=5 les/c 473/473 556/556/556
由于 osd.1 是唯一记录 info.les=477 的 OSD,而 osd.4,osd.0(它们是该区间的 acting set)没有记录(osd.4 重启了,而 osd.0 没有及时收到消息),当 osd.4 或 osd.0 本来是有效选择时,PG 被标记为不完整。为了避免这种情况,我们在计算 min_last_epoch_started_found 时不考虑不完整对等体的 info.les。它不会在 acting set 中,所以无论如何我们必须有来自该区间的另一个 OSD(如果 maybe_went_rw)。如果那个 OSD 不记得那个 info.les,那么我们就不可能服务读取。