文章目录

  • 1. 投票选主
    • 1.1 ZooKeeper
    • 1.2 Etcd
  • 2、竞争选主
  • 3、总结

孙玄:毕业于浙江大学,现任转转公司首席架构师,技术委员会主席,大中后台技术负责人(交易平台、基础服务、智能客服、基础架构、智能运维、数据库、安全、IT 等方向);前58集团技术委员会主席,高级系统架构师;前百度资深研发工程师;

【架构之美】微信公众号作者;擅长系统架构设计,大数据,运维、机器学习等技术领域;代表公司多次在业界顶级技术大会 CIO 峰会、Artificial、Intelligence、Conference、A2M、QCon、ArchSummit、SACC、SDCC、CCTC、DTCC、Top100、Strata+、Hadoop World、WOT、GITC、GIAC、TID等发表演讲,并为《程序员》杂志撰稿 2 篇。

分布式系统为了保证其可靠性,一般都会多节点提供服务,各别节点的故障不会影响系统的可用性。对于分布式的存储系统来说,在保证可用性的同时,数据的可靠性(不丢失)也是其要解决的核心问题。目前通用的方案是使用多副本存储。这就会引入一个新的问题,分布式存储系统的又一核心问题——多个副本间的数据一致性保障。所以就有了各种数据一致性协议。例如:Zookeeper 的 Zab、Etcd 使用的 Raft 和无比复杂的 Paxos 等等。这些一致性协议都有一个共同的特点,那就是都有一个主节点(Leader)负责数据的同步。

本文不讨论这些一致性协议的工作原理,我们重点聊一聊它们的选主策略——当Leader 挂掉后,集群必须有能力选出一个新的 Leader。为什么只讨论选主呢?因为在我们的工作中几乎不太可能去设计实现一致性协议,但"选主"这个事儿还是有可能需要我们去做的。例如之前文章介绍的时间轮,我们有多个节点提供服务,但只能有一个节点去转动轮子(一秒移动一次当前指针),这个时候就需要系统中始终有一个 Leader 负责转动轮子。业务上类似的需求还有很多,这里就不举例了,接下来我们介绍下几种选主策略。

首先明确下选主的时机:一般发生在集群的 Leader 宕机或者集群刚刚启动时,集群中没有 Leader,这时就会触发选主。这里有两个技术点:
1、集群中节点需要能够感知到 Leader 的存在;
2、从剩余的活跃节点中选出一个新的 Leader;
选主常用的方式有两种:投票和竞争,下面我们分别介绍下。

1. 投票选主

在投票选主方式中,一般集群中会有两种角色:Leader 和 Follower,Leader 和各Follower 间保持心跳,Follower 通过心跳判断 Leader 是否存活,如果 Follower 感知不到 Leader,则触发选举。获得集群半数以上节点投票的 Follower 将成为集群新的 Leader。为了提高选举的效率,集群节点数一般都为奇数个。
那么 Leader 是如何选出来的呢?不同的一致性协议,有不同的玩法,下面简单了解下 Zookeeper 和 Etcd 的选主方式(为了便于理解对模型做了简化,只描述核心算法和思路):

1.1 ZooKeeper

ZK 的节点在投票时是通过比较两个“ID”来决定把票投给谁的:
1、ZXID:ZooKeeper 事务 Id,越大表示数据越新;
2、SID:集群中每个节点的唯一编号;
投票时的比较算法为:谁的 ZXID 大谁胜出,ZXID 相同情况谁的 SID 大谁胜出(简单理解:谁的数据新胜出,数据一样谁的编号大谁胜出)。

选举算法如下:
1、集群失去 Leader 后,所有节点进入 Looking 状态,向集群中广播(第一轮投票)自身选举值(SID,ZXID),投自己一票;
2、每个节点都会将自身选举值与收到的所有其它节点的选举值作比较,选出“最大”的,如果最大的不是自己,则改投最"大“节点,广播变更(第二轮投票);
3、集群中节点收到第二轮结果后,统计超过半数的选举值,其对应的节点将成为集群新的 Leader;选举过程入下图所示:

1.2 Etcd

Etcd 使用 Raft 一致性协议,集群中每个节点都有自己的倒计时器,且时间随机。Follower 每次收到心跳后都会重置倒计时器,当某个 Follower 的倒计时结束,说明长时间没有收到心跳,就可以认为 Leader 挂了,需要选举新的 Leader 了。这个 Follower 就会触发选举,想成集群为新的 Leader。

Follower 首先会将自身状态改为 Candidate,并向所有节点发起投票,如果得到半数以上节点的同意则成为集群新的 Leader。否则,在下次倒计时结束后发起新一轮选举。

Raft 选举过程中,投票节点通过对比任期(Term,一个连续递增的整型值)和CommitId(类似 ZK 的事务 Id)来判断是否投“同意”票。选举过程如下:

1、Candidate 发起投票时将自身当前任期加 1 (NewTerm),并向集群中所有节点发起投票请求(请求中包含新的任期值);

2、Follower 节点将自身当前任期(CurrentTerm)和收到的 Candidate 投票请求中带来的 NewTerm 比较,如果 NewTerm 大就投“同意”票(这里忽略的 CommitId的比较是为了更好理解和强调 Term 的作用,比较方法与 ZK 类似);

3、Candidate 得到大于半数节点的”同意“后成为 Leader,与其他节点建立心跳,并更新所有节点的当前任期为 NewTerm;

4、如果不够半数,则选举失败,等待倒计时器下次到期发起下一轮选举;
选举过程如图2、图3所示:


集群正常情况下,各节点处于同一任期,Leader 节点定时发送心跳重置各Follower 倒计时器,当 Leader 心跳中断后,Follower 倒计时器不再被重置,则会必然会有节点到期,触发选举,图2中 Follower 1先到期,变为 Candidate 并发起选举,进入下一任期。

选举成功,原 Follower 成为集群新的主节点,开始向各 Follower 发送心跳,并更新其它节点的任期。

上面介绍的流程只是最简单的场景,实际情况会复杂些,例如有可能会有产生多个 Candidate,因为只要有 Follower 节点到期,就会发起投票,进入 Candidate 状态,Reft 是如何尽量避免产生多个 Candidate 的呢?

首先各节点倒计时时间随机,尽量避免同时到期。其次 Follower 收到 Candidate 的投票请求时会重置自己的倒计时器,这样就尽量保证了在选举失败后 Candidate 能够率先到期,可以下一任期继续由它发起投票。

但是肯定还存在产生多个 Candidate 的情况,所以协议规定一个 Follower 在一个任期只能投一次票,这样就够不可能有两个 Candidate 同时获得半数以上的投票(不可能选出两个 Leader 来)。如果选举失败,由于节点倒计时器时间随机,所以几乎可以肯定会有一个 Candidate 先到期,并且大概率在下一轮选举中成为 Leader。

2、竞争选主

上面介绍的投票选举方式需要集群各节点互相感知对方的存在,实现相对复杂,下面介绍一种比较简单的方案——竞争选主。

竞争选主需要借助外部存储服务来实现,各节点通过对某个约定的 Key-Value 数据的访问,来决定谁是 Leader,假设 KV 数据为 Leader:UUID(写入前生成的唯一 Id),具体”抢主“逻辑如下:

1、尝试获取 Leader:UUID 数据,判断数据是否存在;

2、如果 Leader 不存在,则将 Leader:UUID 写入到存储服务中并设置其 TTL(如果存储服务不支持 TTL,可以将 TTL 作为Value的一部分一起写入),本地保存UUID 值,当前进程为主节点;

3、如果 Leader 存在,通过 TTL 判断是否过期,如果过期,当做 Leader 不存在处理,否则对比 Leader 的 UUID 和本地存储的 UUID 是否一致;

3.1、如果一致则刷新”数据“ TTL,当前进程为 Leader;

3.2、如果不一致则不作任何操作,当前节点不是 Leader;
集群内所有的进程,都保证以小于 TTL 的周期执行上述逻辑,Leader 就会不停的“刷新” Leader:UUID 的 TTL,始终保持自己是 Leader,如果想更安全,刷新时可以使用 CAS 的方式每次更新 UUID。当 Leader 宕机不能继续刷新后,数据必然会过期,其它节点将会竞争写入,成为集群新的 Leader(和分布式锁很像,可以理解为一把长期持有的锁,新的玩法)。


我们分析下上述逻辑,当约定的 Key 不存在时,集群处于没有主或主挂了的状态,其他节点可以通过判断这个 Key 感知到 Leader 是否存在,从而触发选主,写入 Key 的过程相当于竞争选主的过程,谁写入成功谁就是新的 Leader。

3、总结

本文介绍了两种选主方式,竞争的方式很好理解,实现也非常简单,但为什么存储系统很少选择竞争选主方案?如果我们的业务模块要实现选举使用那种方案好一些?欢迎大家在留言区讨论。

孙玄:分布式系统选主怎么玩相关推荐

  1. 分布式系统选主怎么玩

    来自:架构之美 分布式系统为了保证其可靠性,一般都会多节点提供服务,各别节点的故障不会影响系统的可用性.对于分布式的存储系统来说,在保证可用性的同时,数据的可靠性(不丢失)也是其要解决的核心问题.目前 ...

  2. ZAB协议选主过程详解

    说明 ZAB 协议是为分布式协调服务ZooKeeper专门设计的一种支持崩溃恢复的一致性协议.基于该协议,ZooKeeper 实现了一种主从模式的系统架构来保持集群中各个副本之间的数据一致性. ZAB ...

  3. Etcd集群的介绍和选主应用

    女主宣言 ETCD作为开源.分布式.高可用.强一致性的key-value存储系统,提供了配置共享和服务发现等众多功能.目前已广泛应用在kubernetes.ROOK.CoreDNS.M3以及opens ...

  4. CAP原理,分布式一致性算法,两阶段提交,三阶段提交,Paxos,Raft,zookeeper的选主过程,zab协议,顺序一致性,数据写入流程,节点状态,节点的角色

    我们知道,一般在分布式应用都有CAP准则: C Consistency, 一致性,分布式中的各个节点数据保持一致 A availability 可用性,任何时刻,分布式集群总是能够提供服务 P par ...

  5. 【SDCC讲师专访】58同城孙玄:一切抛开业务的架构设计都是耍流氓

    本期我们采访的讲师是来自58同城高级系统架构师&技术负责人孙玄,他是58的技术委员会架构组主任,产品技术学院优秀讲师,代表58同城参与多次对外演讲. 58同城高级系统架构师,技术委员会架构组主 ...

  6. 《叶问》38期,MGR整个集群挂掉后,如何才能自动选主,不用手动干预

    当集群中所有节点都宕机后,集群再次启动后,能否自动选主 1.MGR集群所有节点都宕机后,集群重启,能否自动选主和启动MGR服务 这是个来自群友的问题. 首先,MySQL服务利用 systemd 即可实 ...

  7. redis cluster集群选主

    redis 选主过程分析  当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master.由于挂掉的master可能会有多个slave.Failover的 ...

  8. Zookeeper,etcd,consul内部机制和分布式锁和选主实现的比较

    我的另外3篇文章分别介绍了Zookeeper,etcd,consul是如何实现分布式锁和选主的.本文想比较一下Zookeeper.etcd.consul内部机制有哪些不同,他们实现锁和选主的方式相同和 ...

  9. 用 Go 语言实现 Raft 选主

    用 Go 语言实现 Raft 选主 选主模块主要包括三大功能: candidate状态下的选主功能 leader状态下的心跳广播功能 follower状态下的确认功能 candidate状态下的选主功 ...

  10. Zookeeper选举算法( FastLeader选主)

    FastLeader选主算法: 看网上关于 zookeeper选主节点fast算法的描述,虽然有几篇写的非常不错,但是总感觉描述的差一些,因此打算写一个我认为的较为详细的版本让大家提点意见.当然如果有 ...

最新文章

  1. ffempge 循环_FFmpeg常用使用命令
  2. 多台服务器搭建Spark集群
  3. 用fieldset标签轻松实现Tab选项卡效果
  4. 【重复制造精讲】REM Pull List 拉料单简介
  5. 虚拟机登服务器,用虚拟机登录云服务器
  6. 修改用户名_新华美育查找用户名及修改密码的方法分享
  7. sys.argv[] 的使用详解
  8. 日志采集框架Flume、Flume介绍、概述、运行机制、Flume采集系统结构图(1、简单结构、复杂结构)...
  9. Shell 控制并发
  10. 使用 Visual Studio 2019 批量添加代码文件头
  11. 什么是javax.ws.rs.core.context? [第5部分]
  12. Matlab 格式化字符串sscanf
  13. jQuery数据转换与提交
  14. python提供两个对象身份比较操作符_标准类型对象比较操作符
  15. 《Java并发编程实践》读书笔记
  16. Mac 下 maven 安装与配置
  17. 解决阿里云轻量应用服务器不能安装应用
  18. Flink服务的HA配置
  19. n918st能刷Android5吗?,中兴 N918ST中文Recovery刷机教程
  20. Python开发——8.模块

热门文章

  1. 外贸单证制作常用名称中英互译表
  2. 自己动手,更换光猫,这次是吉比特H2-3换为华为MA5671。(中国移动光纤宽带)
  3. JSP入门必须了解的知识详解
  4. 企业级多用户发卡平台源码 源码完全开源 无任何加密
  5. 五万字,57道hadoop大厂高频面试题,每一字都细心打磨,强烈建议收藏!
  6. java读取txt文件---,java读取TXT文件的方法
  7. Oracle cmd sqlplus 命令
  8. 如何重置IE浏览器?重置IE浏览器的方法
  9. 纯Qt版中国象棋:实现双人对战、人机对战及网络对战
  10. python下载网页中的pdf文件_Python3爬虫下载pdf(一)