前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从小工到专家:网络分区 看这个就够来了

从小工到专家:网络分区 看这个就够来了

作者头像
程序员小王
发布2021-03-04 14:32:12
9710
发布2021-03-04 14:32:12
举报
文章被收录于专栏:架构说架构说

什么是“脑裂”

“脑裂” 就是双master

你的 cluster 里面有两个节点, 两个结点都会觉得现在没有 master, 所以每个都把自己选举成 master

观点1:1 集群奇数2 投票过半和3 任期大小

1、zooKeeper默认采用了Quorums这种方式来防止"脑裂"现象。

即只有集群中超过半数节点投票才能选举出Leader。

这样的方式可以确保leader的唯一性,要么选出唯一的一个leader,要么选举失败。在zookeeper中Quorums作用如下: 1] 集群中最少的节点数用来选举leader保证集群可用。 2] 通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。

一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据。

假设某个leader假死,其余的followers选举出了一个新的leader。

这时,旧的leader复活并且仍然认为自己是leader,这个时候它向其他followers发出写请求也是会被拒绝的。

因为每当新leader产生时,会生成一个epoch标号(标识当前属于那个leader的统治时期),这个epoch是递增的,followers如果确认了新的leader存在,知道其epoch,就会拒绝epoch小于现任leader epoch的所有请求。

那有没有follower不知道新的leader存在呢,有可能,但肯定不是大多数,否则新leader无法产生。

Zookeeper的写也遵循quorum机制,因此,得不到大多数支持的写是无效的,旧leader即使各种认为自己是leader,依然没有什么作用。

https://raft.github.io/

【当问到这个问题时候,现在还是一片空白,感觉很难回答,其实你思路就是基本流程,不需要特别处理】

假死:由于心跳超时(网络原因导致的)认为master死了,但其实master还存活着 假死导致脑裂的一个根源问题就是假死。timeout

脑裂:由于假死会发起新的master选举,选举出一个新的master,但旧的master网络又通了, 导致出现了两个master ,有的客户端连接到老的master 有的客户端链接到新的master。

zk quorum(半数机制)机制解决脑裂,但是timeout造成正常情况下误判???如何解决

超时机制:

  • [源码解析] 从TimeoutException看Flink的心跳机制
  • ubbo的超时机制和重试机制
  • Hystrix超时机制
  • Netty HashedWheelTimer时间轮源码学习 好多概念, 这里只说一个 轮盘定时器 HashedWheelTimer

从小工到专家:设计循环队列 也提到了。

俄罗斯轮盘

Kafka中的时间轮(TimingWheel)是一个存储定时任务的环形队列,底层采用数组实现,数组中的每个元素可以存放一个定时任务列表(TimerTaskList)。TimerTaskList是一个环形的双向链表,链表中的每一项表示的都是定时任务项(TimerTaskEntry),其中封装了真正的定时任务TimerTask

其实时间轮就是一个不存在hash冲突的数据结构 就拿秒表来说,它总是落在 0 - 59 秒,每走一圈,又会重新开始。

观点2: 对假死现象

选举是保证raft安全性的基础,心跳是保证集群能够尽快从Leader宕机或者网络分区中恢复的关键。etcd中将心跳和计时做了集成,抽象成tick

为什么需要预选 添加预选的原因是为了在网络状况不佳时,减少选举次数。

举个具体场景,当集群中的网络不稳定时,会有部分Follower不能及时地收到Leader的心跳,这时候就会有Follower发起选举。

但是网络原因,它自身也很难拿到超过半数选票当选,或者当选之后也很快就会有别的节点因为收不到心跳而再次发起选举,这就导致了集群经常处于选举状态而不可用。

为了防止这种情况的频繁发生,添加预选阶段,等于把Leader挂掉这件事从单个节点自己判断,变成了半数节点一起判断,大大减少了误判。 凡事都有利有弊,当Leader虽然没挂掉,但性能有问题时,可能只影响了不到一半的节点。添加预选之后可能会导致性能不佳的Leader很难被选下去,从而影响读写性能。

作者:空挡 链接:https://www.jianshu.com/p/ff6aaa66ea0f 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上面看不懂就对了, 现在从这个问题开始old leader根据什么来降级的,需要了解raft过程

条分缕析 Raft 算法

本文整理自 Ongaro 在 Youtube 上的视频。

系统模型

我们假设:

  • 服务器可能会宕机、会停止运行过段时间再恢复,但是非拜占庭的(即它的行为是非恶意的,不会篡改数据等);
  • 网络通信会中断,消息可能会丢失、延迟或乱序;可能会网络分区;

Raft 是基于 Leader 的共识算法,故主要考虑:

  • Leader 正常运行
  • Leader 故障,必须选出新的 Leader

优点:只有一个 Leader,简单。

难点:Leader 发生改变时,可能会使系统处于不一致的状态,因此,下一任 Leader 必须进行清理;

难点:Leader 发生改变时,可能会使系统处于不一致的状态,因此,下一任 Leader 必须进行清理;

系统正常运行时,只有一个 Leader,其余都是 Followers.

大家可以看到:

这里说明candidate状态变化,通过上面2个图

你会发现,有3个状态 1, 后退 2 不变 3 前进

问题是:原则上我们可以无限重复分割选票,

假如选举同一时间开始,同一时间超时,同一时间再次选举,如此循环。

解决办法很简单:

  • 节点随机选择超时时间,通常在 [T, 2T] 之间(T = electionTimeout
  • 这样,节点不太可能再同时开始竞选,先竞选的节点有足够的时间来索要其他节点的选票
  • T >> broadcast time(T 远大于广播时间)时效果更佳

这里对上面问题的回答,

超时设置 并不少固定不变的,而是【t,2t】 之内随机时间。

Raft在网络分区时leader选举的一个疑问?

共识算法-raft论文分析

Raft 作者亲自出的 Raft 试题,你能做对几道

资料

[1] MIT 6.824 Distributed Systems Spring 2020 中文翻译版合集: https://www.bilibili.com/video/av91748150

如何安全的领导选举(思考在双master也符合这个规则吗)

https://raft.github.io/raft.pdf

隐含条件:

1. vlolatile state on leaders 代表 不会持久化: 这个是很重要的一点。

2. 上个任期遗漏数据,不能通过上一个版本任期+写入大多数来保证安全。例子1

大家可以看到,故障发送后,通过大多数判断这个原则,失效了。

因为缺少 关键的“leader”,就是它 下线了。【过半失效、

crash的服务,你是不知道的。无法通过个数来统计了。

大家可以看到,图c中的 s5,为什么能被选择上。最后一个任期 3大于其他 节点2,s1(不统一)【任期大规则失效】

rpc请求参数隐含一个条件:单节点不知道那个是安全的,那个不是安全的。

统计个数方式不行,因此通过最新的一个记录做判断。

同样一个例子,一个写入过半数据是安全的,另外一个写入过半不是安全的。

差别在什么地方?

Case 2: Leader 试图提交之前任期的日志

如图所示的情况,在任期 2 时记录仅写在 S1 和 S2 两个节点上,由于某种原因,任期 3 的 Leader S5 并不知道这些记录,S5 创建了自己的三条记录然后宕机了,然后任期 4 的 Leader S1 被选出,S1 试图与其它服务器的日志进行匹配。因此它复制了任期 2 的日志到 S3。

此时 index=3 的记录时是不安全的

因为 S1 可能在此时宕机,然后 S5 可能从 S2、S3、S4 获得选票成为任期 5 的 Leader。一旦 S5 成为新 Leader,它将覆盖 index=3-5 的日志,S1-S3 的这些记录都将消失。

我们还要需要一条新的规则,来处理这种情况。

观察如下:下面2个情况写入大多数节点后无法保证安全:

情况1: leader挂掉后,在当前term内:通过写入大多数节点就是安全 判断失效。例如 3个节点,写入2个是安全的,其中一个节点挂掉 但是写入和没有写入个数为1 无法判断【统计个数失效】

情况2:当新选举 ,term=4,通过先处理 tern=2的,也写入大多数节点。5个写入三个 依然被覆盖的可能。【历史数据先同步失效】

抽象一下,图9 ,节点s5,当选择leader条件是,s1和s2必然同意。

还缺少一票。

假设s4 core了,必须s3同意。这保证,安全。安全安全。

s5 投票来自2部分:

什么情况下是写入安全的

  1. 当前leader节点,在任期内,必须有请求,并且该请求,写入到大多数节点。
  2. 这样不会出现被小于当前任期的数据覆盖。

初步推测:必须当前任期内,第一个日志写入到大多数节点。此时说明

这个位置坐稳了。

动手验证日志复制

这里假设2个规则 ,

在最后一条日志中(不一定是安全的),不能比我的小,

不然就❌。

大家可以看到,s2 在成为leader后,term=5,和term=4还有数据没有同步安全。

此时数据特点是:index=8的日志 和新增 index =9的日志。

任期5内日志,同步到其他节点 s1,s4 节点s5(s3 crash)

s1,s4,s5 其中 index =8 和index =9 日志是一块 “ack” 安全写入成功。

的。s2最后做统计,安全写入成功。

大家可以看出:这里有关键地方。

客户端 没有请求 和有请求

为什么新的选举后,结果是不一样的?

这个观察很重要!!!

隐藏了一个主要规则

上面只是保证了,内部一致性,与客户端关系如何呢?

这里讲述各种故障场景。

当新的 Leader 上任后,日志可能不会非常干净,因为前一任领导可能在完成日志复制之前就宕机了。Raft 对此的处理方式是:无需采取任何特殊处理。

当新 Leader 上任后,他不会立即进行任何清理操作,他将会在正常运行期间进行清理。

原因是当一个新的 Leader 上任时,往往意味着有机器故障了,那些机器可能宕机或网络不通,所以没有办法立即清理他们的日志。在机器恢复运行之前,我们必须保证系统正常运行。

大前提是 Raft 假设了 Leader 的日志始终是对的。所以 Leader 要做的是,随着时间推移,让所有 Follower 的日志最终都与其匹配。

来源:https://my.oschina.net/tantexian/blog/2876308

6. 数据到达 Leader 节点,成功复制到 Follower 所有或多数节点,数据在所有节点都处于已提交状态,但还未响应 Client

这个阶段 Leader 挂掉,Cluster 内部数据其实已经是一致的,Client 重复重试基于幂等策略对一致性无影响。

3 数据到达 Leader 节点,成功复制到 Follower 所有节点,但还未向 Leader 响应接收

这个阶段 Leader 挂掉,虽然数据在 Follower 节点处于未提交状态(Uncommitted)但保持一致,重新选出 Leader 后可完成数据提交,此时 Client 由于不知到底提交成功没有,可重试提交。

针对这种情况 Raft 要求 RPC 请求实现幂等性,也就是要实现内部去重机制。

1.RequestVote RPC 是appid记录,不是commitid记录。

2. 最终v3写入其他节点

3. 如果客户端请求 自己构造一个,然后同步。

一句话:leader不会自己撤销已经写入的log。

客户端看到失败,也不会撤销。

数据到达 Leader 节点,成功复制到 Follower 部分节点,但还未向 Leader 响应接收

这个阶段 Leader 挂掉,数据在 Follower 节点处于未提交状态(Uncommitted)且不一致,Raft 协议要求投票只能投给拥有最新数据的节点。所以拥有最新数据的节点会被选为 Leader 再强制同步数据到 Follower,数据不会丢失并最终一致。

(这里假设最新的被选举,也可能不是)

大家可以看到,在没有网络分区情况下,对客户端没有返回成功,

当前数据在内部:

无论follwer 部分成功写入,全部成功写入,全部确认成功情况下,全部确认成功。都能保证内部的一致性。【是否重复不保证】

客户端假如超时:在服务器内部 可能多个情况。有可能写入成功

有可能写入不成功。但是内部是数据一致的。

还剩下最重要一个情况,也是本章的问题

7. 网络分区导致的脑裂情况,出现双 Leader

网络分区将原先的 Leader 节点和 Follower 节点分隔开,Follower 收不到 Leader 的心跳将发起选举产生新的 Leader。

这时就产生了双 Leader,原先的 Leader 独自在一个区,向它提交数据不可能复制到多数节点所以永远提交不成功。

向新的 Leader 提交数据可以提交成功,网络恢复后旧的 Leader 发现集群中有更新任期(Term)的新 Leader 则自动降级为 Follower 并从新 Leader 处同步数据达成集群数据一致。

综上穷举分析了最小集群(3 节点)面临的所有情况,可以看出 Raft 协议都能很好的应对一致性问题,并且很容易理解。

打住 ,到这里还没有结束。

回到题目开始,假如是通过一个机房,上面2个节点分区了,其他都正常。

仔细观察 上面拓扑结构特点

这里有概念

星型拓扑图#

优点:

  1. 节点扩展,移动方便
  2. 网络传输速度快
  3. 维护容易

缺点:

  1. 核心交换机工作负荷重
  2. 网络布线复杂
  3. 广播传输影响性能
网状拓扑结构

主干网,广域网搭建

全网状拓扑图

容错能力强

成本高

怎么有点p2p的味道。

https://www.cnblogs.com/mindwind/p/5231986.html

更多问题:

https://www.zhihu.com/question/357207584

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Offer多多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是“脑裂”
    • “脑裂” 就是双master
      • Case 2: Leader 试图提交之前任期的日志
  • 观点1:1 集群奇数2 投票过半和3 任期大小
  • zk quorum(半数机制)机制解决脑裂,但是timeout造成正常情况下误判???如何解决
  • 超时机制:
  • 观点2: 对假死现象
  • 系统模型
  • 观察如下:下面2个情况写入大多数节点后无法保证安全:
    • 什么情况下是写入安全的
      • 6. 数据到达 Leader 节点,成功复制到 Follower 所有或多数节点,数据在所有节点都处于已提交状态,但还未响应 Client
      • 3 数据到达 Leader 节点,成功复制到 Follower 所有节点,但还未向 Leader 响应接收
      • 数据到达 Leader 节点,成功复制到 Follower 部分节点,但还未向 Leader 响应接收
      • 7. 网络分区导致的脑裂情况,出现双 Leader
      • 星型拓扑图#
      • 网状拓扑结构
      • 全网状拓扑图
  • 动手验证日志复制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档