文章目录
- Replication
- CAP Conjecture
- Data-centric Consistency Models
- Sequential Consistency
- Causal Consistency
- Entry Consistency
- Eventual Consistency
- Client-centric Consistency Models
- Monotonic Read Consistency
- Monotonic Writes Consistency
- Read Your Writes Consistency
- Writes Follow Reads Consistency
- Replica Management
- Replica-server placement
- Client-initiated Replicas
- States versus Operations
- Pull versus Push Protocols
- Unicasting, Multicasting, or Epidemic Protocols
- Consistency Protocols
- Primary-based Protocols
- Primary-backup Protocols
- Local-write Protocols
- Replicated-Write Protocols
- Quorum-Based Protocols
- Active Replication
- Replicated State Machine
- Paxos
- Raft
- Leader Election
- Log Replication / Normal Operation
- Raft Property
Replication
数据复制的两大原因:
- Reliability & availability:可靠性、可用性
- 如果一个 replica 崩溃了,系统仍可以继续工作
- 防止 corrupted data 破坏系统
- Performance:性能
- 减少数据传输的延迟(latency)
- 根据请求数量以及地理区域而伸缩(scale)
代价:
- 存盘开销、通信开销
- 全局同步、一致性约束
CAP Conjecture
网络分区 / 脑裂:分布式系统分成了互相不能通信的多个子网络,子网络内部的计算机可以正常通信。在实际的系统中,由于节点物理分布和网络稳定性等原因,网络分区总是可能出现的。一般地,我们要求分布式协议能够容忍网络分区故障。
分布式系统的三种要求,
-
(Strict / Strong)Consistency:一致性
- all nodes see the same data at the same time
- 指数据在多个副本之间能够保持一致的特性(严格的一致性)
-
Availability:可用性
- a guarantee that every request receives a response about whether it was successful or failed
- 指系统提供的服务必须一直处于可用的状态,每次请求都能获取到非错的响应(不保证获取的数据为最新数据)
-
Partition tolerance:分区容忍
- the system continues to operate despite arbitrary message loss
- 指系统在遇到任何网络分区故障时,仍然能够对外提供满足一致性和可用性的服务(除非整个网络都发生了故障)
CAP 不可能三角:分布式系统不可能同时拥有三种性能。
权衡和取舍:
-
CA without P:
- 如果不要求 P(分区容忍),则 C(强一致性)和 A(可用性)是可以保证的。但其实分区始终会存在,因此 CA 的系统更多的是允许分区后各子系统依然保持 CA。
- Relational Database(关系型数据库)
-
CP without A:
- 如果每个请求都需要在 Server 之间达成 C(强一致性),而 P(分区容忍)会导致同步时间无限延长。如果不要求 A(可用性),如此 CP 也是可以保证的。
- 传统的数据库分布式事务,Hbase,MongoDB
-
AP without C:
- 要求 A (可用性)以及 P(分区容忍),则需放弃 C(强一致性)。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。
-
Amazon Dynamo,Facebook / Apache Cassandra;NoSQL system(非关系型数据库),Key-value storage system
- 保留 A 和 P,降低对 C 的要求(Weak consistency),例如
- 实现 Eventual consistency,利用 Gossip-based membership protocol
- 实现 Availability,利用 data replication with ( N , R , W ) (N, R, W) (N,R,W),Quorum-based: R + W > N R+W>N R+W>N
- 实现 Partition tolerance,利用 consistent hashing
- 保留 A 和 P,降低对 C 的要求(Weak consistency),例如
Data-centric Consistency Models
A consistency model is a contract between processes and the data store which says if processes agree to obey certain rules, the store promises to work correctly.
以数据为中心的一致性模型:是(若干)进程和(单个分布式)数据存储之间的契约(contract),如果进程同意遵守某些规则,那么存储器就承诺正确工作。
-
Strict consistency / Strong consistency:严格一致性 、 强一致性
-
Weak consistency:弱一致性
- Sequential consistency:顺序一致性
- Causal consistency:因果一致性
- Entry consistency:进入一致性
- Eventual consistency:最终一致性
Sequential Consistency
The result of any execution is the same as if the (read and write) operations by all processes on the data store were executed in some sequential order and the operations of each individual process appear in this sequence in the order specified by its program.
顺序一致性:任意进程的执行结果都与 “如果数据存储上的所有进程的读写操作,按照某种顺序执行,并且在单个进程上的执行按照其指定顺序出现” 的结果一样。简单地说,分布式系统并发执行的结果,与某种全排序执行的结果是一致的。
其中 W ( x ) a W(x)a W(x)a 表示将数值 a a a 写入变量 x x x,而 R ( x ) b R(x)b R(x)b 表示从变量 x x x 中读取到数值 b b b,我们简记 i : O i:O i:O 表示进程 i i i 执行操作 O O O
- 图 ( a ) (a) (a),存在一种全排序 2 : W , 3 : R , 4 : R , 1 : W , 4 : R , 3 : R 2:W,3:R,4:R,1:W,4:R,3:R 2:W,3:R,4:R,1:W,4:R,3:R,执行结果与图上的结果相同
- 图 ( b ) (b) (b),由于 P 3 P_3 P3 先读出 b b b 再读出 a a a,而 P 4 P_4 P4 先读出 a a a 再读出 b b b,无论怎么全排序,这种结果都不可能出现
Causal Consistency
Writes that are potentially casually related must be seen by all processes in the same order. Concurrent writes may be seen in a different order on different machines.
因果一致性:有因果关系的写操作,所有进程必须看到相同的顺序;而并发写,则没有这种要求。简单地说,分布式系统并发执行的结果,与某种因果排序执行的结果是一致的。
- 图 ( a ) (a) (a),存在因果关系 1 : W → 2 : W 1:W \to 2:W 1:W→2:W,但是进程 P 3 P_3 P3 却先看到 a a a 后看到 b b b,不正确。
- 图 ( b ) (b) (b), 1 : W 1:W 1:W 和 2 : W 2:W 2:W 是并发关系, P 3 P_3 P3 和 P 4 P_4 P4 都是正确的。
Entry Consistency
一组操作被一对 Acquire
和 Release
操作括起来,
- Acquire:进入临界区(critical region),获取到某个同步变量
- Release:离开临界区 CS,释放这个同步变量
- Synchronization Variables:同步变量,它的 Owner 是当前持有此变量的进程
An acquire access of a synchronization variable is not allowed to perform with respect to a process until all updates to the guarded shared data have been performed with respect to that process
Before an exclusive mode access to a synchronization variable by a process is allowed to perform with respect to that process, no other process may hold the synchronization variable, not even in nonexclusive mode
After an exclusive mode access to a synchronization variable has been performed, any other process’s next nonexclusive mode access to that synchronization variable may not be performed until it has performed with respect to that variable’s owner
进入一致性:在同步变量完成更新之前,不允许其他进程执行对它的获取访问(acquire access);在一个进程进入关于某同步变量的独占模式(exclusive mode)之前,没有其他进程正在持有这个同步变量;当一个同步变量开始被独占访问,其他进程对于此同步变量的非独占访问(nonexclusive mode access)可能并不会立即执行,要等待该同步变量的 owner 独占执行完毕之后。简单地说,对变量加锁,独占操作执行结束以前,没有其他进程可以访问这个变量。
上图是一个满足进入一致性的例子,同步变量 x x x 的锁是 L x L_x Lx,
- 仅当 P 1 P_1 P1 释放 L x L_x Lx 之后, P 2 P_2 P2 才可以获取到 L x L_x Lx 进入独占模式
- 在 y y y 被 P 1 P_1 P1 独占访问(写操作)时, P 2 P_2 P2 对于 y y y 的进行非独占访问(读操作),返回的值无效
客户访问分布式对象时,感受不到进入一致性(透明性):客户 call 分布式对象,先获取这个同步变量,然后把最新的对象 copy 给客户,最后释放锁。
Eventual Consistency
If no updates take place for a long time, all replicas will gradually become consistent.
Tolerate a relatively high degree of inconsistency.
最终一致性:如果长时间不更新,那么所有的 replica 将逐渐变成一致的,这可以容忍相对较高的不一致程度。
不一致的度量(Metrics for defining inconsistencies):
- numerical deviation,数值的偏差
- deviation in staleness,过时性的偏差
- ordering deviation,排序的偏差
Client-centric Consistency Models
For an eventual consistent data store, client-centric consistency provides guarantees for a single client concerning the consistency of accesses to a data store by that client.
以客户为中心的一致性模型:在 Eventual consistency Data Store 的情况下,为单个客户提供有关数据存储的访问的保证。
- Monotonic-read consistency:单调读一致性
- Monotonic-write consistency:单调写一致性
- Read-your-writes consistency:读你所写一致性
- Writes-follow-reads consistency:先读后写一致性
Monotonic Read Consistency
If a process reads the value of a data item x, any successive read operation on x by that process will always return that same value or a more recent value.
单调读一致性:一个进程读取到了某数据项的值,接下来的同一个进程对这个数据项的读操作,将会得到相同的值或者更新的值。简单地说,读取分布式存储,就如同读取单个本地存储。
其中 W S ( x i ) WS(x_i) WS(xi) 表示在站点 i i i 上数据项 x x x 的副本(Write Series on data item x on site i),而 W S ( x i [ t 1 ] ; x j [ t 2 ] ) WS(x_i[t_1];x_j[t_2]) WS(xi[t1];xj[t2]) 表示已经将时刻 t 1 t_1 t1 的副本 x i x_i xi copy 到了时刻 t 2 > t 1 t_2>t_1 t2>t1 的本地副本 x j x_j xj 上(副本 x 2 [ t 2 ] x_2[t_2] x2[t2] 比 x 1 [ t 1 ] x_1[t_1] x1[t1] 更新)。
- 图 ( a ) (a) (a),站点 L 2 L_2 L2 把 L 1 L_1 L1 上的数据 copy 下来,因此 1 : R 1:R 1:R 和 2 : R 2:R 2:R 的结果一致
- 图 ( b ) (b) (b),这个 data store 它不提供单调读一致性,因为 1 : W S 1:WS 1:WS 和 2 : W S 2:WS 2:WS 没有因果关系
Monotonic Writes Consistency
A write operation by a process on a data item x is completed before any successive write operation on x by the same process.
单调写一致性:对于一个数据项的写操作,在后续的对同一数据项的写操作之前,必须已经完成。简单地说,写入分布式存储,就如同写入单个本地存储。
- 图 ( a ) (a) (a),首先 1 : W 1:W 1:W,接着站点 L 2 L_2 L2 把 L 1 L_1 L1 上的数据 copy 下来,然后才执行 2 : W 2:W 2:W,因此有 1 : W → 2 : W 1:W \to 2:W 1:W→2:W
- 图 ( b ) (b) (b),这个 data store 它不提供单调写一致性,因为 1 : W 1:W 1:W 和 2 : W 2:W 2:W 没有因果关系
Read Your Writes Consistency
The effect of a write operation by a process on data item x will always be sent by a successive read operation on x by the same process.
读你所写一致性:一个进程对某数据项的写操作,总是会影响同一个进程后续对这个数据项的读操作。简单地说,在分布式存储上先写后读,就如同在单个本地存储上先写后读。
- 图 ( a ) (a) (a),首先 1 : W 1:W 1:W,接着站点 L 2 L_2 L2 把 L 1 L_1 L1 上的数据 copy 下来,然后才执行 2 : R 2:R 2:R,因此有 1 : W → 2 : R 1:W \to 2:R 1:W→2:R
- 图 ( b ) (b) (b),这个 data store 它不提供先写后读一致性,因为 1 : W 1:W 1:W 和 2 : R 2:R 2:R 没有因果关系
Writes Follow Reads Consistency
A write operation by a process on a data item x following a previous read operation on x by the same process, is guaranteed to take place on the same or a more recent value of x that was read.
先读后写一致性:一个进程对某数据项的读操作,同一个进程后续对这个数据项的写操作,保证覆盖了当时读取的值或者更新的值。简单地说,在分布式存储上先写后读,就如同在单个本地存储上先读后写。
- 图 ( a ) (a) (a),首先站点 L 2 L_2 L2 把 L 1 L_1 L1 上的数据 copy 下来,然后客户才依次执行 1 : R 1:R 1:R 和 2 : W 2:W 2:W
- 图 ( b ) (b) (b),这个 data store 它不提供先读后写一致性,因为 x 2 x_2 x2 并不一定比 x 1 x_1 x1 更新
Replica Management
副本(Replica)的管理:
- Replica-server placement:找出放置 data store 的最佳的位置(locations)
- Content replication and placement:找出放置 content 的最佳服务器(Servers)
- Permanent Replicas:预先把内容放置到服务器上
- Server-initiated Replicas:服务器发起的副本,数据缓存
- Client-initiated Replicas:客户发起的副本,构建客户 Caches
- Content distribution/Update propagation:内容的分发、更新的传播
- States versus Operations:状态 vs. 操作
- Pull versus Push Protocols:拉取 vs. 推送
- Unicasting, Multicasting, or Epidemic Protocols:单播、多播、传染病协议
Replica-server placement
目标环境(Target Environment):rarely-modified data store,数据几乎不更新的数据存储,例如 Web 服务的 .html
文件
把服务器 Q Q Q 上的文件 F F F 迁移(migrate)到其他服务器:
- c o u n t Q ( P , F ) count_Q(P,F) countQ(P,F),来自 P P P 的对 F F F 的请求计数,其中 P P P 是最靠近访问文件 F F F 的那个 Client 的 Server
- r e p ( Q , F ) rep(Q,F) rep(Q,F),复制阈值(replication threshold)
- d e l ( Q , F ) del(Q,F) del(Q,F),删除阈值(deletion threshold)
Client-initiated Replicas
放置:
- 把 cache 放置在客户机上
- 把 cache 放置在客户机所在的局域网上的共享机器上(a machine shared by clients on the same local-area network)
- 分布式缓存系统(Distributed cache system)
指标:
- Cache 中数据项的失效时间
- Cache 的命中率
States versus Operations
- 只传播更新的通知(a notification of an update):Invalidation protocol
- 指出 data store 的哪一部分(各个 Servers 存储相同或不同的数据项的 copy)被更新了,标记这些 copy,但不更新它们
- 在对一个 invalidated copy 执行操作之前,首先更新它(如果一个过期的 copy 没被使用,那么就不必更新了)
- 在 copy 之间传输被修改的数据(modified data):
- 只传递改变量(changes),减小带宽
- 将多个修改打包(pack)到一个消息里
- 适用于计算复杂的情况
- 在 copy 之间传输更新指令(update operation):
- 假设每个 replica 有能力通过执行操作使得数据保持最新状态
- 适用于数据复杂的情况
Pull versus Push Protocols
- Push-based:推送 updates 给其他的 replicas
- Pull-based:由 Server 或者 Client 请求其他 Server 来获取 updates
混合形式(Hybrid Form):使用租期(lease),
- 在租期内,Server 推送 updates
- 如果租期到了,Client 只能定期地主动拉取 updates
Client 可以请求 Server 延长租期,续租。或者,使用动态调整租期时间:
- Age-based leases:依赖于上一次数据修改的时间
- Renewal-frequency leases:依赖于客户请求文件的频率
- 依赖于状态空间的开销(state-space overhead)
Unicasting, Multicasting, or Epidemic Protocols
-
Unicasting:分别发送 N N N 个消息给 N N N 个服务器,通常用于 pull-based 的更新传递
-
Multicasting:使用底层网络支撑的多播发送一个消息,通常用于 push-based 的更新传递
-
Epidemic Protocols:传染病协议,通常用于 eventual consistent data stores 的更新传递
Consistency Protocols
一致性协议有两种:
- Primary-based Protocols:基于主机的中心化协议
- Replicated-Write Protocols:复制写的分布式协议
Primary-based Protocols
基于主机的一致性协议:每一个数据项都关联一个主机(Primary),由这个主机负责这个数据项的写操作,这是中心化的协议。
- Remote-write:远程写
- 读操作:从本地的 copy 中读取
- 写操作:发送 write operations 到一个固定的主备份上(fixed primary copy),让它执行写操作
- Local-write:本地写
- 读操作:从本地的 copy 中读取
- 写操作:把 primary 移动(move)到接收到 write operations 的那个进程上,然后执行本地的写操作
Primary-backup Protocols
Primary-backup Protocols 是一种 Remote-write Protocols,流程如下:
- 如果 primary 是正确的,那么系统提供 sequential consistency
- 如果 primary 故障了,那么系统通过选举产生将某一个 backup 提升为 primary。如果新系统的配置恰好接管上次中断的位置(the new system configuration takes over exactly where the last left off),那么系统依旧可以提供 sequential consistency
- primary 使用视图同步的组通信(view-synchronous group communication)发送 updates 给 backups,这种组通信可以在动态组故障时提供可靠的组通信(reliable group communication with dynamic groups in the presence of failures)
- primary 通过广播心跳(heartbeat)定期维持与 backups 的联系。主机 crash 一段时间后,其他的 backups 将会发现它,开启一次选举。
Local-write Protocols
第一种方式,数据项的 Single Copy 在多个进程间传递,同一时间只有一个进程持有数据项的 copy。基于 name service 来定位资源。
第二种方式,数据项的 primary 在 Multiple Replicas 之间传递,每个 replica 都维护数据项的 copy。使用一个固定的中心服务器来实现非阻塞(Non-blocking)的更新传递。
Replicated-Write Protocols
复制写入的一致性协议:有多个 replicas 都可以执行写操作,这是分布式的协议。
-
Quorum-Based Protocols:基于法定数的协议。获得法定数(Quorum)的投票,一般而言需要 majority voting
-
Active Replication:主动复制协议。发送指令到全部的 replica 上
Quorum-Based Protocols
基于法定数的协议,假如存在 N N N 个 replicas,设置:
- N R N_R NR:读法定数(read quorum),必须收集至少这个数的 votes 才可以读取文件
- N W N_W NW:写法定数(write quorum),必须收集至少这个数的 votes 才可以修改文件
- 图 ( a ) (a) (a) 中: N R + N W > N N_R+N_W>N NR+NW>N,因此可以避免 “读写冲突” 。同时 2 N W > N 2N_W > N 2NW>N,也可以避免 “写写冲突” 。
- 图 ( b ) (b) (b) 中: N R + N W > N N_R+N_W>N NR+NW>N,因此可以避免 “读写冲突” 。但是 2 N W ≤ N 2N_W \le N 2NW≤N,可能会出现 “写写冲突” 。
- 图 ( c ) (c) (c) 中:与图 ( a ) (a) (a) 一样可以避免两种冲突。这种 N R = 1 , N W = N N_R=1,N_W=N NR=1,NW=N 的设置叫做 ROWA(Read one, Write all)
Active Replication
主动复制协议,发送写指令到全部 replicas 的基本问题:
- 确保各个 replica 上的 operations 都按照相同的顺序执行
- Agreement:每一个正确的 replica 都接收到全部的 requests
- Order:每一个正确的 replica 以相同的顺序接收到 operations
- Stability:一个 replica 仅执行具有最小标识符(unique identifier, UID)的稳定请求(stable request)
- 我们说一个 request 是在某个 Server 上是稳定的(注意这个 request 可能在其他的 Server 上依然不稳定),如果不存在来自正确 replica 的、具有更小 UID 的 request 在后续被提交给这个 Server
- 采用全序组播原语(totally-ordered multicast primitive)来发送 request
在故障-停止(Fail-Stop)模型下,Client 通过可靠的全序组播来发送 request 给全部的 Replica Servers,
- 多播的可靠性:确保每一个正确的 replica 执行同样的 request 集合
- 多播的全排序:确保每一个正确的 replica 以相同的顺序接收 request,然后以相同的顺序执行它们
- Client 接收到 1 1 1 个回应,就可以确定获得的执行结果
在拜占庭故障(Byzantine failures)模型下,Client 通过拜占庭容错协议来发送 request 给全部的 Replica Servers,
- 需要存在至少 3 f + 1 3f+1 3f+1 个服务器,使用 O M ( f ) OM(f) OM(f) 算法来容错
- Client 需要收集 2 f + 1 2f+1 2f+1 个回应,根据 majority 来确定执行结果
另外,需要避免重复调用(replicated invocations)的问题:在复制对象的顶上实现一个复制感知通信层(replication-aware communication layer on top of which replicated objects execute),每个 replicated object 都关联一个协调者(coordinator),由协调者发送和回应。
Replicated State Machine
通过 Active Replication 来实现 fault-tolerant services 的一种方案是状态机复制(State Machine Replication,SMR):
- Client 把 update 组播到全部的 Replica Servers 上
- 每一个 Server 都是一个状态机(State Machine)。如果它们的初始状态相同,并且全部的 updates 按照相同的 total order 被传递,那么所有正确的 replica 将会进入相同的状态
- 如果 Active Replication 所要求的 agreement 以及 order 都被满足了,那么 SMR 就可以实现容错服务
- 故障模型:delayed/lost messages, fail-stop (not Byzantine)
- 所有 Server 以相同的顺序执行相同的指令(execute same commands in same order)
- 复制日志(replicated log),把 request 按序记录到复制日志里
- 共识模型(Consensus module),确保正确的日志复制(proper log replication)
- 只要大多数(majority)的 Servers 正常运行,那么容错系统就可以工作
Paxos
Paxos 是 Leslie Lamport(没错,又是他)在 1990 年提出来的容忍 Fail-Stop Failure 的共识协议。后来,Paxos 发展成为了一个协议族(a family of protocols for solving consensus in a network of unreliable processors)
然而,Paxos 有一些缺点:
- Impenetrable,不能理解的:很少有人真的明白 Paxos 是如何工作的。
- Incomplete,不完整的:仅支持单个数值的协定(Only agrees on single value)、没有解决活性(Does not address liveness)、如何选择提案值(Choosing proposal values)、集群成员的管理(Cluster membership management)
- Inefficient,不高效的:需要进行两轮通信来选择一个数值
Raft
Raft 是 Lamport et al. 在 2014 年提出的一种 Understandable 分布式共识协议。它可以实现 Paxos 可以做到的任何功能。
用到的技术:leader election(选举), log replication(日志复制), safety (e.g., keep logs sequential consistency), membership changes(成员变更)
任期(Term):Time is divided into terms.
- 每个 Term 开始于一次选举,包括 Leader Election 阶段、Normal Operation 阶段
- 每个 Term 内至多有一个 Leader,可以存在没有 Leader 的情况(自然也就没有 Normal Operation 阶段)
- 每个 Server 都在本地维护自己的当前任期值(current term value),
- 在每个 RPC 调用时,都携带上自己的 current term
- 如果发现了更高的 Term,那么就更新自己的 Term,成为 Follower
- 如果接收到了过期的 Term,那么就 reply with error,携带上自己的 current term
- Term 类似于逻辑时钟,记录已发生的选举事件,识别过时的信息
Leader Election
Raft 的各个 Server 的状态转移过程如图所示:
- Follower:追随者
- 一开始,每一个 Server 都是 Follower
- Follower 被动监听来自 Leader 的规律心跳
- 如果长时间没接收到心跳,那么就成为 Candidate 开启一次选举
- Candidate:候选人
- 调用 Request Vote RPC,请求其他 Server 投票
- 如果收集到了 majority 的选票,那么就成为 Leader
- 如果等到计时器超时,也没有收集完成,那么就重新开启一次选举
- 如果收到了当前任期的、或者更高任期的 Leader 的心跳,那么就成为 Follower
- Leader:领导人
- 调用 Append Entries RPC,把自己的日志 copy 到其他的 replica 上
- 定期向自己的 Leader 发送心跳,以维持自己的统治
- 如果发现了更高任期的 Leader,那么就成为 Follower
Liveness(活性):必须有一些 Candidate 最终获胜(eventually win)
- 各个 Server 在 [ T , 2 T ] [T,2T] [T,2T] 范围内,随机地选择选举超时值(election timeouts),防止 Server 同时开启选举
- 当 T ≫ broadcast time T \gg \text{broadcast time} T≫broadcast time 时,这种随机方法 work well
- 可能连续多个 Term 没有选举出 Leader,但最终会出现一个 Leader
Safety(安全性):每个 Term 中至多有一个获胜者
- 每个 Server 在一个 Term 内只允许投 1 1 1 票
- 想要赢得选举必须收集 majority(严格过半)的选票
Log Replication / Normal Operation
日志复制的流程为:
- Client 发送指令(command)给 Leader
- Leader 将这个指令 append 到本地的 log 里(日志只能追加,不可删改)
- Leader 在下一次 heartbeat 时,发送 Append Entries RPC 给全部的 Followers
- 每个 replica 接收到指令后,本地执行完成后,通知 Leader
- Leader 收集到 majority 的回复,提交这一项(commits the entry)
- 如果等待超时,那么就重新发送 Append Entries RPC,直到接收到 Follower 的回应
- Leader 最后把计算结果发送给 Client
下面是日志的结构:
- Entries:日志的组成单元是项
- Log Index:日志项的序号
- Term:这一项所属于的任期
- Command:这一项中记录的指令
- Committed Entries:被大多数 replicas 写入日志的指令
Leader 总是认为自己的 log 是正确的,它总把自己的本地日志 copy 到那些 Followers 上。如果出现 crash 或者 message lost,那么就可能没有把日志复制到每一个 Follower 上,导致各个 replicas 的日志状态不一致。可能的错误有:
- Follower 的日志中相较于 Leader 缺少某些 entry
- Follower 的日志中拥有比 Leader 更多的 entry
- Follower 的日志中的 entry 与 Leader 的不同
Raft 要求的复制日志一致性目标:
- 如果不同的 Server 上,一些 entries 拥有相同的 index 以及 term,那么
- 这些 entry 必然存储了相同的 command
- 这个 entry 之前的所有 entries 都是相同的
- 如果给定的一个 entry 被提交了,那么之前的所有 entries 也都被提交
为了实现上述目标,Append Entries RPC 被设计如下:
- Leader 发送 RPC 时,在日志上添加一个新的 entry 时,携带上自己日志中的前一个 entry 的 ( i n d e x , t e r m ) (index,term) (index,term)
- Follower 必须首先检查
(
i
n
d
e
x
,
t
e
r
m
)
(index,term)
(index,term) 是否 match 自己的日志最后一项
- 如果一致,那么就把新的 entry 追加到自己的日志里
- 否则,发送一个 reject 回应,拒绝 Leader
- Leader 被拒绝后,重新尝试发送更低的 entry 的 ( i n d e x , t e r m ) (index,term) (index,term),直到匹配上 Follower 的 entry
- Follower 从 Leader 那里获取到 matching entry 之后的所有 entries,写入自己的日志
Safety(安全性):一旦某个 entry 被提交了,未来所有的 Leader 都必须把它记录在日志里
- Candidate 必须在 Request Vote RPC 中,提供本地日志里最后一个 entry 的 ( l a s t I n d e x , l a s t T e r m ) (lastIndex,lastTerm) (lastIndex,lastTerm)
- Server 如果发现自己的日志,比收到的 ( l a s t I n d e x , l a s t T e r m ) (lastIndex,lastTerm) (lastIndex,lastTerm) 还要新,那么就拒绝投票
- 这样,仅当 Candidate 的最后一个 entry 被存储在 majority 的 replicas 里,它才有可能提升为新的 Leader
Raft Property
性质:
- Election Safety:每个 Term 中至多只有一个 Leader
- Leader Append-Only:Leader 无法修改或者删减 entry
- Log Matching:如果两个 logs 包含了一对拥有同样的 index 以及 term 的 entry,那么之前的所有 entries 都是相同的
- Leader Completeness Safety:如果一个 entry 被提交了,那么这个 entry 将被未来所有的 Leader 所记录
- State Machine Safety:如果一个 Server 执行了某个 entry 改变了自身状态,没有其他 Server 会执行同一个 index 上的不同指令
特点:
- 分布式共识(Distributed Consensus),
- 协定(Agreement):
- 故障模型(Failure model):
- 架构(Architecture):Client / Server 架构,选举 Leader
- 依赖的技术,
- 分布式时间:Term 以逻辑时钟的方式工作
- 进程交互:使用 RPC(远程过程调用)
- 进程协作:选举算法,随机超时(Liveness),大多数投票(Safety)
- 数据复制:日志复制, 一种 Active Replication 的 Replicated-Write Protocols
- 故障处理:只有携带 up-to-date logs 的 Server 才可能成为 Leader(Safety)