学习raft协议(1)

CAP

C: 一致性
强调数据的正确性,每次读操作,要么读到最新,要么读失败
A:可用性
不发生错误,也不能出现过长的等待时间.
P:分区容错性
在网络环境不可靠的背景下,整个系统仍然是正常运作的

两种流派

(1)CP:强调系统数据的正确性,但由于建立保证不同节点间保证数据严格一致的机制,可能会牺牲系统的可用性.
(2)AP:强调系统的可用性,那就必须在数据一致性上做出妥协退让.

常见c的问题

1.4 C 的问题
(1)即时一致性问题:
  服务端采用了异步完成数据同步任务的机制,那么客户端的读请求就可能在 follower 同步到 set x = 3 这一项任务之前就打到 follower,此时会取到 x 的老数据或者 x 不存在的响应。
(2)顺序一致性问题
  因为网络延迟,数据同步指令的先后顺序造成了不一致

为了解决上面c的问题

可能利用一些ACK机制,包装统一收到从节点的响应才将数据同步,变成了串行化的机制,一个从节点的延迟或者无服务可能会影响整个系统的服务

分布式一致性共识算法

分布式一致性共识算法指的是在分布式系统中,使得所有节点对同一份数据的认知能够达成共识的算法.

多数派原则

多数派,指的是一个群体的数量达到总数的一半以上.

多数派原则指的是,系统的决断无需全员参与,多数派达成的共识即可视为整个系统的答复.

以集群存在 5 个节点为例,多数派则需要集齐 3 个及 3 个以上节点,至多可以允许 2 个节点存在开小差背离主流的情况. 同理,倘若集群 6 个节点,则多数派需要集齐 4 个及 4 个以上节点,因此同样至多允许 2 个节点开小差. 综上,这是奉行多数派原则的集群通常将节点个数设置为奇数的原因之一.

多数派原则是提高分布式系统可用性 A 的关键

一主多从

raft 算法下系统中的节点分为领导者 leader 和跟随者 follower 两类角色.

读写分离

读操作可以由集群的任意节点提供服务;

写操作统一需要由 leader 收口处理,并向 follower 同步. 倘若 follower 率先收到了来自客户端的写请求,也需要转发给 leader 进行处理.

如果是原始的raft论文《In Search of an Understandable Consensus Algorithm (Extended Version)》,读写请求都是发送给leader。

状态机与预写日志

状态机 (state machine)是节点实际存储数据的容器,写请求的最后一步是将结果写入状态机,而读请求也需要从状态机中获取数据进行响应.

预写日志( wal) 在 raft 算法中,写请求会先组织成预写日志的形式添加到日志数组中,当一个日志(写请求)达到集群多数派的认可后,才能够被提交,将变更应用到状态机当中.

预写日志由一个数组承载,为一段时间内的多笔写请求提供了一个缓存区;同时,每笔预写日志是一笔写请求的抽象,通过其记录的明细,使得我们可以对写请求的内容进行比较. 这样的机制之下,我们只要保证预写日志数组中,被准许应用到状态机的部分每笔预写日志的内容都完全相同,这样就能解决写请求乱序的问题,从而达成数据的最终一致性.

两阶段提交

从单机层面,一笔写请求会分为添加到预写日志和应用到状态机两个步骤,这是对两阶段提交的一种体现;

在整个系统层面
(1)leader 接收到来自客户端的一笔写请求;

(2)leader 将写请求添加到本地的预写日志中,并向集群中其他节点广播同步这笔写请求. 这个过程可以称之为“提议”(proposal);

(3)集群中各节点接收到同步请求后,会一套检验机制判断是否能执行同步(添加到预写日志),校验机制这里不细述,留待 4.1 小节细说;

(4)倘若集群总计半数以上的节点(包括 leader 自身)都将这笔请求添加预写日志,并给予了 leader 肯定的答复(ack),那么 leader 此时会“提交”这个请求,并给予客户端写请求已成功处理的响应;

(5)其他节点在随后的时段中,会通过与 leader 的交互(心跳或其他同步数据的请求)感知到这个“提交”动作,最终也在预写日志中提交这笔请求;

(6)被提交的预写日志具备了被应用到状态机的资格. 但应用的时机取决于实现方式,倘若只追求最终一致性,可以选择异步应用;倘若追求立即一致性,则会要求 leader 先应用到状态机,才能给予客户端 ack.


领导者选举

leader的存活
(1)leader 需要定期向 follower 发送心跳,证明存活. 与之对应的,follower 会建立一个心跳检测定时器,当超过指定时长未收到 leader 的心跳,则认为 leader 已死,会切换成候选人(candidate)发起竞选,尝试补位成为新的 leader.
(2)follower 成为 candidate 后,会广播向所有节点拉票,当投赞同票的节点数(包括candidate 本身)达到多数派的时候,该 candidate 会胜任,成为新的 leader.

任期与日志索引

   二元组
(1)term:标志了这则日志是哪个任期的 leader 在位时同步写入的;

(2)index:标志了这则日志在预写日志数组的位置.

raft 算法下节点的角色流转

1.角色切换

(1)leader -> follower

倘若 leader 发现当前系统中出现了更大的任期,则会进行“禅让”,主动退位成 follower.

leader如何探测到更大任期
I 向 follower 提交日志同步请求时,从 follower 的响应参数中获得;
II 收到了来自新任 leader 的心跳或者同步日志请求;III 收到了任期更大的 candidate 的拉票请求.

(2)follower -> candidate

leader 需要定期向 follower 发送心跳,告知自己仍健在的消息.

倘若 follower 超过一定时长没收到 leader 心跳时,会将状态切换为 candidate ,在当前任期的基础上加 1 作为竞选任期,发起竞选尝试补位.
(3)candidate -> follower
 I 多数派投了反对票(忽略不投票);

 II 竞选期间,收到了任期大于等于自身竞选任期的 leader 传来的请求.
 (4)candidate -> leader

 candidate 竞选时,倘若多数派投了赞同票,则切换为 leader.
 (5)candidate -> candidate
  candidate 的竞选流程有一个时间阈值. 倘若超时仍未形成有效结论(多数派赞同或拒绝),则会 维 持 candidate 身份,将竞选任期加1,发起新一轮竞选.

1.2 领导者

领导者是写请求的统一入口,在接收到来自客户端的写请求时,会开启“两阶段提交”
leader 还需要周期性地向集群中所有节点发送自己的心跳,告知自己的健康状况
(1)让 follower 重置心跳检测定时器,避免其切换成 candidate 发起竞选;

(2)在心跳请求中携带上 leader 最新已提交日志的标识 id(term + index),推动 follower 更新日志提交进度.
心跳请求是单向传输,而非双向通信. 因此,follower 无需对 leader 的心跳请求进行回复.

1.3 跟随者

follower 的职责包括如下几项:

(1)负责同步 leader 传来的写请求,此时也有一个参与民主反馈的过程,倘若同步成功,会给予 leader 正向反馈,当 leader 的同步请求收到半数以上的认可时,会提交日志;

(2)通过接收 leader 心跳的方式,获取到携带的 commitIndex 信息,及时完成已被多数派认可的预写日志的提交,以推进其写入状态机的进度. 这一项相当于做到了数据的备份,也被读请求最终一致性提供了保证;

(3)负责为参与竞选 candidate 的投票,决定赞同与否的判断机制见 5.3 小节;

(4)通过心跳检测定时器时时关注 leader 的健康状态,当超时未收到心跳时,会切换为 candidate 发起竞选.

1.4 候选人

candidate 是一个临时态,成为 candidate 意味着此时正处于成与败的分叉路口,candidate 有关的核心流程如下:

(1)倘若 follower 切为 candidate,会将当前任期加1,作为竞选任期;

(2)会将自身的一票投给自己;

(3)广播向所有节点拉票;

(4)倘若拉票请求超时前,得到多数派认可,则上位为 leader;

(5)倘若拉票请求超时前,遭到多数派拒绝,则老实退回 follower;

(6)倘若拉票请求超时前,收到了任期大于等于自身竞选任期的 leader 的请求,则老实退回 follower;

(7)倘若拉票请求超时,则竞选任期加 1,发起新一轮竞选拉票请求.

参考
小徐先生万字长文解析raft算法原理

你可能感兴趣的:(学习)