← 返回题目列表

快照和日志压缩有什么作用?

高频 中等 第 9 / 27 题 更新于 2026/09/30
快照日志压缩Raft崩溃恢复
学习 AI 实战项目

简化版

快照把某个已提交且已应用水位的完整状态固化下来,日志压缩则删除该水位之前已被快照覆盖的历史,从而控制日志空间并加速新副本恢复。快照必须记录边界 index/term、校验和与格式版本,原子生成和安装;它不是备份,未提交日志也不能被快照固化。

详细版

若状态机有 1 亿条日志,新节点逐条重放可能要数小时。创建 index=9000 的快照后,新节点先安装快照,再重放 9001 之后日志即可。

创建边界必须满足 snapshotIndex <= appliedIndex <= commitIndex。Copy-on-write、MVCC 快照或短暂停写用于得到一致视图,不能边遍历边读取互相矛盾的业务状态。

安装流程是分块传输到临时文件、校验长度/checksum、fsync、原子切换状态机和元数据,再处理可衔接的日志后缀。中断时旧状态仍可服务。

快照用于副本恢复和日志压缩;备份则面向误删、软件 bug 和灾难恢复,通常要独立保留多个历史恢复点。

完整版教学

一、为什么日志不能无限增长

日志适合增量复制,却不适合永久保存全部历史。空间会持续增长,启动重放越来越慢,严重落后副本追赶时间也不可接受。快照把历史命令的效果折叠为一个状态基线。

snapshot(index=9000, term=12) + log[9001..current]

二、快照边界包含什么

除了状态数据,还要记录 lastIncludedIndex、lastIncludedTerm、成员配置、schema/format version 和 checksum。index/term 让共识层判断后续日志能否衔接,格式版本让新旧程序知道能否读取。

字段用途缺失风险
index/term连接共识历史错接日志后缀
checksum检测传输/落盘损坏静默错误
config恢复成员关系使用错误 quorum
format version兼容升级新程序无法解释状态

三、如何生成一致快照

快照只能覆盖已应用前缀。状态机在 index=9000 建立 MVCC read point,后台可继续应用更高日志,但快照读取始终看到同一版本。没有 MVCC 时可用 copy-on-write 或短暂冻结后复制。

边扫描边读“当前值”会得到撕裂视图,例如账户 A 已扣款而 B 尚未入账。快照 API 必须提供一致读取语义,而不是仅仅复制目录。

四、何时压缩日志

快照成功写入、checksum 验证并原子发布后,才能删除它覆盖的日志。还要考虑是否有安装中的旧副本、增量备份或审计需要引用这些段;生产常保留一段尾日志,而非立即删到边界。

触发条件可结合日志字节、条目数、恢复时间目标和磁盘水位。过于频繁会增加 CPU/I/O,太稀疏则恢复慢且日志占用大。

五、安装快照的原子性

Leader 分块发送快照,Follower 写临时区域并支持断点续传。全部块到齐后校验 checksum、fsync 数据和目录,再以原子元数据切换为活动状态。失败时删除临时产物,继续使用旧状态。

如果本地在快照边界之后存在 term 匹配的合法日志,可保留后缀;无法证明衔接时应丢弃冲突后缀,再从 Leader 获取。绝不能把已应用的新状态与不匹配旧日志拼接。

六、快照不是备份

如果软件 bug 把错误状态合法提交,最新快照也包含错误;若运维误删,集群会把删除复制到所有副本。备份应隔离权限、跨故障域、保留历史恢复点并定期恢复演练。

监控快照年龄、生成耗时、大小、失败率、安装进度、校验错误、日志保留字节和预计恢复时间。空间规划要覆盖新旧快照短时共存。

记忆钩子:快照是“已应用历史的压缩证明”,只有新证明原子落稳后,旧日志才有资格删除。

七、常见误区与追问

  • 误区:commitIndex 之前都可直接快照。 状态机必须已经应用到边界,不能快照尚未执行的命令。
  • 误区:复制数据目录就是一致快照。 并发更新可能产生撕裂视图,需要 MVCC/COW 或冻结。
  • 误区:有快照就不需要备份。 快照随集群复制错误,不能替代独立历史恢复点。
  • 追问:安装中断怎么办? 临时文件不激活,支持续传或丢弃,旧状态继续有效。
  • 追问:日志何时能删? 快照校验并原子发布,且没有必要引用后再按保留策略删除。
  • 追问:为什么记录 term? 用于验证快照边界与后续日志是否属于同一合法历史。

八、加强记忆

快照流程按“选已应用边界—取得一致视图—写临时文件—校验 fsync—原子发布—压缩旧日志”记忆。恢复时先装快照再追尾日志。把 index/term、原子性和备份边界讲清,才能避免把快照误解成普通文件拷贝。