分布式系统中 Map 增量(Delta)是否需要持久化

以 Ceph OSDMap 为例,结合自研分布式文件系统的设计决策


一、背景:什么是 Map 增量

在分布式系统中,通常有一个"集群拓扑视图"(Map),比如:

  • Ceph 的 OSDMap:描述每个 OSD 的状态、CRUSH 拓扑
  • 自研系统的 PartitionMap:描述每个 partition 的归属 MDS 和状态

这个 Map 会随集群状态变化频繁更新,每次更新产生一个新 epoch。

全量推送:每次变更都推送完整的 Map(简单,但数据量大)

增量推送(Delta):只推送变化的部分(节省带宽,但实现复杂)

核心问题来了:这些增量(Delta)需要持久化到 DB 吗?


二、Ceph OSDMap 为什么必须持久化增量

2.1 OSD 需要历史 epoch 定位 PG

Ceph 使用 CRUSH 算法根据 OSDMap 计算 PG(Placement Group)的位置。
同一个 PG 在不同 epoch 的 OSDMap 下,计算出的 OSD 位置可能不同。

复制代码
PG 1.0a 在 epoch=100 时 → 存在 [osd.1, osd.5, osd.9]
PG 1.0a 在 epoch=95  时 → 存在 [osd.1, osd.3, osd.9]  (osd.3 还活着)

当 OSD 之间做数据迁移(backfill/recovery)时,需要知道:

  • "这个 PG 在旧 epoch 时应该在哪些 OSD 上"
  • "数据从哪里迁移到哪里"

如果 Monitor 只保留最新全量 OSDMap,OSD 拿着一个老 epoch 的视图来询问 Monitor,

Monitor 无法重建那个历史时刻的拓扑,就无法指导正确的数据迁移。

2.2 具体场景:落后很多的 OSD 追赶

复制代码
当前 epoch = 500
某 OSD 宕机了一段时间,重启后持有的 epoch = 450

OSD 向 Monitor 请求追赶:build_incremental(450 → 500)
Monitor 需要:
    epoch 451 的 Incremental(包含:哪个 OSD 出入/权重变化)
    epoch 452 的 Incremental
    ...
    epoch 500 的 Incremental

每个 Incremental 都记录了"从 N-1 到 N 发生了什么变化"
OSD 逐步 apply,最终追赶到最新 epoch

如果 Monitor 没有保存历史 Incremental:
    只能发 epoch=500 的全量
    OSD 知道了"现在是什么样",但不知道"中间发生了什么"
    → 无法正确计算哪些 PG 需要迁移数据(因为不知道迁移路径)

2.3 OSDMap Incremental 的持久化内容

每个 epoch 的 Incremental 存储在 Monitor 的 RocksDB 中:

复制代码
key: "osdmap/v{epoch}"      → 存该 epoch 的 Incremental(变化集)
key: "osdmap/full/{epoch}"  → 每隔若干 epoch 存一个全量快照

Incremental 记录:

cpp 复制代码
struct OSDMap::Incremental {
    epoch_t epoch;
    map<int32_t, entity_addr_t> new_up_client;   // 新上线的 OSD
    set<int32_t>                new_down;         // 新下线的 OSD
    map<int32_t, uint32_t>      new_weight;       // 权重变化
    map<int32_t, pg_t>          new_pg_temp;      // PG 临时映射变化
    // ...
};

2.4 Trim 策略:历史不会无限保留

Monitor 会定期清理太老的历史 epoch:

cpp 复制代码
version_t OSDMonitor::get_trim_to() const {
    // 至少保留 mon_min_osdmap_epochs 个 epoch(默认 500)
    // 至少保留到所有 OSD 都 clean 到的最老 epoch(min_last_epoch_clean)
}

超出保留范围的历史 epoch 被 GC 删除。

客户端/OSD 落后太多时,直接发全量快照 + 从该时间点之后的增量。


三、什么情况下不需要持久化增量

与 OSDMap 形成对比,很多系统的 Map 不需要持久化增量:

条件一:接收方不依赖"历史路径",只需要"当前状态"

如果接收方(MDS、客户端)只需要知道"partition 现在在哪里",而不需要知道"中间经历了哪些迁移路径",那么:

  • 全量快照持久化(DB 里始终有最新的完整 Map)
  • 增量只在内存中缓存少量历史(用于追赶近期落后的接收方)
  • 落后太多时降级为推全量

内存缓存的增量是性能优化,不是正确性保证。

条件二:接收方重连时能接受"全量重建"

如果接收方(MDS)重启后,从 mgmtd 拉一次全量 PartitionMap 就能正常工作,不需要回放历史变更序列,则增量不需要持久化。

条件三:Map 数据量小,全量推送开销可接受

PartitionMap 即使有 1000 个 partition,全量序列化也就几十 KB,全量推送的代价很低。


四、决策框架:如何判断是否需要持久化增量

复制代码
问题一:接收方是否需要"历史路径"来保证正确性?
    是 → 必须持久化增量(如 Ceph OSDMap)
    否 → 继续下一个问题

问题二:接收方落后时,全量推送是否可接受(带宽/延迟)?
    可接受 → 不需要持久化增量,内存缓存少量即可
    不可接受(Map 极大)→ 考虑持久化增量,或分片推送

问题三:mgmtd 重启后,是否需要快速恢复增量推送能力?
    否(重启后推全量给所有 MDS 即可)→ 不需要持久化
    是(重启后要能继续发增量,不想推全量)→ 需要持久化增量

五、两类系统的对比

系统 Map 类型 增量是否持久化 原因
Ceph OSDMap 拓扑路由 Map ✅ 必须持久化 OSD recovery 依赖历史路径计算数据迁移
Ceph FSMap MDS 状态 Map ❌ 不持久化增量 MDS 只需要最新状态,全量很小
Ceph MDSMap MDS 状态 Map ❌ 不持久化增量 同上
自研 PartitionMap partition 路由 Map ❌ 不需要持久化 MDS/客户端只需当前状态,全量可接受
Kubernetes etcd 所有资源状态 ✅ 持久化(WAL) 强一致性,事件溯源需要完整历史
TiKV PD Region Map Region 路由 Map ❌ 只存全量 TiKV 只需要当前 Region 分布

六、自研 PartitionMap 的推荐实现

复制代码
持久化(DB):
    PartitionMap 全量快照(每次变更后持久化最新全量)
    key: "partition_map/v{epoch}" → 全量
    key: "partition_map/latest"   → 最新 epoch 指针

内存(不持久化):
    delta_cache: RingBuffer<PartitionMapDelta, 20>
    // 保留最近 20 个 epoch 的增量,用于追赶近期落后的 MDS
    // mgmtd 重启后 delta_cache 清空,落后的 MDS 推全量

推送策略:
    MDS 心跳携带 current_epoch
    if mds_epoch >= delta_cache.oldest_epoch:
        推送增量(Delta)追赶到最新
    else:
        推送全量(Full)

七、总结

OSDMap 持久化增量是因为 OSD recovery 在语义上依赖历史 epoch 的拓扑路径,这是正确性需求,不是性能优化。

PartitionMap 不需要持久化增量,因为 MDS 和客户端只需要"当前状态",接收方重建时拉全量即可。增量只是减少推送量的性能优化,放内存缓存就够了。

判断标准一句话:接收方是否需要"历史路径"来保证行为正确?需要 → 持久化;不需要 → 内存缓存即可。

相关推荐
一个行走的民2 天前
BlueStore 核心原理与关键机制
ceph
奋斗的小青年I4 天前
Proxmox VE Ceph 超融合集群落地实战
windows·ceph·vmware·pve·超融合·proxmox
一个行走的民4 天前
深度剖析 Ceph PG 分裂机制:原理、底层、实操、影响、线上避坑(最全完整版)
ceph·算法
一个行走的民4 天前
Ceph 核心概念精讲:彻底搞懂 PG、PGP、pg_num、pgp_num
ceph
Mr.王83517 天前
Kubernetes宿主机本地盘池化管理
ceph·云原生·容器·kubernetes
一个行走的民21 天前
CEPH OSD心跳机制
ceph
一个行走的民21 天前
Ceph PG 状态详解与线上故障处理
网络·ceph
一个行走的民21 天前
Ceph MDS 状态机与 Monitor 中的状态流转分析
ceph
Virtual_human08061 个月前
在VMware workstation上,部署3节点ceph测试,及加入openstack
ceph·云计算·openstack·osd·ceph集群