# 数据模型

> etcd 数据存储方法

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

etcd 旨在可靠地存储更新频率较低的数据，并提供可靠的监听查询。etcd 通过暴露键值对的旧版本，支持低成本的快照和监听历史事件（“时间旅行查询”）。持久化、多版本、并发控制的数据模型非常适合这些应用场景。

etcd 将数据存储在多版本 [持久化][persistent-ds] 键值存储中。当键值对的值被新数据覆盖时，持久化键值存储会保留该键值对的先前版本。键值存储本质上是不可变的；其操作不会就地更新结构，而是始终生成新的已更新结构。在修改后，所有历史版本的键仍可访问并可被监听。为防止数据存储随时间无限增长并避免长期保留旧版本，可对存储执行压缩以移除被覆盖数据的最旧版本。

### 逻辑视图 {#logical-view}

存储系统的逻辑视图是一个扁平的二进制键空间。键空间在字节字符串键上具有字典序排序的索引，因此范围查询的开销较低。

键空间维护多个**修订版本**。创建存储时，初始修订版本为 1。每次原子性修改操作（例如，事务操作可能包含多个操作）都会在键空间中创建一个新的修订版本。所有先前修订版本持有的数据保持不变。通过先前的修订版本仍可访问键的旧版本。同样，修订版本也进行了索引；通过监听器遍历修订版本的效率很高。若对存储执行压缩以节省空间，压缩修订版本之前的修订版本将被删除。在集群的生命周期内，修订版本单调递增。

键的生命周期跨越一个版本周期，从创建到删除。每个键可能拥有一个或多个版本周期。创建键会使其版本号递增，若该键在当前修订版本中不存在，则版本号从 1 开始。删除键会生成一个键墓碑，通过将版本号重置为 0 来结束该键的当前版本周期。对键的每次修改都会使其版本号递增；因此，在一个键的版本周期内，版本号单调递增。一旦执行压缩，所有在压缩修订版本之前结束的版本周期将被移除，且在压缩修订版本之前设置的值（除最新一个外）也将被移除。

### 物理视图 {#physical-view}

etcd 将物理数据以键值对的形式存储在持久化的 [b+tree][b+tree] 中。存储系统状态的每个修订版本仅包含相对于前一修订版本的增量，以提高效率。单个修订版本可能对应树中的多个键。

键值对的键是一个三元组（主版本、子版本、类型）。主版本表示持有该键的存储修订版本。子版本用于区分同一修订版本内的不同键。类型是可选后缀，用于标识特殊值（例如，`t` 表示值中包含墓碑标记）。键值对的值包含相对于前一修订版本的修改内容，因此仅包含与前一修订版本的差异。B+ 树按键以字节序的字典序进行排序。对修订版本差异范围的查询操作快速；这使得能够快速定位从某一特定修订版本到另一修订版本的修改。压缩操作会移除过期的键值对。

etcd 还维护一个二级内存中的 [btree][btree] 索引，以加速对键的范围查询。btree 索引中的键为存储系统向用户暴露的键。值为指向持久化 b+tree 修改记录的指针。执行压缩时会移除无效指针。

总体而言，etcd 从 btree 获取修订版本信息，然后使用该修订版本作为键，从 b+tree 中获取值（如下图所示）。
<p align="center">
  ![MVCC 数据模型](/docs/etcd/learning/img/data-model-figure-01.png)
</p>

[b+tree]: https://en.wikipedia.org/wiki/B%2B_tree
[btree]: https://en.wikipedia.org/wiki/B-tree
[persistent-ds]: https://en.wikipedia.org/wiki/Persistent_data_structure

---

反链：

- [etcd 持久化存储文件](/zh/docs/etcd/learning/persistent-storage-files/)
