群首节点commit消息分两步:1. 发送proposal 2. 收到超半数ack再发送commit广播。
思考1: 场景如下,一个客户端依次执行了两条命令 W1 R1(使用异步),先写后读。是否存在这种情况:W1请求在上述的 proposal和ack未完成或者已完成但客户端连接的服务器未commit,此时读的可能仍然是老数据?
答:是的,ZooKeeper不能保证读的强一致性。
思考2:群首节点依次广播两条proposal P1 P2。假如跟随节点对这两个proposal皆ACK但是由于网络原因导致P2 先一步 到达群首(考虑极端情况,所有P1的ACK都晚到),那么是否使得ZooKeeper不能按照提交顺序P1->P2执行事务了呢?而会是P2->P1?
答:不能。
先看Follower 对proposal的处理
FollowerZooKeeperServer
follower会使用阻塞队列依次存储P1->P2。
再来看群首收到P2的ACK消息处理方法。
Leader
1.先有一个zxid的校验,如果P2先到,不影响这个校验
2. 向follower发送commit消息
我们再回来看follower的commit方法
FollowerZooKeeperServer
这里会取出刚才阻塞队列中的第一个节点 即P1,commit的zxid属于P2,显然不一致,系统重启,重新同步数据。
但是再从群首对于ACK消息的处理方法看,因为
commit P2的时候
lastCommitted=P2.zxid了,所以会导致
P1消息的ACK被拒绝。
那么问题来了,这种情形是不是就表示P1被跳过了呢?
有请楼下大神解答。。。
原文:https://www.cnblogs.com/liuyuchong/p/10858931.html