在 Apache Pulsar 的存储层 Apache BookKeeper 中,Ledger 滚动(Rolling)与垃圾回收(GC)机制 是保障系统长期稳定运行、避免磁盘耗尽、优化存储效率的核心机制。
理解这两个机制,是掌握 Pulsar 存储生命周期管理的关键。
📘 Pulsar Ledger 滚动与 GC 机制深度解析
一、核心概念回顾
| 术语 | 说明 |
|---|---|
| Ledger | BookKeeper 中的“账本”,一个只追加的日志单元,存储一组消息 |
| Entry | Ledger 中的一条消息条目 |
| Ensemble | 负责存储 Ledger 副本的一组 Bookie |
| Entry Log | Bookie 上的物理文件,多个 Ledger 的 Entry 可能混合存储其中 |
| GC(Garbage Collection) | 清理已删除 Ledger 占用的磁盘空间 |
📌 Ledger 滚动:关闭当前 Ledger,创建新 Ledger。
📌 GC:回收旧 Ledger 文件的磁盘空间。
二、Ledger 滚动(Ledger Rolling)机制
1. 什么是 Ledger 滚动?
- 当一个 Ledger 达到预设的 大小 或 时间限制 时,Pulsar Broker 会自动关闭它,并创建一个新的 Ledger 接替写入。
- 这个过程称为 Ledger Rolling(账本滚动)。
Ledger-100 (512MB) → [Entry-1, Entry-2, ..., Entry-N]
↓ 滚动触发
Ledger-101 (新) → [Entry-N+1, ...]
2. 滚动的好处
| 优势 | 说明 |
|---|---|
| ✅ 防止单个 Ledger 过大 | 便于故障恢复、数据迁移 |
| ✅ 提升 GC 效率 | 小文件更容易被回收 |
| ✅ 负载均衡 | 新 Ledger 可选择不同的 Ensemble |
| ✅ 支持 TTL 和保留策略 | 按 Ledger 粒度清理数据 |
3. 触发滚动的条件
Ledger 滚动由 Pulsar Broker 控制,可通过以下任一条件触发:
(1) 按大小滚动
# broker.conf
managedLedgerMaxLedgerSizeMB=512
- 当 Ledger 大小 ≥ 512MB 时,触发滚动。
(2) 按时间滚动
# broker.conf
managedLedgerMaxMarkDeleteLedgerAgeIntervalInMinutes=360 # 6小时
- 即使未满 512MB,只要 Ledger 存活超过 6 小时,也会滚动。
(3) 手动触发
pulsar-admin topics trigger-managed-ledger-rollover persistent://public/default/my-topic
- 用于测试或强制释放旧日志。
4. 滚动流程
1. Broker 检测到滚动条件满足
↓
2. 停止向当前 Ledger 写入新消息
↓
3. 调用 bookkeeper.close() 关闭 Ledger
↓
4. 创建新 Ledger(选择新 Ensemble)
↓
5. 更新 ManagedLedger 元数据(ZooKeeper)
↓
6. 新消息写入新 Ledger
✅ 滚动对生产者透明,不会中断写入。
三、Ledger GC(垃圾回收)机制
1. 为什么需要 GC?
- BookKeeper 使用 Entry Log 存储多个 Ledger 的 Entry。
- 即使某个 Ledger 被删除,只要 Entry Log 中还有其他 Ledger 的数据,该文件就不能被删除。
- 导致 磁盘空间无法释放,形成“存储碎片”。
💡 这就是 逻辑碎片问题。
2. GC 的核心目标
- 回收 已删除 Ledger 占用的磁盘空间。
- 减少 Entry Log 文件数量。
- 释放 Bookie 磁盘空间。
3. GC 的两种类型
| 类型 | 说明 |
|---|---|
| Minor Compaction(小合并) | 合并多个部分删除的 Entry Log,回收空间 |
| Major Compaction(大合并) | 全量扫描所有 Entry Log,最大化空间回收 |
⚠️ 注意:BookKeeper 的 “Compaction” 实际是 GC,不是 Kafka 的日志压缩。
4. GC 工作流程
(1) 标记阶段(Mark)
- 扫描所有活跃 Ledger。
- 记录每个 Entry Log 中 仍被引用的 Entry。
(2) 清理阶段(Sweep)
- 对于每个 Entry Log 文件:
- 如果 所有 Entry 都已被删除 → 物理删除文件。
- 如果 部分 Entry 被删除 → 标记为“可压缩”。
- 触发 Compaction:将仍有效的 Entry 复制到新 Entry Log 文件。
- 删除原文件。
(3) 结果
- 磁盘空间被释放。
- Entry Log 文件数量减少。
5. 配置参数(bookkeeper.conf)
# 是否启用 GC(默认 true)
isForceGCAllowWhenNoSpace=false
# Minor Compaction
minorCompactionThreshold=0.2 # 当 20% 数据可回收时触发
minorCompactionInterval=3600 # 每 1 小时检查一次
# Major Compaction
majorCompactionThreshold=0.5 # 当 50% 数据可回收时触发
majorCompactionInterval=86400 # 每 24 小时一次
# Entry Log 滚动大小(影响 GC 效率)
logWriteCacheMaxSizeMB=2048 # 2GB
✅ 建议:
minorCompactionThreshold=0.2(频繁小回收)majorCompactionInterval=24(每日一次深度清理)
四、Ledger GC 的挑战与优化
1. 挑战
| 问题 | 说明 |
|---|---|
| ❌ I/O 压力大 | Compaction 需要大量读写磁盘 |
| ❌ 长时间运行 | 大集群可能持续数小时 |
| ❌ 不支持在线压缩 | 需要额外磁盘空间 |
| ❌ 无法完全消除碎片 | 若 Ledger 分布稀疏,仍难回收 |
2. 优化策略
| 策略 | 说明 |
|---|---|
| ✅ 合理设置 Ledger 滚动大小 | 避免过小(太多文件)或过大(GC 慢) |
| ✅ 启用 Ledger Offload | 将冷数据迁移到 S3/GCS,减少本地 GC 压力 |
| ✅ 分离 Journal 和 Ledger 存储 | 防止 GC I/O 影响写入性能 |
| ✅ 使用 SSD 存储 | 提升 Compaction 速度 |
| ✅ 监控 under-replicated ledgers | 防止因 GC 导致副本不足 |
| ✅ 避免频繁创建/删除 Topic | 减少 Ledger 元数据压力 |
五、监控与诊断
1. 关键监控指标
| 指标 | 说明 |
|---|---|
bookkeeper_client_under_replicated | 副本不足的 Ledger 数 |
bookie_disk_usage | 磁盘使用率 |
compaction_rate | Compaction 速度(entries/sec) |
entry_log_count | Entry Log 文件数量 |
gc_pause_time | GC 暂停时间 |
建议设置告警:
disk_usage > 80%或under_replicated > 0
2. 常用诊断命令
# 查看 Bookie 磁盘使用
bookkeeper shell bookieinfo
# 列出所有 Ledger
bookkeeper shell listledgers
# 检查 Ledger 完整性
bookkeeper shell ledgerchecker -l 1001
# 手动触发 GC(不推荐生产使用)
bookkeeper shell majorcompaction
bookkeeper shell minorcompaction
六、可视化:Ledger 滚动与 GC 流程图(文字描述)
[消息持续写入]
↓
Ledger-100 (增长中)
↓
达到 512MB 或 6小时
↓
[触发 Ledger Rolling]
↓
Ledger-100 → CLOSED
Ledger-101 → OPEN (新)
↓
消费者消费完 Ledger-100 的消息
↓
ManagedLedger 删除 Ledger-100
↓
[GC 触发]
↓
扫描 Entry Log 文件
↓
发现 Ledger-100 的 Entry 可回收
↓
Compaction:复制有效 Entry 到新文件
↓
删除旧 Entry Log
↓
[磁盘空间释放]
七、最佳实践总结
| 实践 | 建议 |
|---|---|
| ✅ Ledger 大小:512MB ~ 1GB | 平衡滚动频率与 GC 效率 |
| ✅ 滚动时间:6 ~ 24 小时 | 防止单个 Ledger 过长 |
| ✅ 启用 Minor/Major Compaction | 定期回收空间 |
| ✅ 监控 entry_log_count | 过多表示碎片严重 |
| ✅ 结合 Ledger Offload | 冷数据归档,减轻 GC 压力 |
| ✅ 避免短生命周期 Topic | 减少 Ledger 创建/删除频率 |
✅ 总结
| 机制 | 作用 | 触发条件 |
|---|---|---|
| Ledger Rolling | 控制单个 Ledger 大小和生命周期 | 大小/时间限制 |
| Minor Compaction | 回收部分删除的 Entry Log 空间 | 可回收率 > 20% |
| Major Compaction | 全量回收,最大化空间释放 | 每 24 小时一次 |
| Ledger Offload | 外部归档,替代本地 GC | 配合 TTL 策略 |
📌 一句话总结:
Ledger 滚动是“预防”,GC 是“治疗” —— 通过合理的滚动策略减少碎片,再通过 Compaction 回收空间,才能确保 Pulsar 集群长期稳定运行。
44

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



