3. 数据压缩(Compaction)原理:删除旧版本,回收空间
etcd 是一个多版本并发控制(MVCC)的键值存储。每次对键的 put 或 delete 操作,etcd 不会原地覆盖数据,而是生成一个新的版本记录。随着时间推移,历史版本会不断累积,导致存储空间膨胀、读写性能下降。数据压缩(Compaction)正是解决这一问题的核心机制——它通过删除指定版本之前的所有旧数据,回收磁盘空间,同时保持最新数据的可访问性。
3.1 MVCC 与版本堆积
在 etcd 中,每个键值对都关联一个全局递增的 revision(修订版本号)。当执行写操作时,etcd 会追加一条新的记录,而旧记录仍然保留在存储引擎(BoltDB)中。下图展示了 MVCC 下的版本链结构:
关键理解:压缩不是删除“最新数据”,而是删除“过时的历史版本”。即使执行了
delete 操作,etcd 也只是写入一个删除标记(tombstone),真正的数据清理依赖压缩机制。
3.2 压缩的两种模式
etcd 支持两种压缩模式,分别适用于不同的运维场景:
| 模式 | 触发方式 | 压缩依据 | 典型场景 |
|---|---|---|---|
| 时间模式(Time-based) | 自动(周期性) | 保留最近 N 小时内的所有版本 | 生产环境默认推荐,避免手动干预 |
| 版本模式(Revision-based) | 手动或 API 调用 | 保留从指定 revision 开始到最新的版本 | 故障恢复、数据迁移、精确控制 |
3.2.1 时间模式(自动压缩)
通过启动参数 --auto-compaction-retention 设置保留时长,单位可以是小时(h)或分钟(m)。etcd 会周期性地计算当前时间与保留时长的差值,然后压缩掉所有早于该时间点的版本。
# 保留最近 1 小时的数据,自动压缩更早的版本
etcd --auto-compaction-retention=1h
# 保留最近 30 分钟
etcd --auto-compaction-retention=30m
3.2.2 版本模式(手动压缩)
通过 etcdctl 或 gRPC API 指定一个 revision 号,etcd 会删除所有小于等于该 revision 的历史数据。此模式需要运维人员对数据版本有清晰认知。
# 压缩所有 revision <= 1000 的数据
etcdctl compaction 1000
# 查看当前最新的 revision
etcdctl endpoint status --write-out=table
⚠️ 风险提示:版本模式压缩不可逆。如果指定的 revision 过大(例如压缩到当前最新 revision),可能导致 etcd 丢失所有历史数据,甚至影响 watch 和线性化读操作。生产环境建议优先使用时间模式。
3.3 压缩的内部流程
当触发压缩时,etcd 会执行以下步骤:
- 计算压缩目标 revision:根据时间或用户指定的 revision,确定一个截止 revision
compactRev。 - 标记 BoltDB 中的过期数据:遍历 BoltDB 的 bucket,标记所有
revision ≤ compactRev的键值对为“可删除”。 - 删除历史版本记录:从 BoltDB 中物理删除这些标记的数据条目,释放 B+ 树中的页面空间。
- 更新元数据:在 etcd 的元数据 bucket 中记录本次压缩的 revision,供后续操作(如 watch)参考。
- 触发碎片整理(可选):压缩仅删除数据,但 BoltDB 文件大小不会立即缩小。需要后续执行
defrag才能回收磁盘空间(详见下一章)。
3.4 压缩对存储的影响
压缩完成后,etcd 的存储空间变化如下:
| 指标 | 压缩前 | 压缩后 | 说明 |
|---|---|---|---|
| 逻辑数据量 | 高(包含所有历史版本) | 低(仅保留最新版本) | 查询和 watch 效率提升 |
| BoltDB 文件大小 | 大 | 不变(或略微减小) | 物理空间未回收,内部出现空闲页面 |
| 磁盘碎片 | 较少 | 增多 | 空闲页面分散,需要 defrag 整理 |
| 读写性能 | 可能下降(B+ 树膨胀) | 提升(B+ 树高度降低) | 索引扫描更快 |
核心结论:压缩是 etcd 存储管理的“第一步”,它释放了逻辑空间,但物理空间回收需要依赖后续的碎片整理(defrag)。两者配合使用,才能实现存储空间的真正优化。
3.5 压缩的最佳实践
- 生产环境始终开启自动压缩:推荐保留时长
1h或2h,根据业务对历史版本的需求调整。 - 避免过于频繁的压缩:压缩本身消耗 I/O 和 CPU,过于频繁(如每几分钟一次)可能影响集群性能。
- 监控压缩状态:通过
etcdctl endpoint status查看DB SIZE和COMPACT REVISION,确认压缩是否正常执行。 - 压缩后及时执行 defrag:在业务低峰期执行碎片整理,回收磁盘空间。
- 版本模式谨慎使用:仅在故障恢复或数据迁移等特殊场景下手动压缩,并确保指定合理的 revision。