Zookeeper 多领导选举问题

Zookeeper multiple leader election issue

我有一个使用 ZooKeeper 进行领导选举的分布式应用程序。 Only the elected leader can commit to the database.我最近发现有一个潜在的情况可能会导致多个领导者。当民选领导人被暂停长时间的GC并可能输给动物园管理员的心跳,导致选举新领导人时,就会发生这种情况。此时,两个节点都认为自己是领导者并可能导致冲突。

关于如何避免这种情况有什么建议吗?

当您使用 ZooKeeper 进行领导者选举时,您 无法保证领导者的唯一性 。有可能 运行即使没有 GC 暂停,也会陷入这种情况。例如,当领导者在网络分区期间与 ZooKeeper quorum 隔离时,或者当领导者发出长 运行ning 查询时,死亡并且新领导者可以在当前仍然活跃时发出新查询。

解决方法是在更新数据库时使用比较并设置。一旦选出新领导者,您应该获得一个不断增加的领导者 ID(例如,通过更新 ZooKeeper 中的节点并使用其版本或 mzxid)并使用它来保护该领导者发出的每个事务。

例如,如果您想更改数据库的状态,则不要使用以下事务:

BEGIN TRANSACTION;
db.update($change);
END TRANSACTION;

你应该使用像

这样的东西
BEGIN TRANSACTION;
if (db.leaderID <= $leaderID) {
    db.leaderID = $leaderID;
    db.update($change);
}
END TRANSACTION;

此技巧将保护您的系统免受并发领导者引起的不确定性的影响。当然你的数据库应该是可线性化的并且支持比较和设置。

为了更正其中一个答案,Zookeeper 确实保证了网络分区中领导者的唯一性和基于仲裁的一致性。在网络分区时,如果领导者与法定人数隔离,它将由于无法连接到法定人数的节点而失去领导地位。同时,在另一个分区中选出新的领导者。同样的道理,旧的leader所在的partition也无法选举出新的leader。通过发布新的领导者选举恢复网络分区后,该情况得到解决。