← 中文资源

简体中文版本

领导者选举

领导者选举通过租约或共识选出一个节点执行单例工作,并用栅栏令牌防止暂停后恢复的旧领导者继续写入。

阅读英文原文

领导权是租约,不是王冠

节点通过获取租约或赢得一轮共识,在某个任期内成为领导者。租约有效期间,它可以执行单例工作。困难的情况是领导者暂停的时间超过租约——例如垃圾回收、虚拟机冻结或网络延迟。另一个节点获得领导权,但暂停的进程恢复后仍然认为自己领导。如果它继续写共享存储,系统就出现了两个领导者。

栅栏令牌可以解决这个问题。每个任期都有一个单调递增的令牌。每次写入都携带该令牌,存储会拒绝令牌小于已见最高值的写入。旧领导者可能仍然认为自己掌权,但它的写入会失败。

任期 7 领导者 A -> 写入(token=7) -> 接受
A 暂停,租约过期
任期 8 领导者 B -> 写入(token=8) -> 接受
A 恢复 -> 写入(token=7) -> 被存储拒绝

选择协调层

etcd、Consul 或 ZooKeeper 等基于共识的存储提供租约和监听通知。关系数据库可以用带过期时间的比较并交换行来实现选举,但应用必须处理时钟偏移和栅栏。不要用长事务中的 SELECT ... FOR UPDATE 来代表整个工作期间的领导权;它会阻塞、超时,并且无法干净地应对进程暂停。

为交接而设计

新领导者应等待旧领导者的租约过期,并等待在途工作稳定后再接管。工作应当幂等或带栅栏,这样重复执行不会破坏状态。优雅停机应主动释放领导权;崩溃则依赖租约过期。监控选举抖动:频繁更换领导者通常意味着网络不稳定、过载,或租约相对于工作耗时过短。

何时使用

当同一时刻只允许一个执行者,且重复执行会造成危害时,使用领导者选举。优点是单写者和清晰的归属模型;缺点是对协调系统的依赖和故障转移延迟。与按 key 分区工作相比,选举更适合全局单例,但更难做到高可用。