Consul arch(三) 一致性协议 raft

本文详细介绍了Consul中使用的一致性协议Raft,包括其关键概念如Log、Peer set、Quorum和Term,以及一致性模式。重点阐述了Raft的节点角色(leader、follower、candidate)及其转换,以及Leader Election和Log Replication过程。同时讨论了不同一致性模式的优缺点,并解释了如何在Consul中实现Raft。
摘要由CSDN通过智能技术生成

Raft 是一种强一致性协议。注意是 consul 中 raft 指 servers 间的协议,与 client 无关。

当 consul server 收到 consul client 转发的请求或者同步过来的信息时,consul servers 内部需要保持一致,这就是 raft 的作用。


Raft 的几个关键概念:

Log - 行为序列(ordered sequence of entries)。Entry 包括所有的集群行为:添加节点、注册服务、写kv对等等。

Peer set - 参与 log replication 的所有成员,即所有 servers。

Quorum - 法定人数。对于 N 来说,quorum = (N / 2) + 1,即刚刚超过半数的 servers 数量。

即当 servers 只有 2 个时,quorum 也为 2,则当其中一个不可用时,整个系统则无法达到 quorum 数,将无法更新集群状态,同时,考虑同步性能,推荐 server 数为 3 或者 5 个。为什么不是不推荐 4 个?因为 4 个和 3 个一样,都只能容错一台节点错误。

在这里插入图片描述

Committed Entry - 达到 quorum 数的 server 收到了某个 entry,则称这个 entry 为 committed entry。

Term - 任期。每个 Term 都是一个连续递增的编号,每一轮选举都是一个 Term 周期,在一个 Term 中只能产生一个 leader。

Raft 的节点一共有三种角色:leader、follower、candidate。所有的 server 一开始都是 follower 。

正常情况下 follower 从 leader 处接收 entry,如果超过一定时间没有接收到 entry,则暗示着 leader 有可能出问题,则该 follower 自动成为 candidate。注意,当 follower 接收到 client 的 RPC 请求,follower 不进行处理,而是转发给 leader 进行处理。

在 candidate 状态下,可以请求其他的节点给自己投票。当票数达到 quorum 时,就转变为 leader 状态。

在 leader 状态下,需要处理 log。如果是读请求,则 leader 根据当前状态返回所需结果,如果是写请求,则生成一个新的 log 并且开始同步,直到 这个 log 被 committed(达到 quorum 数节点收到) 并且 applied(写入状态机)则写完成。


一致性模式

default - 只允许 leader 节点响应请求,但是当 leader 节点变更时,可能会出现两个 leader ,在这种情况下,老 leader 响应的可能是脏数据。

consistent - 强一致性但是最慢,leader 在响应读请求时,需要遍历其他节点确保自己是 leader。

stale - 允许非 leader 节点响应读请求。速度最快,但是值有可能是过期的(通常不会超过50ms过期)。


关键过程

raft 主要包括 Leader ElectionLog Replication 两个关键步骤。

Leader Election

心跳超时(heartbeat timeout) - follower 与 leader 进行通信的最大时间间隔。

选举超时(election timeout) - candidate 收到每张选票的最大时间间隔。

当 follower 心跳超时,会成为 candidate 进行选举开始选举。candidate 会向每个节点请求投票(request votes),若出现选举超时,则重新开始请求投票;若收到法定人数的计票则成为 leader。注意 candidate 会在开始请求投票之前给自己投一票,即只需(法定人数 - 1)张票即可。

注意当 candidate 和 leader 接收到新 term 的请求时,都会退化为 follower。

在这里插入图片描述

Log Replication

leader 需要向其他节点同步操作,即 log replication 过程,该过程通过 append entry 指令发出。当有法定数节点(包括 leader 自身)感知到状态更新后,即称为该 log 为 committed。

所以一个有 3 个和 4 个 servers 的 raft 集群,容错节点数都为 1 个节点。

一次完整 Log Replication 如下进行:

  1. client 请求 leader 更新状态;
  2. leader 向其他节点发出 append entry 指令;
  3. 其他节点相应指令并成功返回给 leader;
  4. 当 leader 发现 log 已 committed,即返回给 client;

在这里插入图片描述


实现

当 agent 运行在 server mode 下时会初始化 raft 实例:

https://github.com/hashicorp/raft

func NewRaft(conf *Config, fsm FSM, logs LogStore, stable StableStore, snaps SnapshotStore, trans Transport) (*Raft, error) {
   
    // ...
   
    // 初始化为 follower
    r.setState(Follower)

    // Start as leader if specified. This should only be used
    // for testing purposes.
    if conf.StartAsLeader {
   
        r.setState(Leader)
        r.setLeader(r.localAddr)
    }

    // ...

    // Start the background work.
    r.goFunc(r.run)
    r.goFunc(r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值