一、核心定位
FileTxnSnapLog 是 Zookeeper 持久化的核心帮助类,核心作用是 封装 TxnLog(事务日志)和 SnapShot(快照),通过组合模式将持久化相关操作转发给这两个组件,统一提供数据恢复、快照保存的入口,简化持久化流程。
二、类结构核心细节
1. 核心属性
| 属性名 | 类型 | 作用 |
| dataDir | File | 事务日志文件存储目录(最终路径为传入目录下的 version-2 子目录) |
| snapDir | File | 快照文件存储目录(最终路径为传入目录下的 version-2 子目录) |
| txnLog | TxnLog | 事务日志实例(实际为 FileTxnLog 实现类) |
| snapLog | SnapShot | 快照实例(实际为 FileSnap 实现类) |
| VERSION | 常量(int) | 版本号,固定为 2 |
| version | 常量(String) | 版本前缀,值为 "version-" |
2. 内部类:PlayBackListener
- 作用:接收事务应用过程中的回调,用于 Zookeeper 数据恢复后期的 事务修正。
- 核心方法:
void onTxnLoaded(TxnHeader hdr, Record rec),事务加载完成后触发,处理数据修正逻辑。
3. 构造函数
- 核心逻辑:
- 接收外部传入的日志目录(dataDir)和快照目录(snapDir)。
- 在传入目录下自动创建
version-2子目录(作为实际存储目录)。 - 校验目录创建结果,创建失败则抛出
IOException。 - 初始化
txnLog(FileTxnLog实例)和snapLog(FileSnap实例),绑定上述目录。
三、核心函数功能与流程
1. restore 函数:数据恢复(核心)
- 作用:从快照文件(snapshot)和事务日志(log)中恢复内存数据库(DataTree)和会话(sessions)。
- 关键步骤:
- 调用
snapLog反序列化快照文件,得到历史的DataTree(内存数据树)和sessions(会话信息)。 - 获取快照文件中记录的最大 zxid,筛选出 zxid > 快照 zxid + 1 的所有事务日志文件,生成迭代器。
- 迭代遍历日志中的每个事务,通过
processTransaction处理事务:
- 按事务类型(
createSession、closeSession等)维护会话映射(sessions):创建会话则添加到映射,关闭会话则移除。 - 调用
DataTree.processTxn将事务操作应用到内存数据树(通过DataNode进行树状节点的增删改)。
- 触发
PlayBackListener.onTxnLoaded回调,完成数据修正。 - 关闭日志迭代器,返回日志中最后一个事务的 zxid(作为当前最新事务 ID)。
2. save 函数:快照保存(核心)
- 作用:将当前内存数据库(DataTree)和会话超时信息(sessionsWithTimeouts)保存为快照文件。
- 关键步骤:
- 获取内存数据库中已处理的 最新 zxid(事务唯一标识)。
- 基于最新 zxid 和快照目录(snapDir),生成快照文件。
- 将
DataTree(全量内存数据)和sessionsWithTimeouts(所有会话的超时配置)序列化后写入快照文件。
3. 其他函数
其余函数均为转发逻辑,直接调用 txnLog 或 snapLog 的对应方法(如事务日志追加、快照读取等),无需额外实现。
四、核心总结
- 设计模式:采用 组合模式,封装
TxnLog和SnapShot,对外提供统一的持久化操作接口,降低使用复杂度。 - 核心能力:
- 数据恢复:结合快照(全量历史数据)+ 事务日志(增量更新数据),确保数据不丢失且恢复至最新状态。
- 快照保存:定期将全量内存数据序列化存储,减少日志回溯量,提升恢复效率。
- 数据存储结构:事务操作的底层存储依赖
DataTree,通过DataNode以 树状结构 组织数据,所有节点操作(增删改)本质是树节点的父子关系调整。