2020年8月27日

在研究DCache过程中,发现其计划使用ETCD作为RouterServer的分布式协调组件,所以顺便研究了一下,帮助大家了解ETCD的功能、用途以及重要原理。

1 简介

1.1 功能特性

       ETCD是一种用于实现共享配置服务发现的分布式一致性系统,具备如下功能特性: 

  • GO语言实现的,K/V分布式一致性存储系统
  • 提供HTTP API, 支持POST/GET/DELETE操作
  • 支持SSL客户端安全认证
  • 支持KEY持有TTL属性
  • 支持目录(树形)操作
  • 支持多KEY的事务操作

1.2 架构说明

etcd 架构 常见问题 etcd原理剖析_etcd 架构 常见问题



HTTP Server:用于处理客户端HTTP请求

Store:用于处理客户端大部分事务(读)

Raft:etcd的一致性协议,核心模块,数据新增或变更时调用Raft模块;

WAL:Write ahead Log,预写式日志,是etcd的持久化存储方式

Snapshot,是为了防止日志文件过多而进行的快照存储

Entry,是存储日志的具体内容。

1.3 用途

鉴于ETCD的上述特性,其可以应用于:配置中心、服务注册发现、选主、分布式锁、应用调度,分布式队列,等等场景中。

1.4 与zookeeper对比

与zookeeper对比,etcd在项目实现,一致性协议易理解性,运维,安全等多个维度上,都占据优势。

1、一致性协议

etcd使用raft协议,zk使用zab(类paxos协议),前者易于理解,方便工程实现。ZooKeeper的部署、维护、使用比较复杂,需要安装客户端。

2、多语言适配

etcd提供http+json,grpc接口,跨平台语言;zk则需要使用其专用客户端,且官方只提供了Java和C两种语言的接口。

3、访问安全方面

etcd支持https访问,zk在这方面缺失。

5、etcd读写性能

每个实例每秒支持一千次写操作。这个性能还是相当可观的。越多,由于数据同步涉及到网络延迟,会根据实际情况越来越慢,而读性能会随之变强,因为每个节点都能处理用户请求。

2 基本概念

2.1 超时时间

在Raft算法中有2种超时设置:

1、选举超时时间(electric timeout)

        当follower超过此时间未收到leader的心跳消息,会先发起投票,选举Leader。

2、心跳超时时间(heartbeat timeout)

  • Leader定时(heartbeat timeout)向follower发送心跳消息,日志复制是随着心跳消息发送的。

2.2 term

新的leader时代,每发生一次leader选举,都会刷新term值+1。

2.3 角色

ETCD中存在3种角色

  • leader
  • follower
  • candidate

3 一致性算法 --Raft

分布式协调系统的一致性算法,主要体现在选举和日志复制的过程中。

3.1 选举过程

1、所有节点初始状态为 follower

2、当 follower 没有收到 Leader的心跳时,角色就转变为 candidate,更新term值;投票给自己,然后给其他 follower发vote请求;

  • 如果此时集群里有其他 candidate,也发起了投票(vote)请求,则follwer的投票响应遵循“先到先得”原则,并且只能投票给一个candidate;也就是说谁的投票请求先到达 follower,谁就会获得该follower的投票;后到达的投票请求无法获得投票(即voteResponse中标识位为false) 。
  • 收到投票请求的节点会重置自己的选举超时时间,避免发起重复选举;

3、当candidate获得集群中半数以上的投票时,升级为Leader,开始日志复制。

4、当多个candidate收集到的票数相同,且commitIndex一致的情况下,会等待一个选举周期,进行下一次选举;

3.2 日志复制(Log replication)

3.2.1 二阶段提交

  1. leader接到客户端请求,会先写log;
  2. 将请求log发送给所有follower;follower跟leader一样写log,成功后给予响应;
  3. Leader 统计响应,如有超过半数响应成功,leader本地提交,响应客户端,然后发送commit消息给follower;
  4. follower接收到commit消息后提交本地变更
  5. 最终达到数据一致性

3.2.2 异常情况

某个follower出现异常,恢复后的数据同步:

  1. 如果在同步过程中有1个follower掉线,这个节点收不到后续的数据内容
  2. 在Leader节点上会维护每个follower当前的 commitIndex,并一直尝试发送 commitIndex 的提交请求;
  3. 当这个节点恢复后,状态仍为follower,等待leader消息;
  4. leader消息到来,follower提交本地 commitIndex 这条数据;
  5. 循环这个过程,直到 follower数据与其他节点一致;

3.4 重新选举

  1. 当leader宕机或网络异常时,follower在超过选举超时时间(electic timeout)后,变成cadidate,进入投票选举过程
  2. cadidate发起投票,重复“选举过程”

3.5 其他情况

当各follower数据不一致时,选举流程如下:

1、cadidate给 follower发送 vote请求,并附带以下信息

  • term,这个cadidate当前所处的选举周期
  • lastLogIndex,log中最新Index的位置
  • lastLogTerm,log中最新Index是在哪个选举周期产生的

2、follower在接收到vote请求时,会跟自身情况对比,每个follower保存的信息有:

  • currentTerm,follower所处的选举周期;
  • Log[],本节点上的数据;
  • commitIndex, log中最后一个提交的index;

3、比较规则:

  • 先看是否处于同一选举周期,若term < currentTerm,follower对此投票请求不予理睬(返回false);
  • 如果follower已经购票给了别人,则返回false;
  • 如果处于同一选举周期,再看数据的新旧程度;若 lastLogIndex<commitIndex,follower对此投票请求不予理睬(返回false);
  • 以上都满足,则反馈投票,并等待选举结束;

3.6 参考资料

Raft动画演示:Raft

Raft一致性算法演示:Raft Consensus Algorithm

4 其他问题

4.1 日志压缩

  1. Log是以追加的方式写入的,会越来越大;
  2. 对log采用快照的方式进行备份;并清理log中已备份、提交的内容
  3. 快照的另一个作用是:当有新节点加入时,或者某一个follower落后较多时,可以通过快照加载数据
  4. Leader必须偶尔发送一次快照给follower

4.2 客户端访问流程

  1. 客户端随机挑选一台etcd通信
  2. 如果不是leader,请求会被拒绝;follower会在响应消息中携带接收到的 leader(地址)信息;
  3. 客户端再次发送请求到Leader,进行交互;
  4. 如果Leader这时候挂了,客户端访问会超时,等待一段时间重复这个过程。

5 总结

etcd工作流程总结:

  1. 所有节点在leader,cadidate,follower之间切换
  2. 在选举阶段,cadidate向其他节点发送vote请求;最终只有包含所有最新数据的节点才能升级为leader;
  3. 在数据同步阶段,采用二阶段提交:
  • Leader在收到客户端变更请求后,先将数据写入本地log,然后发送给所有follower;
  • follower接受数据后给予成功或失败响应;
  • Leader在收到超过半数的成功响应后,提交本地log,并广播提交给follower;
  • follower在收到提交确认后提交数据