最近在看raft相关的代码和实现,发现etcd的raft模块在实现上还是比较灵活的,但缺点就是需要用户实现比较多的功能,如存储和网络等,同时带来的优点就是不会对用户的存储和传输作限制.网上对该模块的描述也比较多,这里我主要根据代码画出简易的处理逻辑,代码逻辑可以参考这里(后续流程图也会按照这个系列的讲解顺序来). 该例子给出了etcd raft处理的总体架构图,但并不涉及raft处理的细节,绿底部分为raft节点的server,右下侧为需要用户实现的存储和传输层.右上侧为对外的Http serv…
存储和节点的创建 raftexample中的存储其实有两种,一个是通过raft.NewMemoryStorage()进行创建的raft.raftStorage,关联到单个raft节点,另一个是通过newKVStore创建的kv存储,用于服务来自外部的访问. 节点启动时raft.raftStorage的加载 上一篇中主要围绕replayWAL介绍wal的读写,到本文为止可以完整拼接出该函数的处理逻辑.其中snapshot的作用是通过index限定了加载的wal日志的范围. 一开始会通过loadSn…
本文仅介绍wal的基本处理,如create.open.close.read等操作.鉴于篇幅原因,下面介绍replayWAL(启动raft节点时执行)函数涉及的读文件操作:从wal目录中加载snapshot,wal文件的创建,以及读取wal目录中的所有数据(主要是entryType.stateType.metadataType这几类). WAL的处理还是比较复杂的可以借鉴的地方也很多.WAL在编码以及flush时使用缓存来提升效率.flush的单位为分页,每页又分为8个section,sectio…
本章给出了raftexample中使用的传输层代码,补全了上一节中传输层与raft节点(raft server和channel server)的交互细节.下图中流程的核心在于传输层中的streamRt和pipelineRt,raft的传输层通过这两个roundtrip与其他节点交互,并通过streamReader读取来自其他节点的信息进行处理.streamHandler用于给msgAppV2Writer和writer提供连接,处理完之后返回给handler(raft example中好像没有涉及…
早在2013年11月份,在raft论文还只能在网上下载到草稿版时,我曾经写过一篇blog对其进行简要分析.4年过去了,各种raft协议的讲解铺天盖地,raft也确实得到了广泛的应用.其中最知名的应用莫过于etcd.etcd将raft协议本身实现为一个library,位于https://github.com/coreos/etcd/tree/master/raft,然后本身作为一个应用使用它. 本文不讲解raft协议核心内容,而是站在一个etcd raft library使用者的角度,讲解要用上这…
etcd raft选举机制 etcd 是一个分布式的k/V存储系统.核心使用了RAFT分布式一致性协议.一致性这个概念,它是指多个服务器在状态达成一致,但是在一个分布式系统中,因为各种意外可能,有的服务器可能会崩溃或变得不可靠,它就不能和其他服务器达成一致状态.这样就需要一种Consensus协议,一致性协议是为了确保容错性,也就是即使系统中有一两个服务器当机,也不会影响其处理过程. 为了以容错方式达成一致,我们不可能要求所有服务器100%都达成一致状态,只要超过半数的大多数服务器达成一致就可以…
成员变更在一致性协议里稍复杂一些,由于不同的成员不可能在同一时刻从旧成员组切换至新成员组,所以可能出现两个不相交的majority,从而导致同一个term出现两个leader,进而导致同一个index的日志不一致,违反一致性协议.下图是个例子: raft作者提出了一种比较简单的方法,一次只增加或减少一个成员,这样能够保证任何时刻,都不可能出现两个不相交的majority,所以,可以从旧成员组直接切到新成员组.如下图: 切换的时机是把成员变更日志写盘的时候,不管是否commit.这个切换时机带来的…
https://github.com/coreos/etcd/tree/master/raft import "github.com/coreos/etcd/raft" --------------------------------------------------------------------------- raft是一个协议,一个节点集群可以维护一个复制状态机.状态机通过使用复制日志保持同步.有关Raft的更多详细信息,请参阅Diego Ongaro和John Ouste…
leadership transfer可以把raft group中的leader身份转给其中一个follower.这个功能可以用来做负载均衡,比如可以把leader放在性能更好的机器或者离客户端更近的机器上. 对于一个大规模分布式系统来说,负载均衡非常重要.然而raft本身在选主方面必须要求新主包含所有的意境committed的log,从这点上看,在选主阶段,不能加入自定义的选主逻辑.而paxos协议不太一样,paxos对选主没有要求,任何一个成员都可以成为主,选主协议可以自己实现.paxos…
Linearizable Read通俗来讲,就是读请求需要读到最新的已经commit的数据,不会读到老数据. 对于使用raft协议来保证多副本强一致的系统中,读写请求都可以通过走一次raft协议来满足.然后,现实系统中,读请求通常会占很大比重,如果每次读请求都要走一次raft落盘,性能可想而知.所以优化读性能至关重要. 从raft协议可知,leader拥有最新的状态,如果读请求都走leader,那么leader可以直接返回结果给客户端.然而,在出现网络分区和时钟快慢相差比较大的情况下,这有可能会…