Mooncake Store 源码阅读(四):Master 持久化、快照与热备恢复
Mooncake Store 把对象位置和副本状态集中在 Master。这样简化了一致性,但也意味着 Master 的状态不能只存在进程内存中。 本篇基于提交 777cc77,阅读 oplog、snapshot、standby controller 和恢复相关源码。 一、先澄清高可用目标 Mooncake Store 面向高速缓存池。缓存数据本身可以因为节点故障而丢失,系统并不等价于强持久化对象存储。 但控制面仍需要可靠:Master 重启后必须尽可能恢复对象元数据、Segment、配额和副本状态,否则即使真实字节还在,系统也不知道如何访问和回收它们。 因此需要区分两件事。 数据副本是否仍存在。 Master 是否记得这些副本及其状态。 本篇主要讨论第二件事。 二、为什么只做定期快照不够 假设 Master 每十分钟保存一次完整快照。第九分钟发生的大量 Put、Remove 和 Eviction,在崩溃后都会消失。 缩短快照间隔又会频繁扫描和序列化庞大元数据。 常见解决方案是 snapshot 加 oplog: Snapshot 保存某个时刻的完整状态。 OpLog 记录快照之后的增量变化。 恢复时先加载 Snapshot,再重放 OpLog。 Mooncake Store 的 Master 也采用了这一思路。 三、OpLog 记录什么 不是每个函数调用都值得写日志。需要持久化的是会改变可恢复状态的操作,例如对象元数据建立、提交、删除、副本变化和 Segment 相关更新。 当前 master_service.cpp 中可以看到 AppendOpLogWithDurableFinalize、批量预留和 durable finalize 等路径。 这里最关键的顺序是:某些不可逆的内存状态变化,要等对应日志达到持久条件后才能最终确认。 否则进程可能在“内存已经释放,但日志还没记住”时崩溃,恢复后重新得到一个指向已释放空间的副本。 四、Durable Finalize 的设计含义 名字里的 durable finalize 表明操作被拆成了准备与最终完成。 大致过程如下: 准备元数据变化 -> 追加 OpLog -> 等待达到持久条件 -> 执行最终回收或确认 这和 Put 的两阶段思路相似。系统先建立可回滚或可恢复的中间状态,再跨过明确的持久化边界。 ...