etcd架构原理
2021-10-26 本文已影响0人
Wu杰语
etcd重要的两个功能是一致性和watch,针对这两个特性深入理解一下。
一致性raft算法
一致性要学习的是raft协议,对于raft协议,有这么几个角色
角色
- Leader,有同步日志的特权,定时广播心跳给follower
- Follwer,跟随者,接收从leader发出的日志
- Candidate,竞选者
当leader失效的时候,Follower接收leader的心跳超时,就会转化为candidate节点,投票给自己,然后投票给其它节点,如果它获取到超过半数节点支持,就会成为新的leader。为了避免同时发起投票都成为leader节点,每个candidate发起投票使用了一段随机时间。简要理解就是这样,深入理解还有任期等复杂机制,我们先理解简要的就可以了。
一致性实现
交互图一致性raft实现需要很多模块的配合:
- 接口层,使用grpc作为rpc机制
- 逻辑层,预先检查模块,包括Quota和Auth,其中Quota用来检查数据库配额,如果超过数据库配额,就会直接返回失败;Auth表示鉴权,如果鉴权失败,会返回错误
- Raft层,是一致性的实现
- 逻辑层,kvserver,字面上理解,key-value server
- 存储层,wal,当有变化时,先写日志到wal,避免丢失,当大多数节点确认后,才会将日志写入boltdb状态机
- 存储层,使用mvcc机制,使用reeindex作为索引,boltdb作为数据库。
一个etcd,包含的东西可不少,对于关键的技术点我们需要注意。
- kvServer是交互的核心,可以与k8s的apiServer对比,这两个组件都是交互核心,所有其它模块都不会直接交互,都会通过这个交互核心来交互。这是etcd和k8s设计的一个重要点。用控制和逻辑思维来认知,就是kvServer是控制,其它模块都是逻辑模块,逻辑模块只和控制模块交互。
- grpc,grpc是google的开源rpc接口,可以支持多语言交互。grpc支持protobuffer和json格式,默认是protobuffer,protobuffer定义idl,客户端只要拿到idl,编译生产自己语言客户端,就可以实现对服务器的访问。
- wal日志,wal是在很多组件里面都采用的一个东西,使用了lsm存储。
- mvcc机制,mysql数据库也是mvcc机制,因为实际数据是写文件,当数据变化的时候,不是立即删除,而是新产生一个版本号数据存储起来,删除的时候只是标记一下。这样可以访问到历史数据,如果数据太大,就compact进行压缩,把无效数据或者超过限制数据删掉,这是mvcc的设计机制。
- treeindex,底层实现是B+树,B+树的目录节点不存数据,只有叶子节点存储数据,这样保障了数据存储的连续性,读取的时候可以连续读取,可以进行范围读取。
- boltdb这个数据库使用了mmap机制,从而减少了一次拷贝,直接将文件映射到内存,如果内存修改了,操作系统会定义将脏数据刷到文件。
为什么需要这么多模块,是raft协议的要求,当发起put操作时,先把日志写入wal并发送到follower,当follower半数承认后,才会把数据提交到boltdb写入。
watch机制
watch机制是核心功能
watch
通过上图可以看到,一个gprc流可以支持多个watch操作,这都是因为grpc使用了http2,http2是可以支持流式处理,不需要每个watch一个链接,所以能支持海量watch。watch是k8s控制器的核心依赖。
etcd的性能
在微服务或者组件设计,特别是k8s,会把etcd作为状态持有者,如果etcd出了问题,会导致整个集群都出现问题,可见etcd的重要性。
为了确保etcd的稳定和性能,有很多需要考虑的地方,例如:
- 为了选举,需要使用奇数个etcd节点,最好使用5个,如果使用3个,坏掉了需要立即处理,5个可以减少运维压力。
- etcd设计了一堆各个组件的运维工具,可以检查wal、boltdb等各个部件的问题。
- etcd设计了compact机制,定期瘦身
- etcd的boltdb映射到内存,所以硬件要设计一定大小,并且由于效率起见,boltdb大小也要进行限制,一般8G。
诸如此类等等,需要在工作中慢慢积累。
小结
etcd进化到v3达到工程化着实不易,通用我们看到开源的力量,一个组件只有开源,才能不断进化,有更大的场景和用户。
下一节再学习一下etcd在真实的k8s中的交互。