基础概念
ledger
: 日志流- 具有全局唯一的 id
- 只允许追加写
- 提供
at-most-once
语义
record
: 记录,用户写入的最小单位,也叫entry
entry
归属于某个ledger
entry
具有唯一的 id
bookie
: 存储 ledger 的服务器
架构
![](/2022/03/20/apache-bookkeeper/fig1-architecture-of-apache-bookkeeper.png)
- Metadata Store:存储 Ledger 的元数据,同时为 Client 提供服务发现功能
- Ledger 元数据包括
- Ledger 状态: Open / Closed
- Ensambles: 每段 Eid 范围所在的 bookie
- Ledger 元数据包括
- Bookie: 存储 Ledger 的数据
- Journal: 日志文件,记录了追加操作,用于保证可靠性,所有 Ledger 共享同一个 journal 文件
- LederStorage
- Client: 负责处理一致性相关逻辑
- Writer Client 负责生成 EntryId
- Ensamble / Write Quorum / Ack Quorum
- Ensable 一组 bookie,负责存储一个 Ledger 的所有副本
- Write Quorum:写入分组,Write Quorum Size 即为保存副本数
- Ack Quorum Size:等待几个 Write Quorum 请求成功
- LastAddConfirmed & LastAddPushed
- LAP: 最后一条发送的 Eid
- LAC:最后一条写入成功的 Eid
- LAC 之前的所有的 Entry 都已经 Confirm 过
- LAP 和 LAC 之间的 Entry 是 on-flying
- 假设发出去请求 1 和 2,2 先回来,不能把 LAC 改为 2,必须等 1 和 2 都回来了才能改成 2
- LAC 存在 Entry Metadata 中
- Fencing: 防止脑裂
- 给 bookie 发 Fenced 状态,之后我那个这个 Ledger 写的操作会失败,Client 收到 LedgerFenced 错误
- Client 收到 LedgerFenced 错误后,会放弃 Ledger 的 Ownership
- 新 Client 会将 LAC 之后的 Entry 进行 Forward Recovery,即尝试修复 LAC 和 LAP 之间的 Entry,这个动作由 AutoRecovery Worker 后台完成(可能同时由多个 worker 同时负责,最小粒度为 Entry)
- 新 Client 关闭老 Ledger 并打开新 Ledger
Bookie 写入过程
![](/2022/03/20/apache-bookkeeper/fig2-write-cache-flush.png)
- 先写 Journal,fsync 成功后才向 Client 返回成功,保证可靠性
- 支持 Group Commit,在一定时间间隔内的写入的数据一次 fsync 到盘上
- 再写内存的 Write Cache
- 对 Entry 按照 Lid, Eid 排序
- Write Cache 写满之后 flush 到 Entry Log 中,并按 Ledger 生成索引
- Entry Log 中同一个 Ledger 的 Entry 具有局部性
- 删除 Journal
- 如果 Writer 写入失败,会有新的 Writer Close 当前 Ledger 去写新的 Ledger