ETCD——基础原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ETCD——基础原理相关的知识,希望对你有一定的参考价值。
参考技术A 一个ETCD集群一般由3个或者5个节点组成,两个quorum一定存在交集,则
即:3个节点容忍1个节点故障,5个节点容忍2个节点故障,以此类推。
首先,所有的数据都保存在B+树(灰色),当我们指定了版本信息之后,会直接到灰色B+树中去获取相关的数据;同时,还有另外一个B+树,它维护了key和revions的映射关系,查询key的数据时候,会根据key查询到revision,再通过revision查询到相应的key。
etcd 使用 raft 协议来维护集群内各个节点状态的一致性。简单说,etcd 集群是一个分布式系统,由多个节点相互通信构成整体对外服务,每个节点都存储了完整的数据,并且通过 Raft 协议保证每个节点维护的数据是一致的。
每个 etcd 节点都维护了一个状态机,并且,任意时刻至多存在一个有效的主节点。主节点处理所有来自客户端写操作,通过 Raft 协议保证写操作对状态机的改动会可靠的同步到其他节点。
etcd 的设计目标是用来存放非频繁更新的数据,提供可靠的 Watch插件,它暴露了键值对的历史版本,以支持低成本的快照、监控历史事件。这些设计目标要求它使用一个持久化的、多版本的、支持并发的数据数据模型。
当 etcd 键值对的新版本保存后,先前的版本依然存在。从效果上来说,键值对是不可变的,etcd 不会对其进行 in-place 的更新操作,而总是生成一个新的数据结构。为了防止历史版本无限增加,etcd 的存储支持压缩(Compact)以及删除老旧版本。
逻辑视图
从逻辑角度看,etcd 的存储是一个扁平的二进制键空间,键空间有一个针对键(字节字符串)的词典序索引,因此范围查询的成本较低。
键空间维护了多个修订版本(Revisions),每一个原子变动操作(一个事务可由多个子操作组成)都会产生一个新的修订版本。在集群的整个生命周期中,修订版都是单调递增的。修订版同样支持索引,因此基于修订版的范围扫描也是高效的。压缩操作需要指定一个修订版本号,小于它的修订版会被移除。
一个键的一次生命周期(从创建到删除)叫做 “代 (Generation)”,每个键可以有多个代。创建一个键时会增加键的版本(version),如果在当前修订版中键不存在则版本设置为1。删除一个键会创建一个墓碑(Tombstone),将版本设置为0,结束当前代。每次对键的值进行修改都会增加其版本号 — 在同一代中版本号是单调递增的。
当压缩时,任何在压缩修订版之前结束的代,都会被移除。值在修订版之前的修改记录(仅仅保留最后一个)都会被移除。
物理视图
etcd 将数据存放在一个持久化的 B+ 树中,处于效率的考虑,每个修订版仅仅存储相对前一个修订版的数据状态变化(Delta)。单个修订版中可能包含了 B+ 树中的多个键。
键值对的键,是三元组(major,sub,type)
键值对的值,包含从上一个修订版的 Delta。B+ 树 —— 键的词法字节序排列,基于修订版的范围扫描速度快,可以方便的从一个修改版到另外一个的值变更情况查找。
etcd 同时在内存中维护了一个 B 树索引,用于加速针对键的范围扫描。索引的键是物理存储的键面向用户的映射,索引的值则是指向 B+ 树修该点的指针。
元数据存储——Kubernetes
Service Discovery(Name Service)
Distributed Coordination: Leader Election
etcd的原理分析
k8s集群使用etcd作为它的数据后端,etcd是一种无状态的分布式数据存储集群. 数据以key-value的形式存储在其中. 今天同事针对etcd集群的运作原理做了一个讲座,总结一下.
A. etcd 数据的组织形式
etcd的API分为两种, 分别用export ETCDCTL_API=3和export ETCDCTL_API=2来区分. 两种API的调用接口不同, 其数据组织形式也不同. API_2下,其key和value都存储在内存中.
而API_3下,key存储在内存中,value存储在硬盘中. 显然, API_3更有优势,因为key是相较于value来说要短小的多. 这里我们讨论的是更为常用的API_3下的数据组织.
在etcd中,key以B树的形式存储在内存中, value以B+树的形式存储在硬盘中. 为什么要以B/B+树的形式来存储呢? 这涉及到一个所有的数据系统都要面对的问题, 如何花更少的时间
将数据从硬盘中读取出来. 众所周知, 计算机的存储体系里, cache> 内存>>> 磁盘, 也就是说对于etcd来说,访问一个数据最大的时间消耗在磁盘访问. 那么就要想方设法降低访问磁盘的
次数. 这个时候B/B+树的优势就体现出来了. 下面详细分析一下.
B/B+树模型的源头是AVL(二叉平衡树). 对于AVL来说, 它每一个节点只存储一个数据, 因此对于一个很庞大的AVL树来说, 访问一个数据的时间复杂度是log2 n. 这里n是这棵AVL树
存储的数据总数. 假设有一个数据总量为1023的AVL, 访问某个数据最坏的情况下需要访问10个节点. 由于AVL树的节点之间不像数元素在内存中连续存储, 这10次节点访问操作
很有可能包含多次磁盘访问. 因此拖慢了访问速度. 而对于B/B+树来说, 设计者将每一个节点的大小设置为内存一个分页的大小(一般是4kb), 而内存的一个分页的大小又等同于磁盘一个数据块的大小.因此, B/B+树相对于AVL来说的优势在于,它在硬盘中读取数据时, 单位是4kb的数据块而不是单个数据. 这样, 它将数据块读取到内存中后再进一步查找,从而大大减少了磁盘I/O的次数. 关于B/B+树在数据库系统应用中更为详细的介绍网上有很多相关资料.不再赘述.至于B树和B+树的区别,B+树只在叶子节点中存储data, 在非叶子节点中只存储search_key, B树在非叶子节点中存储的就是真正的数据.
B. etcd中如何存储一个key-value
了解了B/B+树的概念后, 我们分析一下etcd如何将数据存储到硬盘中. 首先,etcd中有个概念叫revision, 这个revision可以理解为是一个全局变量. 用户每次执行一个操作, 例如插入一个
key-pair, 这个revision就会自增1, 可以理解为这个revision就是一个全局的ID,表示已经执行了多少次操作, 每一次操作都有唯一的revision来识别. 对于内存中的B树来说, 它在进行查找时所使用的search-key是etcd key, 节点中存储的就是revision信息.而硬盘中存储的B+树的search-key就是revision值, 其节点中存储的是etcd key和etcd value. 通过这样的组织结构, etcd做到了保存每一个key 的每一个历史记录.
至此,我们可以梳理一下etcd查找关键字,例如"spe",的过程, 首先etcd根据"spe"去内存中遍历B树, 找到这个key所对应的revision, 这里revision是一组数字,包含了"spe"的每一次修改. 从
这一组revision中找到最大的那一个,如果用户指定了某个revision的话, 那么就取出用户指定的那个. 然后拿着revision去硬盘中查找B+树, 依次将节点读入内存进行查找.直至到达叶子节点,并且最终找到想要的值.
B. etcd的
以上是关于ETCD——基础原理的主要内容,如果未能解决你的问题,请参考以下文章