04 | Raft协议:etcd如何实现高可用、数据强一致的?
该思维导图由 AI 生成,仅供参考
如何避免单点故障
- 深入了解
- 翻译
- 解释
- 总结
etcd基于Raft协议实现高可用、数据强一致性。文章深入分析了etcd在Leader节点异常时,Follower节点如何快速感知异常并高效选举新Leader,保障高可用服务。通过日志复制流程图介绍了etcd如何保障数据一致性,以及Raft算法增加的安全规则。文章还介绍了Raft算法的诞生背景和共识算法的重要性,以及解决Leader选举、日志复制和安全性等问题。在Raft协议中,etcd定义了节点状态,包括Follower、Candidate和Leader。通过心跳机制维持Leader身份、触发Leader选举,etcd基于Raft协议实现了高可用。文章还详细介绍了日志复制原理和安全性规则,以及Raft算法如何保证数据一致性。通过本文,读者可以了解etcd在异常场景下如何基于Raft算法实现高可用、数据强一致。 Raft算法通过Leader选举限制、Leader完全特性、只附加原则、日志匹配等安全特性,实现了一个可严格通过数学反证法、归纳法证明的高可用、一致性算法,为etcd的安全性保驾护航。文章还介绍了etcd的读写性能优化历史,从线性读请求到全并发读的演进过程,以及expensive request对etcd性能的影响和相应的优化措施。总的来说,本文详细介绍了etcd基于Raft算法实现高可用、数据强一致的原理和安全机制,以及etcd的读写性能优化历史,对于想深入了解分布式系统和共识算法的读者具有很高的参考价值。
《etcd 实战课》,新⼈⾸单¥59
全部留言(50)
- 最新
- 精选
- blentle老师,如果一个日志完整度相对较高的节点因为自己随机时间比其他节点的长,没能最先发起竞选,其他节点当上leader后同步自己的日志岂不是冲突了?
作者回复: 你所说的这个日志完整度相对较高的节点,投票时有竞选规则安全限制,如果它的节点比较新会拒绝投票,至于最终先发起选举的节点能否赢得选举,要看其他节点数据情况,如果多数节点的数据比它新,那么先发起选举的节点就无法获得多数选票,如果5个节点中,只有一个节点数据比较长,那的确会被覆盖,但是这是安全的,说明这个数据并未被集群节点多数确认
2021-01-2732 - mckee思考题: 1.哪些场景会出现 Follower 日志与 Leader 冲突? leader崩溃的情况下可能(如老的leader可能还没有完全复制所有的日志条目),如果leader和follower出现持续崩溃会加剧这个现象。follower可能会丢失一些在新的leader中有的日志条目,他也可能拥有一些leader没有的日志条目,或者两者都发生。 2.follower如何删除无效日志? leader处理不一致是通过强制follower直接复制自己的日志来解决了。因此在follower中的冲突的日志条目会被leader的日志覆盖。leader会记录follower的日志复制进度nextIndex,如果follower在追加日志时一致性检查失败,就会拒绝请求,此时leader就会减小 nextIndex 值并进行重试,最终在某个位置让follower跟leader一致。
作者回复: 怒赞,优秀,还需要补充下为什么WAL模块只能通过追加日志,那它是如何删除已持久化的废弃日志条目呢?
2021-01-3129 - jeffery讲的太好了、图文并貌、形象生动、raft这章就够本了!老师问下.es 也用raft!为啥会出现数据不一致性?部署etcd高可用有运维有最佳实践建议吗?谢谢老师
作者回复: 感谢你的认可,有收获就好,数据不一致原因和高可用运维最佳实践,实践篇都有,稍等,一起学下去,加油,保证让你收获满满
2021-01-28212 - 写点啥呢谢谢老师的回答,关于第三个问题,“3. 如果在写数据过程中leader崩溃了。比如在leader完成自身WAL并发送MsgApp后崩溃了,本次写提案没有完成,重新选leader之后新leader有这次写记录的log,它会怎么恢复数据?” 我详细描述下,请老师帮忙解答下: 1. Leader收到用户put请求后,完成自己的WAL日志及raft日志持久化后发送MsgApp到其它follower节点。 2. 其它follower节点接收到MsgApp后也完成自己的WAL及raft日志操作。 3. 此时Leader节点崩溃了,follower节点无法发送自己日志MsgAppResp给已经崩溃的Leader。此时集群开始新一轮选举并选出一个Leader 4. 新的Leader接收过之前的put提案并在日志中找到它,新的Leader如何恢复这条提案到提交状态?新的leader是不是在日志中看到这条没有完成提案后重新在做一轮提案? 谢谢老师
作者回复: 首先在raft中并没有什么数据结构来保存提案状态,leader只维护了一个committed index, 它表示这个index之前的日志条目已被成功同步到了大多数follower节点。当原leader crash后,其他follower节点选举出新leader, 按照raft安全性原则,它是不能删除前任leader的任何日志条目,因leader crash前这条日志条目已经被持久化到了多数follower节点上,那么follower节点选举出新leader后,它含有这条日志条目,并且多数节点已经同步了,那么对新leader而言,它的状态就是已提交,可以直接提交给状态机模块执行。对client而言,虽然写请求超时了,但最终它的提案是成功执行的,client需要自己确保幂等性,也就是写超时后,你的提交可能是成功的。
2021-01-29611 - 写点啥呢关于选举过程和节点崩溃后恢复有几个问题请教老师: 1. 如果多数follower崩溃后重启恢复(比如极端情况只剩下Leader其它follower同时重启),根据选举规则是不是会出现重启follower占多数投票给了一个数据不是最新的节点而导致数据丢失。我理解这种情况不满足法定票算法前提,所以是无法保障数据一致的。 2. 对于少数节点崩溃恢复后,它是如何追上leader的最新数据的呢?比如对于日志复制过程,leader完成自身的WAL及raft日志然后发送MsgApp,但是其它follower没有来得及发送MsgResp就崩溃了,那么这条raft日志其实没有得到法定票数的提交信息,raft模块应该通过什么方式来让follower恢复这份数据,让它能够最终在恢复的节点得到法定票数提交,然后应用到上层状态机? 3. 如果在写数据过程中leader崩溃了。比如在leader完成自身WAL并发送MsgApp后崩溃了,本次写提案没有完成,重新选leader之后新leader有这次写记录的log,它会怎么恢复数据? 谢谢老师
作者回复: 好问题,第一个问题不能说是数据丢失,正如你所说的,可能存在一个新日志条目,这些异常重启后的follower中没有,因为异常的follower数达到了法定数,那么这个新日志条目肯定没同步到多数节点上,因此是合理的。 第二个问题,看落后数据程度,通过内存中的raft log和快照文件追赶,因篇幅关系,未介绍日志压缩和快照,后面我根据情况是否单独加餐篇。如果提交过程中,不能达到法定数,这时会超时,依赖客户端重试 第三个问题,描述可以更详细点吗,没太懂,按我初步理解回答下,其他节点收到此日志条目后会持久化,选出leader也有此条记录,新老leader如果数据有冲突,以新leader为准
2021-01-279 - Index关于etcd的raft实现源码有个问题 func ExampleNode() { c := &Config{} n := StartNode(c, nil) defer n.Stop() // stuff to n happens in other goroutines // the last known state var prev pb.HardState for { // Ready blocks until there is new state ready. rd := <-n.Ready() if !isHardStateEqual(prev, rd.HardState) { saveStateToDisk(rd.HardState) prev = rd.HardState } saveToDisk(rd.Entries) go applyToStore(rd.CommittedEntries) sendMessages(rd.Messages) } } 网络,存储都是用户自己实现的,如果这里在处理存储和发送消息很慢,这样不会影响到心跳吗?比如心跳默认是1s,那如果处理存储和网络的时间经常超过1s,岂不是心跳就时常超时,集群经常处于选举的状态吗?求解答
作者回复: 嗯,etcd特别依赖磁盘I/O性能,日志条目需要同步持久化到磁盘,当心跳间隔是100ms,选举超时是1s, 如果fsync 日志条目WAL耗时不稳定、波动很大、超过1秒,那集群就会频繁选举。
2021-01-2924 - 青鸟飞鱼主从复制缺点是因为主节点崩溃后,没有选主机制(是否可以考虑redis的哨兵选主)呢?还是因为数据一致性呢(raft保持强一致性的话,也是通过某些机制保证强一致性(主节点读或者ReadIndex))
作者回复: 嗯,主从复制我个人认为最大的缺点还是数据一致性,Raft的保证一致性背后的核心数学原理其实是抽屉原理,你可以详细了解下,不管是集群选举还是数据复制,都要求一半以上节点确认
2021-01-2754 - Geek_aaa517raft日志跟wal日志没太搞明白,分别是什么作用呢
作者回复: WAL日志是用来持久化raft日志条目和相关集群元数据信息的,可防止节点发生重启、crash后,对应的已提交日志条目丢失等异常情况,一般情况下,它是将数据持久化到磁盘中。 Raft日志记录了节点过去一段时间内收到的写请求,如put/del/txn操作等,一般是通过一个内存数组来存储最近一系列日志条目。当Follower节点落后Leader较小时,就可以通过Leader内存中维护的日志条目信息, 将落后的日志条目发送给它,最终各个节点应用一样的日志条目内容,来确保各个节点数据一致性。 etcd节点重启后,可通过WAL日志来重建部分raft日志条目。
2021-03-2023 - 春风假如老的 Leader A 因为网络问题无法连通 B、C 节点,这时候根据状态图,我们知道它将不停自增任期号,发起选举。等 A 节点网络异常恢复后,那么现有 Leader 收到了新的任期号,就会触发新一轮 Leader 选举,影响服务的可用性。 老师,这里没太懂,A不是本身是leader吗,为什么还要发起选举?
作者回复: 感谢反馈,是我描述不严谨,让你误会了,在上文中老的Leader A crash后,重启会变成Follower节点,已完善描述,谢谢你
2021-01-273 - HelloBug老师在讲解流程的时候,会说raft模块,kvserver模块,这些都好理解。但又会说etcd发送什么消息,或者etcdserver怎么怎么样,具体是什么模块呢?我之前以为这两者不指哪个模块,就是etcd的框架代码,但是这篇文章里又看到etcdserver模块,着实不知道怎么理解了
作者回复: 嗯,有些术语的确可以更友好点,推荐先简单看看etcd源码(3.3/3.4版本),跟着02和03大致走读下,这样你会更加清晰
2021-12-0221