diff --git a/README.md b/README.md index d6fcab10..722c681e 100644 --- a/README.md +++ b/README.md @@ -111,10 +111,6 @@ File, InputStream OutputStream, Reader Writer, Serializable, Socket, NIO 整理自《大规模分布式存储系统》 -> [一致性协议](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/一致性协议.md) - -两阶段提交、Paxos、Raft、拜占庭将军问题。 - > [分布式问题分析](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/分布式问题分析.md) 分布式事务、负载均衡算法与实现、分布式锁、分布式 Session、分库分表的分布式困境与应对之策。 diff --git a/notes/一致性协议.md b/notes/一致性协议.md deleted file mode 100644 index 4d14be8f..00000000 --- a/notes/一致性协议.md +++ /dev/null @@ -1,157 +0,0 @@ - -* [一、两阶段提交协议](#一两阶段提交协议) -* [二、Paxos 协议](#二paxos-协议) -* [三、Raft 协议](#三raft-协议) -* [四、拜占庭将军问题](#四拜占庭将军问题) -* [五、参考资料](#五参考资料) - - - -# 一、两阶段提交协议 - -Two-phase Commit(2PC)。 - -可以保证一个事务跨越多个节点时保持 ACID 特性。 - -两类节点:协调者(Coordinator)和参与者(Participants),协调者只有一个,参与者可以有多个。 - -## 运行过程 - -- 准备阶段:协调者询问参与者事务是否执行成功; - -- 提交阶段:如果事务在每个参与者上都执行成功,协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。 - -

- - -需要注意的是,在准备阶段,参与者执行了事务,但是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。 - -## 存在的问题 - -- 参与者发生故障。解决方案:可以给事务设置一个超时时间,如果某个参与者一直不响应,那么认为事务执行失败。 - -- 协调者发生故障。解决方案:将操作日志同步到备用协调者,让备用协调者接替后续工作。 - -# 二、Paxos 协议 - -用于达成共识性问题,即对多个节点产生的值,该算法能保证只选出唯一一个值。 - -主要有三类节点: - -- 提议者(Proposer):提议一个值; -- 接受者(Acceptor):对每个提议进行投票; -- 告知者(Learner):被告知投票的结果,不参与投票过程。 - -

- -## 执行过程 - -规定一个提议包含两个字段:[n, v],其中 n 为序号(具有唯一性),v 为提议值。 - -下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程,每个 Proposer 都会向所有 Acceptor 发送提议请求。 - -

- -当 Acceptor 接收到一个提议请求,包含的提议为 [n1, v1],并且之前还未接收过提议请求,那么发送一个提议响应,设置当前接收到的提议为 [n1, v1],并且保证以后不会再接受序号小于 n1 的提议。 - -如下图,Acceptor X 在收到 [n=2, v=8] 的提议请求时,由于之前没有接收过提议,因此就发送一个 [no previous] 的提议响应,并且设置当前接收到的提议为 [n=2, v=8],并且保证以后不会再接受序号小于 2 的提议。其它的 Acceptor 类似。 - -

- -如果 Acceptor 接收到一个提议请求,包含的提议为 [n2, v2],并且之前已经接收过提议 [n1, v1]。如果 n1 > n2,那么就丢弃该提议请求;否则,发送提议响应,该提议响应包含之前已经接收过的提议 [n1, v1],设置当前接收到的提议为 [n2, v2],并且保证以后不会再接受序号小于 n2 的提议。 - -如下图,Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的提议请求,由于之前已经接收过 [n=4, v=5] 的提议,并且 n > 2,因此就抛弃该提议请求;Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的提议请求,因为之前接收到的提议为 [n=2, v=8],并且 2 <= 4,因此就发送 [n=2, v=8] 的提议响应,设置当前接收到的提议为 [n=4, v=5],并且保证以后不会再接受序号小于 4 的提议。Acceptor Y 类似。 - -

- -当一个 Proposer 接收到超过一半 Acceptor 的提议响应时,就可以发送接受请求。 - -Proposer A 接收到两个提议响应之后,就发送 [n=2, v=8] 接受请求。该接受请求会被所有 Acceptor 丢弃,因为此时所有 Acceptor 都保证不接受序号小于 4 的提议。 - -Proposer B 过后也收到了两个提议响应,因此也开始发送接受请求。需要注意的是,接受请求的 v 需要取它收到的最大 v 值,也就是 8。因此它发送 [n=4, v=8] 的接受请求。 - -

- -Acceptor 接收到接受请求时,如果序号大于等于该 Acceptor 承诺的最小序号,那么就发送通知给所有的 Learner。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那么该提议的提议值就被 Paxos 选择出来。 - -

- -## 约束条件 - -### 1. 正确性 - -指只有一个提议值会生效。 - -因为 Paxos 协议要求每个生效的提议被多数 Acceptor 接收,并且 Acceptor 不会接受两个不同的提议,因此可以保证正确性。 - -### 2. 可终止性 - -指最后总会有一个提议生效。 - -Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性。 - -# 三、Raft 协议 - -Raft 和 Paxos 类似,但是更容易理解,也更容易实现。 - -Raft 主要是用来竞选主节点。 - -## 单个 Candidate 的竞选 - -有三种节点:Follower、Candidate 和 Leader。Leader 会周期性的发送心跳包给 Follower。每个 Follower 都设置了一个随机的竞选超时时间,一般为 150ms\~300ms,如果在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段。 - -- 下图表示一个分布式系统的最初阶段,此时只有 Follower,没有 Leader。Follower A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。 - -

- -- 此时 A 发送投票请求给其它所有节点。 - -

- -- 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。 - -

- -- 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。 - -

- -## 多个 Candidate 竞选 - -- 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票,例如下图中 Candidate B 和 Candidate D 都获得两票,因此需要重新开始投票。 - -

- -- 当重新开始投票时,由于每个节点设置的随机竞选超时时间不同,因此能下一次再次出现多个 Candidate 并获得同样票数的概率很低。 - -

- -## 日志复制 - -- 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。 - -

- -- Leader 会把修改复制到所有 Follower。 - -

- -- Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。 - -

- -- 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。 - -

- -# 四、拜占庭将军问题 - -> [拜占庭将军问题深入探讨](http://www.8btc.com/baizhantingjiangjun) - -# 五、参考资料 - -- 杨传辉. 大规模分布式存储系统: 原理解析与架构实战[M]. 机械工业出版社, 2013. -- [区块链技术指南](https://www.gitbook.com/book/yeasy/blockchain_guide/details) -- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) -- [Raft: Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft) -- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) diff --git a/notes/分布式基础.md b/notes/分布式基础.md index 920f1e15..d44cbb02 100644 --- a/notes/分布式基础.md +++ b/notes/分布式基础.md @@ -6,19 +6,25 @@ * [二、数据分布](#二数据分布) * [哈希分布](#哈希分布) * [顺序分布](#顺序分布) -* [三、负载均衡](#三负载均衡) -* [四、复制](#四复制) - * [强同步复制协议](#强同步复制协议) - * [异步复制协议](#异步复制协议) -* [五、CAP](#五cap) -* [六、BASE](#六base) + * [负载均衡](#负载均衡) +* [三、复制](#三复制) + * [复制原理](#复制原理) + * [复制协议](#复制协议) + * [CAP](#cap) + * [一致性模型](#一致性模型) + * [BASE](#base) * [基本可用](#基本可用) * [软状态](#软状态) * [最终一致性](#最终一致性) -* [七、容错](#七容错) +* [四、容错](#四容错) * [故障检测](#故障检测) * [故障恢复](#故障恢复) -* [八、CDN 架构](#八cdn-架构) +* [五、一致性协议](#五一致性协议) + * [两阶段提交协议](#两阶段提交协议) + * [Paxos 协议](#paxos-协议) + * [Raft 协议](#raft-协议) + * [拜占庭将军问题](#拜占庭将军问题) +* [六、CDN 架构](#六cdn-架构) * [参考资料](#参考资料) @@ -73,19 +79,15 @@ 可以从两个角度理解一致性:从客户端的角度,读写操作是否满足某种特性;从服务器的角度,多个数据副本之间是否一致。 -有以下三种一致性模型: - -- 强一致性:新数据写入之后,在任何数据副本上都能读取到最新值; -- 弱一致性:新数据写入之后,不能保证在数据副本上能读取到最新值; -- 最终一致性:新数据写入之后,只能保证过了一个时间窗口后才能在数据副本上读取到最新值; - ### 4. 可扩展性 指系统通过扩展集群服务器规模来提高性能的能力。理想的分布式系统需要实现“线性可扩展”,即随着集群规模的增加,系统的整体性能也会线性增加。 # 二、数据分布 -分布式系统的数据分布在多个节点中,常用的数据分布方式有哈希分布和顺序分布。 +分布式存储系统的数据分布在多个节点中,常用的数据分布方式有哈希分布和顺序分布。 + +数据库的水平切分(Sharding)也是一种分布式存储方法,下面的数据分布方法同样适用于 Sharding。 ## 哈希分布 @@ -107,31 +109,41 @@ Distributed Hash Table(DHT):对于哈希空间 [0, 2n-1],将 哈希分布式破坏了数据的有序性,顺序分布则不会。 -顺序分布的数据划分为多个连续的部分,按一定策略分布到不同节点上。例如下图中,User 表的主键范围为 1 \~ 7000,使用顺序分布可以将其划分成多个子表,对应的主键范围为 1 \~ 1000,1001 \~ 2000,...,6001 \~ 7000。 +顺序分布的数据划分为多个连续的部分,按数据的 ID 或者时间分布到不同节点上。例如下图中,User 表的 ID 范围为 1 \~ 7000,使用顺序分布可以将其划分成多个子表,对应的主键范围为 1 \~ 1000,1001 \~ 2000,...,6001 \~ 7000。 -引入 Meta 表是为了支持更大的集群规模,它将原来的一层索引结分成两层,Meta 维护着 User 子表所在的节点,从而减轻 Root 节点的负担。 +顺序分布的优点是可以充分利用每个节点的空间,而哈希分布很难控制一个节点存储多少数据。 + +但是顺序分布需要使用一个映射表来存储数据到节点的映射,这个映射表通常使用单独的节点来存储。当数据量非常大时,映射表也随着变大,那么一个节点就可能无法存放下整个映射表。并且单个节点维护着整个映射表的开销很大,查找速度也会变慢。为了解决以上问题,引入了一个中间层,也就是 Meta 表,从而分担映射表的维护工作。

-# 三、负载均衡 +## 负载均衡 -衡量负载的因素很多,如 CPU、内存、磁盘等资源使用情况、读写请求数等。分布式系统应当能够自动负载均衡,当某个节点的负载较高,将它的部分数据迁移到其它节点。 +衡量负载的因素很多,如 CPU、内存、磁盘等资源使用情况、读写请求数等。 + +分布式系统存储应当能够自动负载均衡,当某个节点的负载较高,将它的部分数据迁移到其它节点。 每个集群都有一个总控节点,其它节点为工作节点,由总控节点根据全局负载信息进行整体调度,工作节点定时发送心跳包(Heartbeat)将节点负载相关的信息发送给总控节点。 一个新上线的工作节点,由于其负载较低,如果不加控制,总控节点会将大量数据同时迁移到该节点上,造成该节点一段时间内无法工作。因此负载均衡操作需要平滑进行,新加入的节点需要较长的一段时间来达到比较均衡的状态。 -# 四、复制 +# 三、复制 + +## 复制原理 复制是保证分布式系统高可用的基础,让一个数据存储多个副本,当某个副本所在的节点出现故障时,能够自动切换到其它副本上,从而实现故障恢复。 -多个副本通常有一个为主副本,其它为备副本。主副本用来处理写请求,备副本主要用来处理读请求,实现读写分离。主副本将同步操作日志发送给备副本,备副本通过回放操作日志获取最新修改。 +多个副本通常有一个为主副本,其它为备副本。主副本用来处理写请求,备副本主要用来处理读请求,实现读写分离。 + +主副本将同步操作日志发送给备副本,备副本通过回放操作日志获取最新修改。

+## 复制协议 + 主备副本之间有两种复制协议,一种是强同步复制协议,一种是异步复制协议。 -## 强同步复制协议 +### 1. 强同步复制协议 要求主副本将同步操作日志发给备副本之后进行等待,要求至少一个备副本返回成功后,才开始修改主副本,修改完成之后通知客户端操作成功。 @@ -139,7 +151,7 @@ Distributed Hash Table(DHT):对于哈希空间 [0, 2n-1],将 缺点:可用性差,因为主副本需要等待,那么整个分布式系统的可用时间就会降低。 -## 异步复制协议 +### 2. 异步复制协议 主副本将同步操作日志发给备副本之后不需要进行等待,直接修改主副本并通知客户端操作成功。 @@ -147,17 +159,21 @@ Distributed Hash Table(DHT):对于哈希空间 [0, 2n-1],将 缺点:一致性差。 -# 五、CAP +## CAP -分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition tolerance),最多只能同时满足其中两项。这三个概念上文中已经提到。 +分布式存储系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition tolerance),最多只能同时满足其中两项。 在设计分布式系统时,需要根据实际需求弱化某一要求。因此就有了下图中的三种设计:CA、CP 和 AP。 +需要注意的是,分区容忍性必不可少,因为需要总是假设网络是不可靠的,并且系统需要能够自动容错,因此实际上设计分布式存储系统需要在一致性和可用性之间做权衡。上一节介绍的强同步协议和异步复制协议就是在一致性和可用性做权衡得到的结果。 +

-需要注意的是,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此实际上设计分布式系统需要在一致性和可用性之间做权衡。 +## 一致性模型 -# 六、BASE + + +## BASE BASE 是 Basically Available(基本可用)、Soft State(软状态)和 Eventually Consistent(最终一致性)三个短语的缩写。BASE 理论是对 CAP 中一致性和可用性权衡的结果,是基于 CAP 定理逐步演化而来的。BASE 理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。 @@ -175,13 +191,17 @@ BASE 是 Basically Available(基本可用)、Soft State(软状态)和 Ev ## 最终一致性 -指所有的数据副本,在经过一段时间的同步之后,最终都能够达到一致的状态。 +一致性模型包含以下三种: -强一致性需要保证数据副本实时一致,而最终一致性只需要保证过一段时间是一致的。 +- 强一致性:新数据写入之后,在任何数据副本上都能读取到最新值; +- 弱一致性:新数据写入之后,不能保证在数据副本上能读取到最新值; +- 最终一致性:新数据写入之后,只能保证过了一个时间窗口后才能在数据副本上读取到最新值; -ACID 是传统数据库系统常用的设计理论,追求强一致性模型。BASE 常用于大型分布式系统,只需要保证最终一致性。在实际的分布式场景中,不同业务单元和组件对一致性的要求是不同的,因此 ACID 和 BASE 往往会结合在一起使用。 +强一致性通常运用在需要满足 ACID 的传统数据库系统上,而最终一致性通常运用在大型分布式系统中。应该注意的是,上面介绍的强同步复制协议和异步复制协议都不能保证强一致性,因为它们是分布式系统的复制协议。这两种复制协议如果要满足最终一致性,还需要多加一些控制。 -# 七、容错 +在实际的分布式场景中,不同业务单元和组件对一致性的要求是不同的,因此 ACID 和 BASE 往往会结合在一起使用。 + +# 四、容错 分布式系统故障发生的概率很大,为了实现高可用以及减少人工运维成本,需要实现自动化容错。 @@ -195,7 +215,147 @@ ACID 是传统数据库系统常用的设计理论,追求强一致性模型。 当某个节点故障时,就将它上面的服务迁移到其它节点。 -# 八、CDN 架构 +# 五、一致性协议 + +## 两阶段提交协议 + +Two-phase Commit(2PC)。 + +可以保证一个事务跨越多个节点时保持 ACID 特性,也就是说它可以用来实现分布式事务。 + +两类节点:协调者(Coordinator)和参与者(Participants),协调者只有一个,参与者可以有多个。 + +### 1. 运行过程 + +1. 准备阶段:协调者询问参与者事务是否执行成功; +2. 提交阶段:如果事务在每个参与者上都执行成功,协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。 + +需要注意的是,在准备阶段,参与者执行了事务,但是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。 + +

+ +### 2. 存在的问题 + +- 参与者发生故障。解决方案:可以给事务设置一个超时时间,如果某个参与者一直不响应,那么认为事务执行失败。 +- 协调者发生故障。解决方案:将操作日志同步到备用协调者,让备用协调者接替后续工作。 + +## Paxos 协议 + +用于达成共识性问题,即对多个节点产生的值,该算法能保证只选出唯一一个值。 + +主要有三类节点: + +- 提议者(Proposer):提议一个值; +- 接受者(Acceptor):对每个提议进行投票; +- 告知者(Learner):被告知投票的结果,不参与投票过程。 + +

+ +### 1. 执行过程 + +规定一个提议包含两个字段:[n, v],其中 n 为序号(具有唯一性),v 为提议值。 + +下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程,每个 Proposer 都会向所有 Acceptor 发送提议请求。 + +

+ +当 Acceptor 接收到一个提议请求,包含的提议为 [n1, v1],并且之前还未接收过提议请求,那么发送一个提议响应,设置当前接收到的提议为 [n1, v1],并且保证以后不会再接受序号小于 n1 的提议。 + +如下图,Acceptor X 在收到 [n=2, v=8] 的提议请求时,由于之前没有接收过提议,因此就发送一个 [no previous] 的提议响应,并且设置当前接收到的提议为 [n=2, v=8],并且保证以后不会再接受序号小于 2 的提议。其它的 Acceptor 类似。 + +

+ +如果 Acceptor 接收到一个提议请求,包含的提议为 [n2, v2],并且之前已经接收过提议 [n1, v1]。如果 n1 > n2,那么就丢弃该提议请求;否则,发送提议响应,该提议响应包含之前已经接收过的提议 [n1, v1],设置当前接收到的提议为 [n2, v2],并且保证以后不会再接受序号小于 n2 的提议。 + +如下图,Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的提议请求,由于之前已经接收过 [n=4, v=5] 的提议,并且 n > 2,因此就抛弃该提议请求;Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的提议请求,因为之前接收到的提议为 [n=2, v=8],并且 2 <= 4,因此就发送 [n=2, v=8] 的提议响应,设置当前接收到的提议为 [n=4, v=5],并且保证以后不会再接受序号小于 4 的提议。Acceptor Y 类似。 + +

+ +当一个 Proposer 接收到超过一半 Acceptor 的提议响应时,就可以发送接受请求。 + +Proposer A 接收到两个提议响应之后,就发送 [n=2, v=8] 接受请求。该接受请求会被所有 Acceptor 丢弃,因为此时所有 Acceptor 都保证不接受序号小于 4 的提议。 + +Proposer B 过后也收到了两个提议响应,因此也开始发送接受请求。需要注意的是,接受请求的 v 需要取它收到的最大 v 值,也就是 8。因此它发送 [n=4, v=8] 的接受请求。 + +

+ +Acceptor 接收到接受请求时,如果序号大于等于该 Acceptor 承诺的最小序号,那么就发送通知给所有的 Learner。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那么该提议的提议值就被 Paxos 选择出来。 + +

+ +### 2. 约束条件 + +**(一)正确性** + +指只有一个提议值会生效。 + +因为 Paxos 协议要求每个生效的提议被多数 Acceptor 接收,并且 Acceptor 不会接受两个不同的提议,因此可以保证正确性。 + +**(二)可终止性** + +指最后总会有一个提议生效。 + +Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性。 + +## Raft 协议 + +Raft 和 Paxos 类似,但是更容易理解,也更容易实现。 + +Raft 主要是用来竞选主节点。 + +### 1. 单个 Candidate 的竞选 + +有三种节点:Follower、Candidate 和 Leader。Leader 会周期性的发送心跳包给 Follower。每个 Follower 都设置了一个随机的竞选超时时间,一般为 150ms\~300ms,如果在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段。 + +- 下图表示一个分布式系统的最初阶段,此时只有 Follower,没有 Leader。Follower A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。 + +

+ +- 此时 A 发送投票请求给其它所有节点。 + +

+ +- 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。 + +

+ +- 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。 + +

+ +### 2. 多个 Candidate 竞选 + +* 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票,例如下图中 Candidate B 和 Candidate D 都获得两票,因此需要重新开始投票。 + +

+ +* 当重新开始投票时,由于每个节点设置的随机竞选超时时间不同,因此能下一次再次出现多个 Candidate 并获得同样票数的概率很低。 + +

+ +### 3. 日志复制 + +- 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。 + +

+ +- Leader 会把修改复制到所有 Follower。 + +

+ +- Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。 + +

+ +- 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。 + +

+ +## 拜占庭将军问题 + +> [拜占庭将军问题深入探讨](http://www.8btc.com/baizhantingjiangjun) + +# 六、CDN 架构 通过将内容发布到靠近用户的边缘节点,使不同地域的用户在访问相同网页时可以就近获取。不仅可以减轻服务器的负担,也可以提高用户的访问速度。 @@ -206,3 +366,8 @@ ACID 是传统数据库系统常用的设计理论,追求强一致性模型。 # 参考资料 - 杨传辉. 大规模分布式存储系统: 原理解析与架构实战[M]. 机械工业出版社, 2013. +- 杨传辉. 大规模分布式存储系统: 原理解析与架构实战[M]. 机械工业出版社, 2013. +- [区块链技术指南](https://www.gitbook.com/book/yeasy/blockchain_guide/details) +- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) +- [Raft: Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft) +- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/)