我有一个分布式应用程序,它使用ZooKeeper进行领导者选举。只有当选的领导者才能提交数据库。我最近发现,潜在的情况可能导致多个领导者。当选出的领导人暂停一个长期的GC并且可能失去对ZooKeeper的心跳时,就会出现这种情况,导致选出一位新领导人。此时,两个节点都认为自己是领导者并且可能导致冲突。
关于如何避免这种情况的任何建议?
答案 0 :(得分:1)
当您使用 ZooKeeper 进行领导者选举时,您无法保证领导者的唯一性。即使没有GC暂停,也可能遇到这种情况。例如,当领导者在网络分区期间与ZooKeeper仲裁隔离时,或者当领导者发出长时间运行的查询时,死亡和新领导者可以在当前仍处于活动状态时发出新查询。
解决方法是在更新数据库时使用compare-and-set。一旦选出新的领导者,您应该获得越来越多的领导者ID(例如,通过更新ZooKeeper中的节点并使用其版本或mzxid)并使用它来保护该领导者发布的每笔交易。
例如,如果您想要更改db的状态,而不是以下事务:
BEGIN TRANSACTION;
db.update($change);
END TRANSACTION;
你应该使用像
这样的东西BEGIN TRANSACTION;
if (db.leaderID <= $leaderID) {
db.leaderID = $leaderID;
db.update($change);
}
END TRANSACTION;
这个技巧将保护您的系统免受并发领导者造成的不确定性。当然您的数据库应该是可线性化的,并且支持比较和设置。
答案 1 :(得分:0)
为了更正答案之一,Zookeeper 确实通过基于仲裁的一致性保证了网络分区上的领导者唯一性。在网络分区时,如果领导者与仲裁隔离,它将由于无法连接到仲裁节点而失去领导权。同时,在另一个分区中选举了一个新的领导者。同理,老领导所在的分区无法选举新领导。通过发起新的leader选举恢复网络分区后,这种情况得到解决。