( 1 )执行过半写成功并 commit 的数据 ,集群内部会保证所有机器都执行了这个事务,同时 zk 客户端收到 操作成功的提示。这个是一致性状态,包括集群内部一致性, 客户端响应结果与集群内部状态一致。
( 2 )如果 leader 执行过半写 但在 commit 之前 宕机了,那么会选举新的 leader,此时选举之后进行数据同步,这个尚未 commit 的事务最终也会在集群内部达到一致性,但是对于客户端来说 这个操作执行失败了。 此时不就出现问题了吗?比如客户端创建一个节点,集群内部显式节点创建成功,但是客户端却收到节点创建失败的结果
( 3 )如果 leader 在将事务 A 的提案发送给 FollowA 后宕机了,集群中其他 follow 节点没有收到事务 A 的提案,经过 leader 选举和数据同步之后,事务 A 的提案应该 会在集群中所有节点都执行并提交(这个理解应该没什么问题吧?),但是此时客户端收到了操作失败的响应结果,而集群内部却显式事务执行成功并提交。 这不就出现不一致了吗?
问题:zk 如何解决 2 和 3 中出现的问题的?
1
a7082633 2020-08-29 13:22:30 +08:00
2:假如你是 zk 的开发者,为什么不自己先写,然后再 commit 呢?这样即使你的 leader 在 commit 之前宕机了,follow 也没有收到 commit,也就是事务执行失败,重新选举,这就满足一致性了吧。
3:发提议之后宕机,也就是没发 commit,没 commit 那 follow 就不会执行事务啊。(第 3 点你描述的我有点懵)。 |
2
SachinBeyond OP @a7082633
(2) leader 执行过半写成功收到了 Follow 的响应(注意 leader 收到了过半写成功确认 ack ), 但是在 leader 向 Follow 发出 commit 指令的时候 leader 宕机了。 这个时候 集群进行 leader 选举。 选举后 集群内部会进行数据同步,这个没有被上一任 leader 提交的事务 会被新 leader 重新发出 事务提案到 所有 follow,然后所有 follow 执行事务并返回响应 ACK 到新 leader, 新 leader 执行 commit,从而实现 将这个事务应用到集群中每一台机器。 但是因为上一任 leader 宕机, 客户端会收到操作执行失败的结果。 比如客户端创建一个节点,集群内部显式节点创建成功,但是客户端却收到节点创建失败的结果。 ------以上是对原问题的 重新描述-------- 你说的“ follow 也没有收到 commit,也就是事务执行失败 ” 这话好像不太正确。 参考 https://blog.csdn.net/u010627840/article/details/100526648 这里面有下面一段话 比如 leader 发起提议 P1,并收到半数以上 follower 关于 P1 的 ACK 后,在广播 commit 消息之前宕机了,选举产生的新 leader 之前是 follower,未收到关于 P1 的 commit 消息,内存中是没有 P1 的数据。而 ZAB 协议的设计是需要保证选主后,P1 是需要应用到集群中的。这块的逻辑是通过选主后的数据同步来弥补。 也就是,follow 没有收到 commit,但是对于集群来说 这个事务 最终也会被集群中的所有节点执行。 但是对于客户端,因为 leader 宕机导致事务执行失败, |
3
lance6716 2020-08-29 15:54:57 +08:00 via Android
返回给客户端状态未确定,等着重试去查
|
4
SachinBeyond OP @lance6716 不太理解你说的是什么意思。 我的困惑就是 2,3 两种情况下客户端都是得到 操作未成功的结果。而集群内部实际上经过一段时间同步后 客户端的操作被 保存下来了。 这个后果很严重呀,比如多个应用尝试创建一个节点,应用 A 尝试创建得到失败的结果,但是实际上节点已经被创建了,然后其他应用又因为节点已经存在无法创建成功,从而导致所有应用都不能工作
|
5
liuhan907 2020-08-29 19:52:45 +08:00 via Android
@SachinBeyond 没有明确得到提交失败的错误的时候,操作应当被视为状态未确定,需要重试,而不是直接判定为失败。
|
6
SachinBeyond OP @liuhan907
有点理解,但又觉得你说的有问题。 你说的前提是客户端没有明确得到提交失败的错误的时候 而实际,客户端做 zk 写操作,由于 leader 宕机,集群需要重新选举 leader 和做数据同步。这个时候客户端难道不会收到因 leader 宕机导致写操作事务失败的回复吗? |
7
liuhan907 2020-08-30 11:11:43 +08:00 via Android
@SachinBeyond 网络错误和提交错误是两回事。发生网络错误的时候一定要重试来确定状态。
|
8
edgar 2020-08-30 21:26:35 +08:00
网络失败和请求执行失败是不同的,网络失败时客户端需要不断重试。可以类比 leader 已经在整个集群里让客户端的请求达成一致,但是正在发送回复给客户端时 leader 挂了或者是客户端挂了。
|
9
SachinBeyond OP |