原文地址 Data Model
Etcd 数据存储方法
etcd 设计思想为可靠的存储,并且不经常对数据进行更新,同时提供了可靠的watch机制。etcd 可以向用户暴露出一个key-value对在当下之前的版本,以此来支持低代价的快照和watch历史变更事件。所以,一个支持持久化、多版本、并发控制的数据模型才能适用于上述使用场景。
etcd 将数据储存到一个支持多版本的key-value存储中。当一个key-value对更新时,该支持持久化的key-value存储会维护key-value对先前的版本,key-value存储的内容实际上是不可变的。对于key-value的操作并不是就地修改它,而是生成一个新的结构。所以,所有keys过去的版本仍旧是可以访问的,并且是可以被watch的。为了防止维护旧的版本导致的数据量随着时间无限制增长,可以做压缩,对过于老的数据版本进行删除。
从逻辑上来看Etcd的数据模型
存储的逻辑视图看起来像是一个平坦的二进制key空间。key空间按照key的词法排序构成索引,所以范围查询的代价不会很大。
该key空间维护key的多个修改。当存储实例被创建时,初始的全局版本(Revision)是1,每一个原子变更操作(比如,一个事务操作可能包含多个子操作)会在这个key空间上创建一个新的全局版本。所有之前的版本持有的数据保持不变。旧版本的keys仍旧可以通过使用之前的全局版本进行访问。同样的,全局版本也一样会有索引;因此Watcher可以实现高效的范围watch。如果存储实例为了节省空间而做了一次压缩,一些小于压缩时指定的全局版本的数据会被清除掉。全局版本号在整个集群的生命周期里是单调递增的。(笔者注:Revision在这里相当于一个逻辑时钟的作用,和Raft中的Term是相似的)
一个key的可能会有多个生命周期,从它被创建到被删除。每个key可能有一个或者多个生命周期(笔者注:一个key可能被创建-修改-删除-创建-删除-创建-删除等,此时该key就经历了3次生命周期)。创建该key的时候会自增它自己的版本(Version)(笔者注:这里的版本是指key内部的版本),版本会从1开始。删除一个key会生成这个key的一个里墓碑,相当于结束这个key的这一次生命周期,并将版本(Version)设置回0。每一次对一个key的修改,会自增它的版本。所以,在一个key的一个生命周期中,它的版本号是单调自增的。一旦一次压缩发生之后,除了key的最后一次写入内容,任何在压缩时使用的全局版本(Revision)之前的keys的和相应的其values集合都将会被删除。(笔者注:这里会保留key-value的最后一次的写入,因为系统还需要向外提供数据的读取和其它操作,但是会压缩掉之前的版本。)
(笔者注:这里需要解释一下,全局版本即Revision来说,无论任何一次的用户写入操作即增删改,都会自增Revision,Revision相当于一个快照时间戳一样,每一个Revision都代表了这一时刻整个存储实例的快照。对于key的更新并不会就地修改该key的内容,而是重新生成一个key的全局版本,并写入到存储实例中。)
从物理上来看Etcd的数据模型
etcd按照key-value对来保存物理数据,将保存到一个以b+树作为持久化存储上。存储实例的每个全局版本(Revision)的状态只包含了与之前的全局版本相比变化的部分,这样相对高效一些。一个全局版本可能对应了树中的多个keys。
key-value对中的key是由3元组组成的(major,sub,type),Major是存储实例的全局版本。Sub是在一次全局版本下的对keys的多次修改的子版本。Type是一个可选的后缀,用于一些特殊值(比如,'t' 如果这个key是一个里程碑(笔者注:被删除的key-value对))。key-value对中的value包含先前全局版本下的修改,因此与先前全局修改相比是一个增量。b+树将key按照字典字节序进行排序。通过全局版本来进行范围查询来查找变化的内容会是很快的,这使得从一个指定的全局版本到另一个全局版本之间的查询将能够很快完成。压缩将移除过期的keys-value对。
etcd也会维护一个内存中b树二极索引来加速那些通过keys来范围查询的请求。在b树中保存的keys就是存储实例暴露给用户的(笔者注:也就是具体写入的key的字符串),它的value就是上文中说的指向b+树中的一次修改的指针。压缩操作将移除那些无效的指针。
总的来看,etcd通过b树获取到key的全局版本信息,然后使用全局版本信息作为key去从b+树中获取value。(如下图片所示)
(笔者注:上图中 R4 R4 可能是一个Tombstone版本。仅仅为猜测。)
(翻译水平有限,如有疑问请看原文。上述内容可能对于未读过源码实现的读者会产生很多疑问,没关系读一下源码即可理解了。)
The End;