[etcd]Raft模块(一)(readme)

Raft是一种协议,节点群集可以使用该协议维护复制的状态机。通过使用复制的日志,状态机保持同步。有关Raft的更多详细信息,请参见Diego Ongaro和John Ousterhout撰写的“寻找可理解的共识算法”(https://raft.github.io/raft.pdf)。(这个论文在之前的博客翻译了一遍,基本上讲了raft的原理)

该Raft库稳定且功能齐全。截至2016年,它是**生产中使用最广泛的Raft库,每天服务数万个集群。它为etcd,Kubernetes,Docker Swarm,Cloud Foundry Diego,CockroachDB,TiDB,Project Calico,Flannel,Hyperledger等分布式系统提供支持。

大多数Raft实现都采用整体设计,包括存储处理,消息传递序列化和网络传输。相反,此库仅通过实现核心Raft算法来遵循简约的设计理念。这种极简主义具有灵活性,确定性和性能。为了使代码库更小并提供灵活性,该库仅实现Raft算法。网络和磁盘IO都留给用户。图书馆用户必须实现自己的传输层,以使信息在Raft对等点之间通过网络传递。同样,用户必须实现自己的存储层才能保留Raft日志和状态。(也就是在etcd中用到的raft模块只用到了基本算法选举,关于网络传输和存储都没用用到!

为了轻松测试Raft库,其行为应具有确定性。为了实现这种确定性,库将Raft建模为状态机。状态机将“消息”作为输入。消息可以是本地计时器更新,也可以是从远程对等方发送的网络消息。状态机的输出是一个三元组的{{] Messages,[] LogEntries,NextState}`,它由一系列Messages,log条目和Raft状态更改组成。对于状态相同的状态机,相同的状态机输入应始终生成相同的状态机输出。

该Raft实现是Raft协议的全功能实现。功能包括:

-领导者选举

-日志复制

-日志压缩

-成员资格更改

-领导者转移扩展

-领导者和关注者都可以进行有效的线性化只读查询

-领导者使用仲裁进行仲裁,并在处理只读查询之前绕过Raft日志

-关注者要求领导者在处理只读查询之前获得安全的读取索引

-领导者和关注者均可以更有效地使用基于租约的线性化只读查询

-领导者绕过Raft日志并在本地处理只读查询

-跟随者要求领导者获取一个安全的读索引,然后处理只读查询

-这种方法依赖于Raft组中所有计算机的时钟

该Raft实现还包括一些可选的增强功能:

-优化流水线以减少日志复制延迟

-日志复制的流控制

-批处理Raft消息以减少同步的网络I / O调用

-批处理日志条目以减少磁盘同步的I / O

-写入领导者磁盘并行

-从跟随者到领导者的内部建议重定向

-领导者失去仲裁时自动下台

-防止仲裁丢失时不受限制的日志增长

Raft中的主要对象是节点。

使用raft.StartNode从头开始启动Node或使用raft.RestartNode从某个初始状态启动Node。启动三节点集群

  storage := raft.NewMemoryStorage()
  c := &raft.Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }
  // Set peer list to the other nodes in the cluster.
  // Note that they need to be started separately as well.
  n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}})

启动一个单节点集群,如下所示:

  // Create storage and config as shown above.
  // Set peer list to itself, so this node can become the leader of this single-node cluster.
  peers := []raft.Peer{{ID: 0x01}}
  n := raft.StartNode(c, peers)

要允许新节点加入该群集,请勿传入任何对等节点。首先,通过在集群内部任何现有节点上调用ProposeConfChange将节点添加到现有集群中。然后,以一个空的对等列表启动该节点,如下所示:

  // Create storage and config as shown above.
  n := raft.StartNode(c, nil)

要从先前的状态重启节点:

storage := raft.NewMemoryStorage()

  // Recover the in-memory storage from persistent snapshot, state and entries.
  storage.ApplySnapshot(snapshot)
  storage.SetHardState(state)
  storage.Append(entries)

  c := &raft.Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }

  // Restart raft without peer information.
  // Peer information is already included in the storage.
  n := raft.RestartNode(c)

创建节点后,用户将承担以下责任:首先,从Node.Ready()通道读取并处理其包含的更新。这些步骤可以并行执行,除非步骤2中另有说明。1.将条目,HardState和快照按顺序写入持久性存储,即先写入条目,如果不为空,则写入HardState和快照。如果持久性存储支持原子写入,则可以将所有原子写入在一起。请注意,在编写索引为i的条目时,必须丢弃索引> = i的所有先前存在的条目。 2.将所有消息发送到“收件人”字段中命名的节点。重要的是,在将最新的HardState持久化到磁盘上之前,以及任何先前的Ready批处理写入的所有条目之前,不要发送任何消息(可以在持久化同一批处理的条目时发送消息)。为了减少I / O延迟,可以应用优化以使引导者与其跟随者并行地写入磁盘(如Raft论文中的10.2.1节所述)。如果任何消息的类型为MsgSnap,请在发送消息后调用Node.ReportSnapshot()(这些消息可能很大)。注意:编组消息不是线程安全的。重要的是要确保在编组时不保留任何新条目。实现此目的最简单的方法是直接在主Raft循环内序列化消息。 3.将快照(如果有)和CommittedEntries应用于状态机。如果任何已提交的Entry的类型为EntryConfChange,则调用Node.ApplyConfChange()将其应用于节点。此时可以通过在调用ApplyConfChange之前将NodeID字段设置为零来取消配置更改(但是ApplyConfChange必须以一种或另一种方式调用,并且取消决定必须仅基于状态机而不是外部信息,例如观察到的节点运行状况)。 4.调用Node.Advance()表示已准备好进行下一批更新。尽管必须按照Ready返回的顺序处理所有更新,但是可以在步骤1之后的任何时间完成此操作。其次,必须通过存储接口的实现使所有持久日志条目可用。可以使用提供的MemoryStorage类型(如果在重新启动时重新填充其状态),或者可以提供自定义的磁盘支持的实现。第三,从另一个节点收到消息后,将其传递给Node。

	func recvRaftRPC(ctx context.Context, m raftpb.Message) {
		n.Step(ctx, m)
	}

最后,以固定的时间间隔(可能通过“ time.Ticker”)调用“ Node.Tick()”。Raft有两个重要的超时:心跳和选举超时。但是,在Raft包装内部,时间用抽象的“滴答声”表示。总的状态机处理循环如下所示:

  for {
    select {
    case <-s.Ticker:
      n.Tick()
    case rd := <-s.Node.Ready():
      saveToStorage(rd.HardState, rd.Entries, rd.Snapshot)
      send(rd.Messages)
      if !raft.IsEmptySnap(rd.Snapshot) {
        processSnapshot(rd.Snapshot)
      }
      for _, entry := range rd.CommittedEntries {
        process(entry)
        if entry.Type == raftpb.EntryConfChange {
          var cc raftpb.ConfChange
          cc.Unmarshal(entry.Data)
          s.Node.ApplyConfChange(cc)
        }
      }
      s.Node.Advance()
    case <-s.done:
      return
    }
  }

提议从节点更改状态机以获取应用程序数据,将其序列化为字节片并调用:n.Propose(ctx, data)

如果提案已提交,则数据将以raftpb.EntryNormal类型出现在已提交的条目中。无法保证会执行建议的命令;该命令可能必须在超时后重新提出。要添加或删除集群中的节点,请构建ConfChange结构'cc'并调用:n.ProposeConfChange(ctx, cc)

提交配置更改后,将返回一些类型为raftpb.EntryConfChange的已提交条目。这必须通过以下方式应用于节点:

var cc raftpb.ConfChange

  cc.Unmarshal(data)

  n.ApplyConfChange(cc)

尽管成员资格更改协议的这种实现与第4章中描述的有所不同,但该实现与最新的Raft论文(https://github.com/ongardie/dissertation/blob/master/stanford.pdf)是最新的。保留成员资格更改一次发生在一个节点上的关键不变性,但是在我们的实现中,成员资格更改在应用其条目时才生效,而不是在将其添加到日志时生效(因此该条目是在旧成员资格下而不是在新成员资格下提交的)新的)。就安全性而言,这是等效的,因为保证了新旧配置的重叠。为了确保没有尝试通过匹配日志位置来一次提交两个成员资格更改(这是不安全的,因为它们应该具有不同的法定要求,这是不安全的),任何提议的成员资格更改都将被禁止,而任何未提交的更改都将显示在领导者的日志中。当从两个成员的集群中删除一个成员时,这种方法会带来一个问题:如果一个成员在另一个成员之前收到了confchange条目的提交而死亡,则该成员将无法再删除,因为该集群无法取得进展。因此,强烈建议在每个群集中使用三个或更多节点。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在VMware虚拟机安装Ubuntu 18.04,可以按照以下步骤进行操作: 1. 首先,从官方网站上下载并安装VMware软件。在安装过程,请按照向导的提示进行操作,并确保VMware软件成功安装。 2. 下载Ubuntu 18.04的镜像文件。你可以从Ubuntu官方网站上下载镜像文件,并确保选择与你的计算机系统兼容的版本。 3. 在VMware创建一个新的虚拟机,并将Ubuntu 18.04的镜像文件加载到虚拟机。在创建虚拟机的过程,你需要为虚拟机分配足够的内存、硬盘空间和其他必要的设置。 4. 安装Ubuntu 18.04操作系统。在虚拟机启动Ubuntu 18.04,并按照向导的提示进行安装。在安装过程,你需要选择安装语言、时区、键盘布局等相关设置。 5. 设置Ubuntu系统。一旦安装完成,你可以根据需要进行一些系统设置,例如调整分辨率[2.3.1]、安装VMware Tools[2.3.2]等。 总结起来,安装VMware虚拟机Ubuntu 18.04的步骤包括:下载并安装VMware软件、下载Ubuntu 18.04镜像文件、在VMware创建虚拟机并加载镜像文件、安装Ubuntu 18.04操作系统,最后进行必要的系统设置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [VMware虚拟机安装Ubuntu18.04(linux发行版)【超详细图文教程】](https://blog.csdn.net/weixin_43290551/article/details/125954709)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [VMware15虚拟机安装Ubuntu18.04的图文教程](https://download.csdn.net/download/weixin_38657835/14048613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值