raft是一种用于管理复制日志的一致性算法。
它做两件事情:
- 选举leader:目的是有个leader好协调处理各个follower之前的问题;
- 日志复制:目的是保证数据在follower之间的一致性和数据的持久化(只要follower不全部挂掉,数据就还在)
1. 三个状态(角色)
- 领导者:leader,皇帝,皇帝在一个任期内只能有一个。负责接收和响应客户端请求、创建日志、同步日志给follwer、发送心跳给follower。
- 跟随者:follower,良民,被皇帝管理的,是良民(能收到皇帝发送的心跳包的)。接受leader的心跳、日志,可以投票给选举者。
- 选举者:candidate,诸侯,没有皇帝管的,是诸侯(可能是皇帝挂了,或者根本就没有皇帝,反正它们这些诸侯在一定时间内没有收到皇帝的心跳包了,才变成诸侯的)。可以选举和被选举。
2. 选举
2.1. 选举过程
- 所有节点初始为跟随者。最开始大家都是良民。
- 跟随者等待一段随机时间(150ms至300ms),这段时间内没有收到来自领导者的消息,就会变成候选人。有些地方好几年没有皇帝的消息,就开始造反,割据一方,成为诸侯。
- 候选人向其他所有节点,发送请求给候选人投票的消息。诸侯们互相招安,让对方投靠自己。
- 每个节点在一个选举周期内只能给一个候选人投票。张辽投靠了曹操,就要一直跟着他,直到天下出现一个新皇帝,这个世界不能有吕布这种二五仔。
- 如果候选人获得大多数节点的投票,就成为领导者。地盘超过一半,就是皇帝,其他势力必须马上投靠。
- 选举过程中,如果收到来自新领导者的消息,候选人会转变为跟随者,如果新领导的任期比当前节点的任期还老,会拒绝当前请求,并让该节点更新term。正在东征西战的诸侯,突然收到皇帝的消息,要直接归顺,但如果是东汉末年收到秦始皇的号令,还是不会接受的,而且会让秦始皇认清现实。
所谓选举周期,就是一轮选皇帝的周期。
为什么要等待随机时间才成为候选人?答:为了减少同时变成候选人的节点数量,这样选举就会结束得快一些。如果美国几亿人都直接参与选举,他们100年都选不出总统来。
2.2. 选举时投票的决策算法
某个节点收到a/b两个候选人节点,投票给谁呢?Raft算法会考虑谁的日志更完整、谁人任期更新。
2.2.1. 更完整的日志
- 日志的长度:日志越长通常意味着该节点包含更多的已提交和未提交的操作记录,更有可能处于最新的状态。所以节点更倾向于投票给日志更长的候选人。选择投靠兵力更多的一方:吕布看到曹操有100万,刘备只有2万,肯定去投靠曹操了。
- 日志条目的内容:如果两个节点的日志长度相同,那么会进一步比较日志条目的内容。具有更完整、连续且与大多数节点一致的日志的候选人更有可能获得投票。选择投靠纪律严明的一方:当初刘备只有5千人马,但军纪严明,公孙瓒有10万人马,但军纪涣散,赵云就投靠了刘备。
2.2.2. 更新的任期号(term)
任期号是Raft算法中用于区分不同选举阶段和领导权的重要标识。每个节点在不同的选举周期中会处于不同的任期。一般来说,任期号更高的候选人更有优势,因为这意味着该候选人可能代表着更新的领导权主张。东汉末年,有个人说他是曹操,另一个人说他是秦始皇,你投靠谁?按raft算法,投靠曹操,秦始皇太老了。
2.2.3. 日志和任期号哪个优先级更高?
Raft算法会优先考虑日志完整性。有个人说他是曹操,有10万乌合之众,另一个人说他是秦始皇,有100万秦锐士,你投靠谁?按raft算法,投靠秦始皇,他虽然老,但是兵力雄厚啊,还是要实力说话。
3. 日志复制
假设有3个raft集群曹操、刘备、孙权。从刘备这个raft集群的角度来看,曹操、孙权是它的客户。刘备这个raft集群里有五虎将作为5个follower,刘备是leader。
- 领导者接收来自客户端的请求,将其作为新的日志条目添加到自己的日志中。孙权告诉刘备,曹操准备进攻汉中,刘备赶紧拿个小本本把这事儿记下来。
- 领导者然后并行地向其他节点发送日志复制请求。刘备派了5个信号兵去分别通知五虎将这个事儿。
- 跟随者收到日志复制请求后,如果日志条目在自己的日志中不存在或者不匹配,就将其添加到自己的日志中,并回复领导者。黄忠收到消息,发现自己还不知道这个事,就赶紧记下来,然后回复刘备;关羽收到消息一看,自己早就知道了,就不记录了,然后回复刘备;张飞之前收到过消息说曹操不过来,今天收到刘备的消息说曹操要来,大吃一惊,然后把他本本上记的消息改正过来,并回复刘备。赵云、马超收到消息也是类似的做法。
- 一旦大多数节点都成功复制了日志条目,领导者就可以将该日志条目应用到状态机,并向客户端返回响应。只要有3个人回复刘备了,刘备就可以告诉孙权说,大舅子,我知道了,我准备好了。
所以在刘备集团里,日志复制的目的,就是让刘备集团里大部分人都知道曹操要打过来了,当然刘备也要知道啊。
4. raft的缺点
- 对领导者的依赖:单点故障风险,领导者故障会导致服务暂时不可用,影响可用性。
- 网络分区的影响:数据不一致风险,不同分区选出不同领导者。设置超过一半才能成为leader,就不会选举出多个leader了。
- 性能开销大:日志复制和选举过程都有通信开销,大规模系统中可能影响效率。如果心跳超时时间太短,可能导致频繁选举。
5. 用了raft的中间件
5.1. etcd
etcd是一个高可用的分布式键值存储系统,用于k8s中,来保证数据的一致性和高可用性。etcd 可以在多个节点上存储关键数据,并确保在节点故障或网络分区的情况下,数据仍然能够被可靠地访问和更新。
5.2. consul
consul是一个服务发现和配置管理工具。用Raft来实现分布式一致性。
5.3. nacos
- Nacos是阿里巴巴开源的分布式协同、配置管理中间件,支持AP、CP两种模式。
- Nacos的CP模式是靠Raft协议来实现的,用于确保分布式系统中的数据一致性和容错性。