paxos协议
paxos
一致性协议的目的是在分布式系统中的节点能够就一个值达成一致。paxos
将节点分为三个角色:proposer
、accepter
和learner
。proposer
主要负责提出提案,accepter
负责接受提案,而learner
负责向accepter
学习已接受的提案。每个节点可能扮演proposer
、accepter
或者learner
中的一个或者多个角色。一个提案由编号
n
n
n和提案值
v
v
v组成:
(
n
,
v
)
(n, v)
(n,v)。提案编号是在整个系统中自增的值。
协议过程
paxos协议的流程可以概括为:
准备阶段
当proposer
收到客户端发送的提案值v
时,使用自己保存的提案编号
n
n
n构成提案
n
+
1
,
v
n+1, v
n+1,v。之后proposer
开始向accepter
发送prepare
请求以确保:
- 要求
accepter
作出不会再接收编号小于 n + 1 n+1 n+1的提案的承诺;- 如果存在的话,其接受的小于 n + 1 n+1 n+1的编号最大的提案的值。
accepter
维护其作出承诺的做大提案编号
n
m
a
x
p
n_{maxp}
nmaxp和接受提案的最大编号
n
m
a
x
a
n_{maxa}
nmaxa和值
v
m
a
x
n
v_{maxn}
vmaxn。如果
n
+
1
>
n
m
a
x
p
n+1 >n_{maxp}
n+1>nmaxp则accepter
答复该prepare
请求并回之以
(
n
m
a
x
a
,
v
m
a
x
n
)
(n_{maxa}, v_{maxn})
(nmaxa,vmaxn),其他情况则不回复;
接受阶段
当proposer
收到来自集群中大多数节点的承诺之后,其通过accept
请求尝试提交提案,而提案的值变成了作出承诺的accepter
中接受过的提案中的最大提案编号。即
v
p
=
max
v
m
a
x
n
i
,
i
∈
C
v_{p} = \max v^i_{maxn}, i \in C
vp=maxvmaxni,i∈C,其中
C
C
C为所有作出承诺的accepter
。如果没有accepter
之前接受过提案,则proposer
使用原来的值
v
v
v。
当accepter
收到来自proposer
的accepter
请求的时候,判断其提案编号是否是自己承诺过的提案编号;是则回复接受,否则不回复该请求。
学习过程
有几种方法:
- 每当
accepter
接受新的提案,就将提案发送给learner
;这要求每个accepter
对每个learner
作出响应; accepter
向特定的一个learner
发送接受的值,由该learner
通知其他learner
接受值;accepter
向特定的一组learner
发送接受的值,当learner
收到填的时候即通知其他learner
。
实现状态机
前述过程存在一些问题。
问题1: 假设proposer
p和proposer
q同时提交提案,p提交提案
(
n
p
,
v
p
)
(n_p, v_p)
(np,vp),而q提交提案
(
n
q
,
v
q
)
(n_q,v_q)
(nq,vq)。首先p完成了准备阶段,q在p之后完成了准备阶段,因而
n
q
>
n
+
p
n_q > n+p
nq>n+p。此时p在完成接收阶段时其提案不会被任何一个accepter
接收,因为accepter已经承诺接收q的提案了,所以p将其提案编号增加到
n
q
+
1
n_q+1
nq+1并重新提交,完成准备阶段后q进行接收阶段,然而q的值不会被接受,因而q增大其提案编号继续提交…以上情景构成了一个死循环。
问题1的解决方法是通过选主机制选择一个leader
作为唯一的proposer
,处理并提交客户端请求。选主可以通过其他方式,如随机化或者超时来实现。
状态机的实现过程:
假设新的leader
有1~136,139号提案,其从137开始提交新的提案。在提交137号提案时,可以通过prepare过程知道accepter
已经存在的137号提案的值,138号提案类似;当提交140号提案时,就可以处理客户端请求的值了。