容器云重要组件—Etcd的概念与性能优化

大家好我是佩奇
发布于 2022-7-1 14:51
浏览
0收藏

作者 | 袁林翔

来源 | 新钛云服(ID:newtyun)

转载请联系授权(微信ID:zlm935177782)

1. Etcd的结构和优势

1.1 结构
Etcd由CoreOS公司设计和开发,是一套分布式的key-value键值对存储系统。Etcd的设计目的是解决集群管理系统中的配置文件存储和分发问题。时至今日,Etcd被Google、阿里巴巴等多个大型互联网公司广泛使用,成为大中型集群管理系统的重要解决方案。

Etcd的集群架构与典型的master-node结构并无根本区别,集群中会存在一个leader节点负责数据的同步和分发。如果leader节点处于不可用状态,集群会立刻选出另一个节点作为leader,保持主从架构稳定性。节点的内部则纵向分为Raft层和Storage层。Raft层与Raft算法同名,参与节点间元数据的同步,Storage层则负责节点元数据的存储。Storage层从内部又可以细分为负责结构映射和查询索引的treeIndex层,和负责持久化存储的boltdb层,如下图所示。
容器云重要组件—Etcd的概念与性能优化-鸿蒙开发者社区

1.2 优势
为什么Etcd会在集群的元数据存储方案中脱颖而出?首先,这与键值对存储系统的特性相关。对于key-value存储系统来说,不论数据的关系结构如何,都是以资源ID为索引,数据内容为键值进行存储的。这是一种很“扁平化”的存储。而集群系统的元数据,一般组合为xml、yml、json等形式,这些形式的文件都是很容易对象化的,使用key-value存储效率极高。从xml/json到key-value,高效的内存索引必不可少,Etcd在tree-index中建立了内部锁,保护正在写入的数据,避免写入冲突,为集群提供了健壮性。

Etcd的在大型集群中的优势,也归功于其优秀的同步算法。Etcd采用了Raft算法,相应地,它的同步层也称为“Raft层”。该算法以quorum为最小单位进行数据同步,所谓quorum,就是集群中一个节点数量大于一半的子群。由于任意两个quorum的节点数量之和必定大于集群总节点数量,因此两个quorum必定含有公共节点。因此,只要保持每一个同步周期都有一个quorum的全部节点处于正常状态,就可以保证集群的数据同步一致性。这个算法能在不花费流量同步全部节点数据的前提下,完成集群正常运行所需的最小规模同步,保证了集群的高可用。

基于其存储特性,Etcd开放了api-server,在保证节点通信能力的同时,提供了可读性较强的外部请求方式。API满足REST API的设计要求,可以使用GET、PUT、DELETE等方式读取和写入数据。Etcd的api-server还支持watch,watch采用发布-订阅模型,可以使用较低的通信流量,使节点外部的服务可以实时获取最新的节点内部信息。基于HTTP+JSON的API让你用curl命令就可以轻松使用,这使得Etcd具有简单易上手的特点。

2. Etcd与容器云的关系

Etcd是容器编排引擎Kubernetes的重要组件。Etcd是Kubernetes集群的数据核心,扮演者“服务发现者”的角色。

Kubernetes作为主从架构的集群,worker和master需要建立通信,以实现组件、服务、配置信息的同步。如果不借助服务发现机制,各个节点中就要不间断地轮询,才能知道其他节点注册了哪些新的服务。Etcd的watch接口很好的解决了服务发现的问题,带来了效率的提升。Etcd记载的并不是集群节点的服务本身,而是集群对服务的“注册”操作,某一节点的服务发生变化时,Etcd才会响应并进行数据同步。这一模型既保证了效率,也没有占用过高的网络负载。在Kubernetes的master节点中使用watch命令或通过http请求能够以很短的间隔检测各node的服务状态,就是Etcd的功劳。

3. Etcd的性能优化

3.1 存储优化
Etcd的存储层采用tree-index作为索引,boltdb作为持久化存储。性能的优化也主要围绕这两个组件进行。

Etcd默认的tree-index采用了粒度比较粗的内部锁。这导致了两个面向相近节点的写请求有很大的几率发生冲突并阻塞。提升内部锁的深度和数量,可以让面向tree-index上不同子树的请求尽可能少的产生互锁,大幅度提升存储层面对高并发请求的效率。

持久化存储的boltdb也面对存储结构方面的性能问题。Etcd内部使用默认为4KB的页面大小来存储数据。用户在删除页数据的时候,Etcd并不会将页面直接还给系统,而是使用freelist记录空闲状态的页面,当用户再次写入数据时,Etcd使用满足数据长度要求的freelist中的若干个连续页面。

容器云重要组件—Etcd的概念与性能优化-鸿蒙开发者社区

其实结论已经出现了,问题出现在freelist的“连续性”要求上。从头开始遍历直到找到一个空闲页面或许并不麻烦,但从头开始遍历找到>=N个连续空闲页面就比较麻烦了,这带来了极高的时间复杂度。阿里云团队对此提出了解决方案,他们建立了一个hashmap,以key为连续空闲页面的数量,value为满足数量要求的起始页面序号的集合。Hashmap的更新并不需要高频率反复遍历列表,当用户删除数据时,hashmap就会随之更新;当用户写入数据,需要申请一个长度为N的空间时,会向hashmap请求key=N的集合,并返回value中的第一个序号,作为数据存储的起始位置,同时hashmap也会更新。

3.2 网络优化
众所周知,信息在网络中的传输时间与网络带宽成反比,与信息量成正比。在网络带宽不发生变化的前提下,完成一个网络请求传输的数据越少,速度就越快。

Etcd在存储层使用了tree-index作为json/xml树状逻辑结构的元数据到平铺的key-value之间的路由,这意味着,树状结构任何深度的节点都能够通过索引到达。在此前提下,如果想要修改json/xml的数据,可以将路由进行到最小的公共深度,并不修改全部数据,而是修改树状结构某一个子树的数据,这样就减少了通信量。甚至,多次数据操作还可以分解为多个子操作,提升最小的公共深度,以减少对无用数据的读取,和对未修改数据的覆写。

举个简单例子,/api/v1/metadata下可访问到json数据{key1: {key11: value11, key12: value12}, key2: value2},如果相对value11进行更改,未经优化的方法是将修改后的json数据{ key1: {key11: newvalue11, key12: value12}, key2: value2}作为PUT请求的参数,访问/api/v1/metadata进行修改。由于tree-index的存在,请求可被优化为向/api/v1/metadata/key1/key11发送PUT请求,参数为newvalue11,或者向/api/v1/metadata发送PUT请求,参数为{URI: key1/key11, value: newvalue11}。通过精确利用tree-index,减小了数据的发送长度,提升了网络请求的效率。

分类
标签
已于2022-7-1 14:51:49修改
收藏
回复
举报
回复
    相关推荐