浅谈分布式一致性协议 | 青训营笔记

137 阅读5分钟

这是我参与「第四届青训营」笔记创作活动的第15天

0 引言

思维导图.png

1 分布式系统

目前来讲分布式系统面临的挑战包括数据规模越来越大、服务的可用性要求越来越高、快速迭代的业务要求系统足够易用。

对于理想中的分布式系统包括高性能(可拓展、低时延、高吞吐)、正确(一致性、易于理解)、可靠(容错、高可用)。

分布式系统我们会想到HDFS(Hadoop分布式文件系统)包括了NameNode、DataNode和Client。

Client客户端通过RPC通讯协议与分布式系统交互(K-V)。

2 一致性与共识算法

分布式一致性写(复制)与读操作
复制操作.png

  • 主副本把所有的操作打包成Log,所有的Log写入都是持久化的,保存在磁盘上;
  • 应用包装成状态机,只接收Log作为Input;
  • 主副本确认Log已经成功写入到副本机器上,当状态机apply后,返回客户端。

读操作

  • 方案一:直接读状态机,要求写操作进入状态机后再返回client
  • 方案二:写操作复制完成后直接返回,读操作Block等待所有pending log进入状态机

一致性的含义
一致性是一种模型(或语义),来约定一个分布式系统如何向外界(应用)提供服务。比如Client客户端想读取分布式机器最近写入的值,那么就需要这种一致性需要。

KV中常见的一致性模型分类:最终一致性(读取可能暂时读不到但是总会读到)、线性一致性(最严格,线性执行)。Linearizability是最理想的。

复制协议
当主副本失效时,需要保证较高的可用性,少数节点挂了的情况下仍然可以工作(容错性)。

共识算法
在分布式系统中让所有节点达成共识达到数据一致性。

在分布式系统中错误总是发生,比如网络断开、分区、缓慢、重传、乱序CPU、IO等都机会停住,因此共识算法可以达到容错(falute-tolerance),使系统整体不会因为个别机器宕机而全盘奔溃。

共识协议不等于一致性:应用层面不同的一致性,都可以用共识协议来实现,比如可以故意返回旧的值。简单的复制协议也可以提供线性一致性。

一般讨论共识协议时提到的一致性,都指线性一致性,因为弱一致性往往可以使用相对简单的复制算法实现。

3 从Raft入手

与PaxoS难以理解不同,Raft易于理解作为算法的设计目标,使用了RSM、Log、RPC(直接使用RPC对算法进行了描述)的概念,有Strong Leader-based,使用了随机的方法减少约束。对于正确性使用形式化验证,拥有大量成熟系统。

复制状态机(RSM)
RSM.png
复制状态机(replicated state machine,RSM)在Raft中所有的consensus都是直接使用Log 作为载体。

Commited Index:一旦Raft更新Commited Index,意味着这个Index前的所有Log都可以提交给状态机了。Commited lndex是不持久化的,状态机也是volatile的,重启后从第一条Log开始。

Raft角色
Raft角色.png
某时刻某服务器节点处于这三个状态之一:leader、follower或者candidate。

在正常情况下,集群中只有一个leader并且其他的节点全部都是follower。

  • Leader处理所有的客户端请求(如果一个客户端和follower通信,follower会将请求重定向给leader)。
  • follower都是被动的,他们不会发送任何请求,只是简单的响应来自leader和candidate的请求。
  • candidate是用来选举一个新的leader。

Raft整体流程 / Raft日志复制 / Raft从节点失效

Raft Term
每个leader服务于一个term,每个term至多只有一个leader(leader与term是一对多的关系)。

每个节点存储当前的term,每个节点term从一开始只增不减。

所有rpc的request reponse都携带term,只commit本term内的log。

Raft主节点失效

  • Leader定期的发送AppendEntries RPCs给其余所有节点,如果Follower有一段时间没有收到Leader的AppendEntries,则转换身份成为Candidate。
  • Candidate自增自己的term,同时使用RequestVote RPCs向剩余节点请求投票。
  • Raft在检查是否可以投票时,会检查log是否outdated,至少不比本身旧才会投给对应的Candidate。
  • 如果多数派节点投给它,则成为该term的leader。

Raft主节点失效.png

Raft安全性–同/跨Term
对于同Term内的安全性,对于所有已经的commited的<term, index>位置上至多只有一条log。

对于跨Term的安全性,如果一个log被标记commited,那这个log一定会在未来所有的leader中出现。

由于Raft的多数派选举,我们可以保证在一个term中只有一个leader,在任何<term,index>位置上,至多只有一条log。

Raft安全性验证
Raft使用TLA+进行了验证,形式验证(Formal Method),对算法所有的状态进行遍历。 Raft安全性验证.png

4 实现细节以及未来

案例K-V设计
方案一:写log被commit了,返回客户端成功;读操作先等待所有commited log apply,再读取状态机;优化写时延。

方案二:写Log被状态机apply,返回给client;读操作直接读状态机;优化读时延。

确定合法的Leadership:
方案一:通过一轮Heartbeat确认 Leadership(获取多数派的响应)
方案二:通过上一次Heartbeat时间来保证接下来的有段时间内follower不会timeout。同时follower在这段时间内不进行投票。如果多数follower满足条件,那么在这段时间内则保证不会有新的Leader产生。

参考引用

1. 分布式系列第一弹:分布式一致性!
2. 深度解析 Raft 分布式一致性协议
3.【大数据专场 学习资料六】第四届字节跳动青训营
4. 分布式一致性算法:Raft 算法(Raft论文翻译)