首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Etcd-数据存储(逻辑视图到物理介质)

Etcd-数据存储(逻辑视图到物理介质)

作者头像
运维小路
发布2026-02-28 18:20:18
发布2026-02-28 18:20:18
550
举报
文章被收录于专栏:运维小路运维小路

作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

数据库是一个系统(应用)最重要的资产之一,所以我们的数据库将从以下几个数据库来进行介绍。

MySQL

PostgreSQL

MongoDB

Redis

Etcd(本章节)

Etcd的数据存储体系并非简单的键值写入磁盘,而是一套分层解耦、各司其职的精巧架构。它要同时满足三个看似矛盾的需求:Raft协议对持久性的苛刻要求多版本并发控制对历史数据的保留需求生产环境对高性能读写的现实追求。etcd的存储设计,正是这三者平衡的产物。本文将从Raft内存存储、WAL持久化、MVCC逻辑存储、BoltDB物理存储四个层次,完整还原etcd的数据流转全貌。

一、Raft日志存储层:共识协议的本地兑现

Etcd的Raft模块是一个纯粹的状态机算法库,它本身不负责持久化,也不感知磁盘。所有日志条目在Raft模块内部存储在两个关键结构中:

MemoryStorage:这并非“内存存储易失数据”之意,而是已持久化日志的内存缓存。etcd将WAL落盘后的日志载入MemoryStorage,供Raft算法快速访问。节点重启时,WAL全量回放重新填充MemoryStorage。

unstable:这是Raft模块收到但尚未通知上层持久化的日志。当etcdserver从readyc通道消费Ready结构时,unstable中的日志才进入WAL写入流程。写入成功后,这些日志从unstable移动至MemoryStorage。

这一设计的精髓在于:Raft算法层只操作内存数据结构,磁盘I/O由上层异步处理,二者通过Channel解耦。etcd的“高性能共识”由此奠基。

二、WAL持久化层:崩溃恢复的保险箱

WAL(Write-Ahead Log)是etcd数据可靠性的第一道防线。任何数据在写入状态机之前,必须先写入WAL并fsync落盘——这是Raft协议对持久性的硬性要求。

WAL以分段文件形式存储在磁盘,默认单文件64MB。当文件达到阈值,etcd执行“切分”(cut):新文件序列号+1,起始索引为当前最大索引+1。WAL中包含五类记录:MetadataType(节点元信息)、EntryType(用户日志)、StateType(Raft状态变更)、SnapshotType(快照标记)、CrcType(文件校验)-5。

写入路径:etcdserver从readyc获取一批待持久化日志,调用wal.Save()顺序追加至当前WAL文件尾部,立即执行fsync刷盘。这是etcd写入路径中唯一的同步磁盘操作,批处理机制使其代价被均摊至数十条请求。

恢复路径:节点重启时,从WAL目录读取所有分段文件,通过ReadAll()重放日志条目。若存在快照,则从快照后的第一条日志开始恢复——这是日志压缩与快照机制的衔接点

三、MVCC逻辑存储层:时间旅行能力的实现

etcd v3最核心的存储革新是多版本并发控制(MVCC)。它不再原地更新数据,而是每次写操作生成新版本,旧版本仍可访问,直至被压缩回收。

逻辑视图:etcd对外暴露的是扁平二进制键空间,按字节字典序排列。每个原子写操作(即使事务中包含多个修改)会生成一个全局单调递增的revision(修订版本)。键值对的每一次修改,都是该键在这个revision下的一个新版本。

Generation与Version:每个键从创建到删除为一个generation(代际)。创建时version=1,每次修改version+1;删除操作生成墓碑(tombstone),结束当前代际。再次Put该键时,新建代际,version从1重新计数。这种设计精妙地解决了“删除后重建”的历史版本混淆问题。

物理视图的双层索引:etcd并未将所有版本数据杂乱堆放,而是构建了内存B-tree + 磁盘B+tree的双层架构:

  • 内存B-tree(TreeIndex):以用户Key为索引,存储该Key的所有历史版本指针(指向BoltDB中的Revision)。范围查询时,先在此处快速定位起始Key。
  • 磁盘B+tree(BoltDB):以(major, sub, type)三元组为Key,存储完整的mvccpb.KeyValue结构体。注意:这里存储的是每次修改的“完整结果”,而非差值(delta)。这使得读取操作一次B+树查询即可拿到全部数据,无需追溯版本链。

四、BoltDB物理存储层:B+树的磁盘艺术

Etcd选择BoltDB作为底层存储引擎,这是一款纯Go实现的嵌入式KV数据库,其核心是B+树 + 内存映射文件(mmap)

磁盘页(Page):BoltDB将文件划分为固定4KB的页,包含meta page(事务元数据)、freelist page(空闲页索引)、branch page(索引页)、leaf page(数据页)。两个meta page交替写入,确保写入中途崩溃时可回滚-5。

事务模型:BoltDB支持完全ACID的读写事务。etcd利用其单写者、多读者能力:

  • BatchTx():获取批量写事务,积累至batchLimit(默认10000)或batchInterval(默认100ms)后统一提交fsync——这是etcd写吞吐量破万的关键。
  • ReadTx()/ConcurrentReadTx():获取读事务,基于mmap直接内存访问,零系统调用,与写事务完全并发-5。

Size与SizeInUse:这是运维中极易混淆的两个指标。Size()是BoltDB文件的物理大小(含空闲空间),SizeInUse()是实际有效数据大小。二者差值越大,碎片越严重——这正是defrag命令的修复目标。

五、结语:存储即分层,分层即性能

etcd的存储体系可以凝练为三条原则:

  1. Raft日志层只负责顺序,不负责检索——MemoryStorage与unstable的分工,使算法与I/O解耦;
  2. MVCC层只负责版本,不负责物理布局——TreeIndex与BoltDB的分工,使查询与写入并行;
  3. BoltDB层只负责持久化,不负责共识——批量提交与mmap,使磁盘从瓶颈变为流水线的一环。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维小路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MongoDB
  • 一、Raft日志存储层:共识协议的本地兑现
  • 二、WAL持久化层:崩溃恢复的保险箱
  • 三、MVCC逻辑存储层:时间旅行能力的实现
  • 四、BoltDB物理存储层:B+树的磁盘艺术
  • 五、结语:存储即分层,分层即性能
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档