在 Apache Pulsar 的存储层 Apache BookKeeper 中,数据恢复流程 是保障消息系统高可用、持久性和一致性的核心机制。当 Bookie 节点宕机、磁盘损坏、网络分区或 Ledger 未正常关闭时,BookKeeper 能够通过一系列自动恢复机制,确保数据不丢失、不重复,并恢复服务的正常运行。
📘 Pulsar BookKeeper 数据恢复流程详解
一、为什么需要数据恢复?
在分布式系统中,以下故障可能导致数据不一致或不可用:
| 故障场景 | 风险 |
|---|---|
| Bookie 宕机或磁盘损坏 | 数据副本丢失 |
| 网络分区(Split-Brain) | 多个副本写入不一致 |
| Broker 崩溃未关闭 Ledger | Ledger 处于“打开”状态,无法读取 |
| 静默数据损坏(Silent Corruption) | 数据写入成功但内容错误 |
✅ BookKeeper 的恢复机制就是为了解决这些问题。
二、数据恢复的三大核心流程
BookKeeper 的数据恢复不是单一操作,而是一套 分层、协作的恢复机制,主要包括:
- Write Recovery(写入恢复)
- Ledger Recovery(账本恢复)
- Autorecovery(自动副本修复)
三、机制 1:Write Recovery(写入恢复)
适用场景:
- Ledger 正在写入时,Broker 或 Bookie 故障,导致写入中断。
- 部分 Bookie 写入成功,部分失败。
恢复目标:
- 确保 Exactly-Once 写入语义,防止部分成功。
恢复流程:
-
Broker 检测写入失败:
- 未在
ackTimeout内收到足够 ACK(AQ)。 - 连接中断或 Bookie 不可用。
- 未在
-
触发恢复流程:
ledger.recover() // 客户端或 Broker 调用 -
查询 Last Add Confirmed (LAC):
- 向 Ensemble 中所有 Bookie 查询该 Ledger 的最后确认位置。
- LAC 是“多数派”确认的最大 Entry ID。
-
确定最终写入点:
- 选择被至少
AQ个副本确认的最大 Entry ID 作为最终 LAC。 - 要求:
AQ > WQ / 2(防止脑裂)
- 选择被至少
-
截断不一致的副本(Truncation):
- 对写入超过 LAC 的 Bookie,强制截断多余 Entry。
- 保证所有副本一致。
-
关闭 Ledger 或创建新 Ledger。
✅ 结果:数据一致,无部分写入。
示例(WQ=3, AQ=2):
Bookie-A: Entry-100 ✅
Bookie-B: Entry-100 ✅
Bookie-C: Entry-101 ❌(未确认)
→ LAC = 100(多数派确认)
→ Bookie-C 被截断到 Entry-100
四、机制 2:Ledger Recovery(账本恢复)
适用场景:
- Ledger 未正常关闭(如 Broker 崩溃后重启)。
- 需要确定该 Ledger 是否可读、最终写入位置。
恢复流程:
-
首次打开 Ledger 读取时触发:
- Consumer 或 Reader 尝试读取一个“打开”但可能不一致的 Ledger。
-
执行恢复检查:
- 与 Write Recovery 类似,查询所有副本的 LAC。
-
选择最大一致的 LAC:
- 使用“多数派原则”确定最终写入点。
-
修复副本:
- 截断写入过多的副本。
- 如果某些副本缺失,从其他副本补全(需 Autorecovery)。
-
标记 Ledger 为 CLOSED:
- 更新 ZooKeeper 元数据。
- 后续只能读取,不能写入。
✅ Ledger Recovery 是 读取时触发的被动恢复。
五、机制 3:Autorecovery(自动副本修复)
适用场景:
- 某个 Bookie 永久故障(如磁盘损坏),导致 Ledger 副本数不足。
- 需要将缺失的副本复制到新 Bookie。
恢复流程:
1. 检测副本缺失
- Auditor 服务定期扫描所有 Ledger。
- 发现某个 Ledger 的可用副本数 <
WQ。 - 在 ZooKeeper 中创建
/underreplicated/ledgers/ledger-1001节点。
2. 触发 Autorecovery
- Autorecovery Worker 监听
/underreplicated路径。 - 检测到新 Ledger 标记。
3. 选择新 Bookie
- 从可用 Bookie 中选择一个目标节点。
- 遵循 Ensemble 分布策略(如跨机架)。
4. 复制数据
- 从其他存活副本读取 Ledger 数据。
- 写入新 Bookie。
- 更新 Ledger 元数据(ZooKeeper)。
5. 完成修复
- Ledger 副本数恢复到
WQ。 - 删除
/underreplicated标记。 - 系统恢复正常。
✅ Autorecovery 是 后台异步进行,不影响正常读写。
配置(bookkeeper.conf):
autorecoveryEnabled=true
auditorEnabled=true
auditorPeriodicBookieCheckInterval=30 # 每 30 秒检查一次
六、静默数据损坏(Silent Corruption)恢复
问题:
- 某个 Bookie 返回错误数据(如内存错误、磁盘坏道),但返回 ACK。
检测机制:
- Read Quorum (RQ):读取时从多个副本读取并比对。
- 如果
RQ=2,两个副本内容不同,抛出异常。
恢复流程:
- Broker 检测到不一致。
- 尝试从第三个副本读取。
- 若第三个副本与其中一个一致,则认为另一个是坏的。
- 标记该 Bookie 为可疑,并触发 Autorecovery 修复。
✅ 推荐:
RQ ≥ 2,否则无法检测数据损坏。
七、恢复流程图(文字描述)
[故障发生]
↓
+---------------------+
| Auditor Service |
| - 扫描 Ledger 状态 |
| - 发现副本不足 |
+----------+----------+
|
v
ZooKeeper: /underreplicated
|
v
+----------+----------+
| AutoRecovery Worker |
| - 选择新 Bookie |
| - 从副本读取数据 |
| - 写入新节点 |
+----------+----------+
|
v
更新 Ledger 元数据
|
v
[副本恢复]
+------------+
| Write Recovery |
| - 查询 LAC |
| - 截断不一致副本 |
+------------+
+------------+
| Ledger Recovery |
| - 确定最终写入点 |
| - 标记 CLOSED |
+------------+
八、关键配置与最佳实践
1. 恢复相关配置(bookkeeper.conf)
# 启用恢复机制
autorecoveryEnabled=true
auditorEnabled=true
# 恢复检查间隔
auditorPeriodicBookieCheckInterval=30
# 写入超时(影响 Write Recovery)
bookieDeathWatchInterval=10000 # 10秒
2. 最佳实践
| 实践 | 建议 |
|---|---|
| ✅ AQ > WQ / 2 | 防止脑裂,保证恢复一致性 |
| ✅ 启用 Autorecovery 和 Auditor | 自动修复副本 |
| ✅ RQ ≥ 2 | 检测静默数据损坏 |
| ✅ 定期运行 ledgerchecker | bookkeeper shell ledgerchecker |
| ✅ 监控 under-replicated ledgers | 及时发现风险 |
| ✅ 使用 SSD 存储 | 提升恢复速度 |
| ✅ 分离 Journal 和 Ledger 磁盘 | 防止 I/O 争抢 |
九、常用恢复命令
# 手动触发 Autorecovery
bookkeeper shell autorecovery
# 查看 under-replicated ledgers
bookkeeper shell listunderreplicated
# 检查 Ledger 完整性
bookkeeper shell ledgerchecker -l 1001
# 列出所有 Ledger
bookkeeper shell listledgers
# 查看 Bookie 状态
bookkeeper shell bookiesanity
✅ 总结
| 恢复机制 | 触发时机 | 目标 |
|---|---|---|
| Write Recovery | 写入失败时 | 保证 Exactly-Once |
| Ledger Recovery | 读取未关闭 Ledger 时 | 确定最终写入点 |
| Autorecovery | 副本缺失时 | 自动修复副本 |
| Read Quorum 检测 | 读取时 | 发现数据损坏 |
📌 一句话总结:
BookKeeper 的数据恢复是“三重保险” —— 通过 Write Recovery 保证写入原子性,Ledger Recovery 确保账本一致性,Autorecovery 实现副本高可用,共同构建了一个即使在故障下也能自愈的存储系统。
107

被折叠的 条评论
为什么被折叠?



