背景
随着云计算的发展,分布式系统已经是几乎所有中大型系统的架构选择。在分布式系统中,原先单机系统中简单的问题变得复杂。如锁的实现由单进程多线程内部的锁变为分布式锁,分布式数据库中如何保证集群数据一致性,或者更准确的说,集群如何达成共识。
对于分布式系统,必须有一个指挥官对系统进行集中控制,指挥系统各部件协同工作,不然大家各干各的,最终肯定是乱套了。而这个指挥官如果是单机部署的,又会出现单点问题,所以指挥官也必须集群部署,而且要从集群中选出一个大将军作为系统的指挥官,当这个大将军挂掉的时候,系统能选择新的大将军接管系统。
本文要探讨的分布式共识问题,主要是探讨大将军如何选择,以及它如何指挥系统协同工作。这个大将军,在分布式系统中,称作分布式应用程序协调服务,业界比较流行的有Zookeeper和ETCD等。
拜占庭将军问题
说到分布式一致性问题,不得不提的是拜占庭将军问题。拜占庭将军问题(Byzantine failures),是由莱斯利·兰伯特提出的点对点通信中的基本问题。含义是在存在消息丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。
由于拜占庭问题需要考虑在有叛徒和敌方间谍的情况,问题比较复杂,根据信息系统通信的现状,主要是主机挂掉或网络中断的情况,而不考虑恶意伪造消息,因此对一致性的研究一般假设信道是可靠的,或不存在本问题。
推选大将军
分布式系统的第一步,是要选出大将军作为系统指挥官,基于简化的拜占庭将军模型(即没有叛徒和间谍,但通信兵可能被暗杀),首先我们先来看下将军们如何选举出大将军。
假设有A、B、C三个指挥官,他们满足以下条件:
- 指挥官个数大于等于3,且为奇数个。
- 每个指挥官都有一个随机计时器叫选举计时器
election timeout
,时间一到,这位将军就发起一轮推举大将军的活动,自荐为大将军候选人,并派出通讯兵,询问其他指挥官是否同意推举自己为大将军,同时重置选举计时器等待大家的回复。 - 其他指挥官收到推举大将军的信息后,如果他没有推举过大将军,就同意此请,由通讯兵回复,并重置自己的选举计时器。
- 每个指挥官每轮只能同意一次。
- 如果候选人收到大多数(超过半数)指挥官同意,则此指挥官成为大将军。
- 成为大将军后,大将军通过心跳计时器
heatbeat timeout
向个指挥官下达作战命令。 - 如果某位指挥官的选举计时器结束时,推举还没有成功,则本轮推举失败,取消所有指挥官候选人资格,重复执行上述第一步,直到推举成功为止。
- 选举成功后,每位指挥官维护一个心跳计时器,如果计时结束时,还没有收到大将军的命令,则认为大将军阵亡,重新启动推举活动。
这就是Raft共识算法选主 Leader Election
的过程。从拜占庭将军的故事映射到分布式系统上,每个将军相当于一个分布式网络节点,每个节点有三种状态:Follower(指挥官),Candidate(候选人),Leader(大将军),状态之间是互相转换的。
注:
- 选举计数器的时长设置,每个指挥官不一样,一般为150ms-300ms,这样可以避免大家的计时器一起结束。
大将军发布命令
大将军发布命令后,需要等大多数(超过一半)的指挥官回复收到命令,命令才算发布成功。对应到Raft共识算法,这就是复制日志 Log Replication
。
- 大将军发布命令,这是命令为未确认
Uncommitted
状态。 - 通信兵把命令发送各指挥官。
- 指挥官收到命令后,保存命令,状态也是未确认,并回复。
- 当大将军收到多数指挥官回复时,任务命令发送成功,把命令状态修改为已确认
Committed
。 - 大将军再次向各指挥官发送确认消息。
- 各指挥官把消息状态改完已确认。
以上主要以通俗的方式描述了下Raft共识算法的大致流程,详细的流程及异常处理,网络有很多的文章,这里不再重复。
参考资料:
共识算法:Raft
Understandable Distributed Consensus
The Raft Consensus Algorithm
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。