注意

本文档适用于 Ceph 开发版本。

OSDMap修剪和PastIntervals

PastIntervals

有两种情况我们需要考虑所有正在运行的OSDs集合,以PG回退到某个时代e:

  • 在对等过程中,我们需要考虑从最后一个完成对等并成为活跃状态的PG时代开始,每个时代的正在运行集last_epoch_started,(见f89e2e:的详细解释)last_epoch_started for a detailed explanation)

  • 在恢复过程中,我们需要考虑从最后一个所有正在运行集中的OSDs完全恢复,并且正在运行集是完整的时代开始,每个时代的正在运行集last_epoch_clean, the last epoch at which all of the OSDs in the acting set were fully recovered, and the acting set was full.

为了这两种目的之一,我们可以通过从当前的OSDMap迭代到相关时代来构建这样一个集合。相反,我们为每个PG维护一个PastIntervals结构。

一个intervalPastIntervals是一个连续的OSDMap时代序列,其中PG映射没有改变。这包括对正在运行集、上升集、主节点和其他几个在PastIntervals::check_new_interval中完全详述的参数的更改。

维护和修剪

PastIntervals结构为每个回退到最后一个last_epoch_clean的时代存储一条记录。在每个新的63a08e:(参见AdvMap反应、PeeringState::should_restart_peering和PeeringState::start_peering_interval)时代,PG的每个OSD都会将其新的2fcba2:添加到其本地PastIntervals中。发送给没有PG的OSD的激活消息包含发送者的PastIntervals,以便接收者不必重新构建它。(参见PeeringState::activate needs_past_intervals)。interval back to last_epoch_clean. On each new interval (See AdvMap reactions, PeeringState::should_restart_peering, and PeeringState::start_peering_interval) each OSD with the PG will add the new interval to its local PastIntervals. Activation messages to OSDs which do not already have the PG contain the sender’s PastIntervals so that the recipient needn’t rebuild it. (See PeeringState::activate needs_past_intervals).

PastIntervals在两个地方被修剪。首先,当主节点将PG标记为干净时,它会清除其past_intervals实例(PeeringState::try_mark_clean())。副本在收到信息时也会做同样的事情(参见PeeringState::update_history)。

第二个,更复杂的情况是在PeeringState::start_peering_interval中。在“地图间隙”的情况下,我们假设PG实际上已经变得干净,但我们还没有收到带有更新ce786a:值的pg_info_t。last_epoch_clean value yet. To explain this behavior, we need to discuss OSDMap trimming.

OSDMap修剪

OSDMaps由Monitor多数派创建,并传播到OSDs。Monitor集群还确定何时允许OSDs(和Monitors)修剪旧的OSDMap时代。由于本文档中解释的原因,主要约束是必须保留所有回退到某个时代的OSDMaps,以便所有PG在该时代或更晚的时代都是干净的(min_last_epoch_clean)。(参见OSDMonitor::get_trim_to)。

Monitor多数派通过每个OSD定期发送的MOSDBeacon消息确定min_last_epoch_clean。每条消息包含OSD在该时刻是主节点的PG集合以及该集合的min_last_epoch_clean。Monitors在OSDMonitor::last_epoch_clean中跟踪这些值。

OSD用于填充MOSDBeacon的min_last_epoch_clean值存在一个微妙之处。OSD::collect_pg_stats调用PG::with_pg_stats来获取lec值,实际上使用pg_stat_t::get_effective_last_epoch_clean()而不是info.history.last_epoch_clean。如果PG当前是干净的,pg_stat_t::get_effective_last_epoch_clean()是当前时代而不是last_epoch_clean——这之所以可行,是因为PG在该时代是干净的,并且它允许在创建OSDMaps的时期(可能是由于快照活动)修剪OSDMaps,但没有任何PG正在进行14d8e4:更改。interval changes.

返回PastIntervals

现在我们可以理解上面我们的第二个修剪情况。如果OSDMaps已经修剪到时代7c9829:,我们知道PG必须在某个时代>=b04092:(实际上,4f6f20: PGs必须已经),所以我们可以在我们的PastIntevals中删除它们。e, we know that the PG must have been clean at some epoch >= e (indeed, all PGs must have been), so we can drop our PastIntevals.

这种依赖关系也出现在PeeringState::check_past_interval_bounds()中。PeeringState::get_required_past_interval_bounds将最古老的epoch作为参数,它来自OSDSuperblock::cluster_osdmap_trim_lower_bound。我们使用cluster_osdmap_trim_lower_bound而不是特定osd的最古老的地图,因为我们不一定修剪所有的MOSDMap::cluster_osdmap_trim_lower_bound。为了避免一次性做太多工作,我们使用040201:在OSD::trim_maps()中限制修剪的osdmaps的数量。osd_target_transaction_size in OSD::trim_maps(). For this reason, a specific OSD’s oldest map can lag behind OSDSuperblock::cluster_osdmap_trim_lower_bound for a while.

请参阅https://tracker.ceph.com/issues/49689的示例。

OSDSuperblock::maps

OSDSuperblock持有一个时代间隔集,它表示OSD存储的OSDMaps。每个处理的OSDMap时代范围都会添加到该集合中。

The interval_set数据结构支持非连续的时代间隔,这可能在“地图间隙”事件中发生。在使用此数据结构之前,e0aed2: 时代存储在OSDSuperblock中。oldest_mapnewest_map epochs were stored in the OSDSuperblock. However, holding a single and contiguous epoch range imposed constraints which may have resulted in an OSDMap leak.

见:https://tracker.ceph.com/issues/61962

由 Ceph 基金会带给您

Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.