3. etcd 键值存储模型:key-value 存储逻辑、版本号与 revision 机制、MVCC 实现原理
在 etcd 存储组件容量水位评估中,理解底层的键值存储模型是基础。etcd 并非简单的哈希表,而是一个基于 多版本并发控制(MVCC) 的、有序的键值存储引擎。本节将深入剖析其核心逻辑,包括 key-value 的物理存储结构、逻辑版本号(version)与全局修订号(revision)的区别,以及 MVCC 如何支撑高并发读写与历史数据回溯。
3.1 键值存储逻辑:从逻辑视图到物理存储
etcd 的键值存储模型在逻辑上呈现为一个扁平的、按 key 的字节序排序的字典。每个 key 对应一个 value,但底层实现远比这复杂。为了支持高效的范围查询和事务,etcd 使用 BoltDB(一个基于 B+ 树的嵌入式数据库)作为其持久化存储引擎。
在 BoltDB 中,etcd 维护了一个名为 “key” 的主 bucket。这个 bucket 中存储的 key 并非用户直接传入的 key,而是一个复合结构。其核心设计如下:
- 物理 Key 构成:物理 key 由
用户 key + ‘\0’ + revision组成。其中‘\0’是分隔符,revision 是全局递增的整数。 - 排序特性:B+ 树按物理 key 的字节序排序。这意味着同一个用户 key 的所有历史版本会物理上聚集在一起,且按 revision 递增排列。
- Value 存储:物理 value 存储的是用户传入的原始 value 以及一些元数据(如创建时的 revision、lease ID 等)。
下图展示了用户 key “/app/config” 在 BoltDB 中的物理存储结构:
3.2 版本号(version)与全局修订号(revision)
etcd 中存在两个核心的递增计数器,它们服务于不同的目的,是理解 etcd 数据一致性和历史查询的关键。
| 属性 | 版本号(version) | 全局修订号(revision) |
|---|---|---|
| 作用域 | 每个 key 独立维护 | 全局唯一,整个集群共享 |
| 递增时机 | 当该 key 的 value 被更新时递增 | 每次事务(Put、Delete、Txn)提交时递增 |
| 起始值 | key 创建时为 1 | 集群初始化时为 1 |
| 用途 | 乐观锁、检测 key 是否被修改 | 全局数据快照、MVCC 版本标识、Watch 事件排序 |
| 示例 | key “/a” 被修改 3 次,version = 3 | 集群第 100 次事务提交,revision = 100 |
3.3 MVCC 实现原理
etcd 的 MVCC 实现并非像传统数据库那样通过 undo/redo 日志,而是通过 保留所有历史版本 的方式。其核心组件包括:
- treeIndex:一个基于内存的 B 树,用于快速查找用户 key 对应的最新 revision 以及所有历史 revision 列表。它维护了从用户 key 到 revision 的映射关系。
- backend:即 BoltDB 实例,负责持久化存储物理 key-value 对。treeIndex 中的 revision 指向 backend 中的具体物理记录。
- 压缩(Compaction):由于历史版本会无限增长,etcd 提供了压缩机制,用于删除指定 revision 之前的所有历史版本,以回收存储空间。
一次典型的读操作流程如下:
- 客户端发起一个带有
revision参数的读请求(例如--rev=100)。 - etcd 在 treeIndex 中查找用户 key,获取其所有 revision 列表。
- 在 revision 列表中,找到小于等于请求 revision 的最大 revision(例如 revision=100)。
- 使用该 revision 和用户 key 拼接成物理 key,在 BoltDB 中执行一次精确查找,获取对应的 value。
- 返回结果。如果未找到,则返回 key 不存在。
下图展示了 MVCC 读操作的完整数据流:
3.4 压缩(Compaction)与容量水位
MVCC 带来的历史版本堆积是 etcd 存储容量增长的主要来源。etcd 通过 自动压缩 和 手动压缩 两种方式来管理历史版本。
- 自动压缩:基于时间周期(如每 5 分钟压缩一次)或 revision 间隔(如每 10000 个 revision 压缩一次)。
- 手动压缩:运维人员通过
etcdctl compaction命令指定一个 revision,删除该 revision 之前的所有历史版本。
- 历史版本数量:通过
etcdctl endpoint status 的 DB SIZE 和 HISTORY SIZE 字段监控。- 压缩延迟:如果压缩速度跟不上写入速度,历史版本会持续堆积,导致 DB SIZE 异常增长。
- 碎片整理:压缩操作会在 BoltDB 中产生空闲页,需要定期执行
etcdctl defrag 来回收磁盘空间。
理解 MVCC 机制是评估 etcd 存储容量水位的前提。运维人员需要密切关注 revision 的增长速率、压缩策略的有效性以及 DB SIZE 的变化趋势,才能准确判断存储组件的健康状态。