Nacos是强一致性还是最终一致性
单机模式下不存在这个问题,强一致性。
1. CAP原则
又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
2. Raft算法
Nacos 集群为了保证集群中数据的一致性,其采用了 Raft 算法,是通过对日志进行复制管理来达到一致性的算法。
Raft 算法是强一致性算法。
Nacos 同时支持 AP 与 CP,默认情况下,Nacos 集群是 AP 的。
Nacos支持CP+AP模式,即Nacos可以根据配置识别为CP模式或AP模式,默认是AP模式。如果注册Nacos的client节点注册时ephemeral=true,那么Nacos集群对这个client节点的效果就是AP,采用distro协议实现;而注册Nacos的client节点注册时ephemeral=false,那么Nacos集群对这个节点的效果就是CP的,采用raft协议实现
Raft算法将Server划分为三种角色:
- Leader:负责处理客户端读和写请求的节点,同时负责日志复制工作,一个集群中只有一个Leader。
- Follower:可以处理客户端读请求,负责同步来自于 Leader 的日志,当接收到其它Cadidate 的投票请求后可以进行投票;当发现 Leader 挂了,其会转变为 Candidate 发起Leader 选举。
- Candidate:一种临时的角色,只存在于leader的选举阶段(Leader 选举的候选人),某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate。如果选举成功,则变为candidate,否则退回为follower
3.选举
Raft中使用心跳机制来出发leader选举。当服务器启动的时候,服务器成为follower。只要follower从leader或者candidate收到有效的RPCs就会保持follower状态。如果follower在一段时间内(该段时间被称为election timeout)没有收到消息,则它会假设当前没有可用的leader,然后开启选举新leader的流程。
Term(任期)
任期用连续的数字进行表示。每一个任期的开始都是一次选举(election),在某些情况下,有可能没有选出Leader,那么,将会开始另一个任期,并且立刻开始下一次选举。Raft 算法保证在一个任期内只有一个Leader.
过程
- follower增加当前的term;
- 转变为candidate;
- 向自己投票;
- 向其它节点发出投票请求。
投票
- 发来投票请求 candidate 的 term 和 log 编号不能小于当前 candidate 的 term 和 log 编号;
- 当前 term 内 candidate 的票还没投递给自己(一个 term 内每个节点都只有一票 );
- 接收到多个投票请求时,采取先到先得投递。
结果
当一个 Candidate 发出投票请求后会等待其它节点的响应结果。这个响应结果可能有三种情况:
- 收到过半选票,成为新的 leader。然后会将消息广播给所有其它节点,产生新 Leader 了(其中包含其当前的 term);
- 接收到别的 candidate 发来的新 leader 通知,比较新 leader 的 term 是否不比当前的 term小,则自己转变为 follower;
- 没有收到过半选票,也没有收到新 leader 通知,则重新选举。
- 票数相同时,采取随机选举超时处理:让这些 candidate 的选举在一个给定范围值内,各自随机的 timeout 之后开始,此时先到达 timeout 的 candidate 会先发出投票请求,并优先获取到投票。
4.数据同步/日志复制
主要作用是用于保证节点的一致性,这阶段所做的操作也是为了保证一致性与高可用性。
Raft 把每条日志都附加了 任期号和下标 来保证日志的唯一性.
当Leader选举出来后便开始负责客户端的请求,所有事务(更新操作)请求都必须先经过Leader处理。
- 在Raft中当接收到客户端的日志(事务请求)后先把该日志追加到本地的Log中;
- 然后通过 heartbeat 把该Entry同步给其他 Follower;
- Follower 接收到日志后记录日志然后向 Leader 发送ACK;
- 当 Leader 收到大多数(n/2+1)Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中;
- 通知客户端并在下个heartbeat中 Leader 将通知所有的Follower将该日志存储在自己的本地磁盘中。
5.脑裂
在一个高可用系统中,当联系着的节点因为网络连接断开联系时,本来为一个整体的系统,分裂成两个独立节点,两个节点开始争抢共享资源造成系统混乱、数据损坏的现象,成为“脑裂”。
列如:FollowerA由于网络问题感知不到Leader存在,FollowerA与FollowerB之间是相连的,此时FollowerA会发起选举,虽然 FollowerB能够感知到 Leader,但由于其接收到了更大 term 的投票请求,所以 FollowerB也就放弃了Leader,参与了新 Leader 的选举。新Leader的写请求并不会同步到原Leader节点上。而之前的Leader由于无法获取过半响应而无法处理写操作请求,不过并没有被Down,其仍为 Leader。所以之前Leader的数据是不会发生变更的。此时就形成了数据的不一致。
解决方案:通过时间续约和term比较最终旧leader被同步为follower。