[etcd]raft总结/选举/数据同步,协议缺陷与解决/Multi Raft

2024-08-24 05:18

本文主要是介绍[etcd]raft总结/选举/数据同步,协议缺陷与解决/Multi Raft,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

raft协议是multi paxos协议的实现.Etcd、Consu都使用了raft

1.角色

raft协议中包含这几种角色

领导者:带头大哥1.提出提议,但是不需要确认,因为我是大哥;2.复制日志,数据以大哥为准,3,领导者会定时发送心跳,确定自己的位置.告诉小弟老实呆着,一旦心跳超时,小弟就会重新选举大哥.

跟随者:只要大哥发送心跳,我就老实的同步日志.一旦没有心跳,我就变成候选人,开始发起投票,争取做大哥

候选人:心跳超时后,变成候选人,这是个中间状态.

2.选举

2.1选举时机:

1.心跳超时后,变成候选人,开始进行选举.为了避免节点全都一起选举,不同节点会有随机心跳超时时间.

2.例如机器刚启动时,大家都是follower,心跳超时后,就开始选举

3.优化.为了避免瓜分选票,心跳超时时间随机,当选举超时后,会进入第二轮选举,这个间隔时间也是随机的

2.2 选举原则:

1.每个节点,对每个任期(trem)只能投出一张票.与zab不同,zab是不断修改自己的选票,然后每个节点都有个投票箱,自己计算

2.收到选举请求后,如果该请求的事务日志编号小于自己的机器,那么就不会投票. 要当leader的机器,最起码掌握的东西得比我多吧(log)

3.收到选举请求后,如果该选举编号(term)小于自己的term,那么就不会投票. 我们都在老xi时代了,你还在选举第二任?

4.当一台机器收到多数投票,代表选举成功.

 

注意一个点.当集群中一个节点出现网络分区.那么他会去选举,增加自己的term.但是还是会超时,因此一直去增加term,发起更多轮的选举.一旦.这个节点网络恢复.那么其他节点就会收到选举请求,发下term大于自己,那么会触发重新选举. 由于事务id小,当然不会成为leader,但是还是影响了集群.

因此.有一个preVote阶段,

在PreVote算法中,Candidate首先要确认自己能赢得集群中大多数节点的投票,这样才会把自己的term增加,然后发起真正的投票。其他投票节点同意发起选举的条件是(同时满足下面两个条件):

  • 没有收到有效领导的心跳,至少有一次选举超时。
  • Candidate的日志足够新(Term更大,或者Term相同raft index更大)。

 

 

2.3 rpc消息:

raft中有两个rpc:

1.选举rpc:是由候选人在选举期间发起,通知各节点进行投票

2.日志复制rpc:是由领导者发起,用来复制日志和提供心跳消息.

 

2.4 term

1.如果一个机器收到,任期编号大的机器发来的心跳,那么他就应该知道自己已经out了.要赶紧同步数据.化为follower.

2.当节点收到任期编号比我小的怎么办?丢弃.

 

2.5 总结:

与multiPaxos相比

1.通过日志编号确定数据是否最新,因此要求数据是连续的

当确认leader之后,leader会同步数据给follower.

3.日志复制:

流程

正常情况:

  1. client向leader发出一个添加请求
  2. leader写入appendEntryLog.并标记为uncommit状态.
  3. 调用appendEntryRpc,拷贝日志项到follower.
  4. follower接收到日志项,并append到本机.返回给leader success
  5. leader收到success后,将日志置为committed状态.并apply到状态机.返回给client success.

异常流程:

当拷贝到follower,follower没有响应成功时,有可能是没有拷贝过去,也有可能ack丢失了.  leader会不断重试,直到满足过半.  当然这时候,client可能会超时.这条日志可能最后会丢失,也可能会committed,客户端需要实现幂等

 

先说问题:

1.leader把数据复制到follower,follower大部分返回成功后,leader会apply此条数据到状态机.并返回给client成功的响应.

注意这里:状态机是对于上层来说的,比如你写成功后,再来读取数据,就是从状态机的数据中读,如果你返回给用户成功,但是状态机数据还是旧的,那么就不对了.

那我能不能在leader复制后,就update状态机呢?

不能,如果直接update,返回成功给用户,但是此时leader挂了.咋整.所以需要等大部分都提交,才返回成功.因为大部分提交后,即使此时leader挂了.重新选举时,根据raft协议.只有提议id大的才可以当leader,

就可以保证,之后当选的leader会有这条数据.因此这里也可以知道.选举时比较的日志id,是复制的日志id,而不是commitedId.

2.raft将两阶段提交,优化为1阶段提交. 

当一条请求发送给leader时,leader会写一条日志(uncommit),之后复制给follower(uncommit),当过半后,leader会变为committed,那么follower啥时候变为committed,并apply到状态机呢???

如果不是实时的,岂不是在读取的时候,读不出来??

a:通过AppendEntriesRPC同步数据,细节前面已经说了.此时就会把数据应用到状态机.大概逻辑就是:心跳/同步数据 rpc,会携带最新日志id,如果少的话,那么需要进行同步.appendEntryRpc互携带最新日志以及前一条日志(preEntryTerm,preEntryLogId),就可以回溯到 到底从哪条日志不一样了,然后再同步给follower.

b:注意:一致性是说 对于client,发出的读请求,可以获取到集群最新的数据,而不是说,集群每个节点数据都是一致的!!.这个是很容易错误理解的!! 例如etcd,早期是通过读写都走leader节点来保证一致性.3.2版本后,通过readIndex来保证.readIndex是什么,可以参考etcd源码分析系列;

所以一般来讲, leader append log(uncommit)--->copy to followers-->leader apply log &commit the log--->下次心跳,同步数据

4.raft算法的缺陷

我们可以在网上看到很多比较 Paxos 和 Raft 的文章,它们都会提到在复制效率上 Raft 会差一些,主要原因就是 Raft 必须“顺序投票”,不允许日志中出现空洞。

  1. Leader 收到客户端的请求。
  2. Leader 将请求内容(即 Log Entry)追加(Append)到本地的 Log。
  3. Leader 将 Log Entry 发送给其他的 Follower。
  4. Leader 等待 Follower 的结果,如果大多数节点提交了这个 Log,那么这个 Log Entry 就是 Committed Entry,Leader 就可以将它应用(Apply)到本地的状态机。
  5. Leader 返回客户端提交成功。
  6. Leader 继续处理下一次请求。

以上是单个事务的运行情况。那么,当多事务并行操作时,又是什么样子的呢?我画了张图来演示这个过程。我们设定这个 Raft 组由 5 个节点组成,T1 到 T5 是先后发生的 5 个事务操作,被发送到这个 Raft 组。

事务 T1 的操作是将 X 置为 1,5 个节点都 Append 成功,Leader 节点 Apply 到本地状态机,并返回客户端提交成功。

事务 T2 执行时,虽然有一个 Follower 没有响应,但仍然得到了大多数节点的成功响应,所以也返回客户端提交成功。

现在,轮到 T3 事务执行,没有得到超过半数的响应,这时 Leader 必须等待一个明确的失败信号,比如通讯超时,才能结束这次操作。因为有顺序投票的规则,T3 会阻塞后续事务的进行。

T4 事务被阻塞是合理的,因为它和 T3 操作的是同一个数据项,但是 T5 要操作的数据项与 T3 无关,也被阻塞,显然这不是最优的并发控制策略。

同样的情况也会发生在 Follower 节点上,第一个 Follower 节点可能由于网络原因没有收到 T2 事务的日志,即使它先收到 T3 的日志,也不会执行 Append 操作,因为这样会使日志出现空洞。

Raft 的顺序投票是一种设计上的权衡,虽然性能有些影响,但是节点间日志比对会非常简单。在两个节点上,只要找到一条日志是一致的,那么在这条日志之前的所有日志就都是一致的。这使得选举出的 Leader 与 Follower 同步数据非常便捷,开放 Follower 读操作也更加容易。要知道,我说的可是保证一致性的 Follower 读操作,它可以有效分流读操作的访问压力。

性能优化方法

缺点:顺序投票,只能串行apply,因此高并发场景下性能差。

TiDB:

1.批操作(Batch)。Leader 缓存多个客户端请求,然后将这一批日志批量发送给 Follower。Batch 的好处是减少的通讯成本。牺牲了写操作的耗时

2.流水线(Pipeline)。Leader 本地增加一个变量(称为 NextIndex),每次发送一个 Batch 后,更新 NextIndex 记录下一个 Batch 的位置,然后不等待 Follower 返回,马上发送下一个 Batch。如果网络出现问题,Leader 重新调整 NextIndex,再次发送 Batch。当然,这个优化策略的前提是网络基本稳定。

3.并行追加日志(Append Log Parallelly)。Leader 将 Batch 发送给 Follower 的同时,并发执行本地的 Append 操作。因为 Append 是磁盘操作,开销相对较大,而标准流程中 Follower 与 Leader 的 Append 是先后执行的,当然耗时更长。改为并行就可以减少部分开销。当然,这时 Committed Entry 的判断规则也要调整。在并行操作下,即使 Leader 没有 Append 成功,只要有半数以上的 Follower 节点 Append 成功,那就依然可以视为一个 Committed Entry,Entry 可以被 Apply。

4.异步应用日志(Asynchronous Apply)。Apply 并不是提交成功的必要条件,任何处于 Committed 状态的 Log Entry 都确保是不会丢失的。Apply 仅仅是为了保证状态能够在下次被正确地读取到,但多数情况下,提交的数据不会马上就被读取。因此,Apply 是可以转为异步执行的,同时读操作配合改造. 这里是牺牲了读取的一致性了

其实,Raft 算法的这四项优化并不是 TiDB 独有的,CockroachDB 和一些 Raft 库也做了类似的优化。比如,SOFA-JRaft 也实现了 Batch 和 Pipeline 优化。

     

参考:

https://zhuanlan.zhihu.com/p/27207160

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

https://time.geekbang.org/column/article/277028

http://blog.sina.com.cn/s/blog_3fc85e260102wr0c.html

 

 

 

 

 

 

 

 

这篇关于[etcd]raft总结/选举/数据同步,协议缺陷与解决/Multi Raft的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101557

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi