在讲述分布式的共识问题之前,我们先了解下什么是拜占庭将军问题, 其次从拜占庭将军问题来认识什么是分布式共识问题,与分布式一致性的区分在哪里?然后推演分布式共识问题产生的原因以及解决共识问题的策略算法有哪些,对应的适用场景有哪些?接下来我们可以带着疑问来逐步揭开上述问题的本质.另外这里要先说明一点,这里讲述的服务节点不可用包含网络超时/服务节点出现故障/网络通信被伪造等情况.
- 所有忠实的将军都能够采取相同的作战计划.
- 少数叛徒不会使忠诚的将军们采取错误的计划从而导致最终的作战失败.
基于上述的问题的理解,假设现在拜占庭军队中有三个师,每个师都有自己的将军,现在要准备开始作战计划攻打城池,现在需要满足上述讲到的要求,即保证每个师的忠诚将军都能够采取相同的作战计划以防止被叛徒信息误导采取错误的决定.此时需要每个师派发行使进行通信协商,同时为了保证协商存在可靠性,即下面的半数投票的可靠性.
这个时候我们可以看到,每一个师的将军都能够提供方案,说明是具备作战的指挥权的,相对地,其他师的将军就作为副官,负责执行作战方案.于是对于一个拜占庭将军问题可以进行以下归纳.
我们可以将问题进行简化为一系列由一个指挥官和多个副官组成的问题,即拜占庭将军问题:
简而言之,拜占庭将军问题就是如何在可能存在有叛徒的情况下,采取合适的通信机制来保证忠诚的将军能够达成共识采取一致的作战计划.
如果忠实于将军的将军少于或等于2/3,则不存在解决方案.
基于拜占庭将军问题的分析,我们将其翻译为分布式系统相关的术语,并对其进行阐述如下:
而分布式共识问题就是在分布式系统中,我们要如何保证系统服务节点之间的通信接收到的消息指令都是可靠且一致的.
在讲述分布式的共识与一致性之前,我们先来看下上述的图解,用户发起请求向分布式系统集群服务请求资源然后服务资源给予响应,这个时候我们考虑以下的场景:
从上述可以看到,对于分布式系统的共识与一致性问题其实关注的点不一样的,即:
分布式共识问题,即为了达到共识,每个进程都提出自己的提议(propose),最终通过共识算法,所有正确运行的进程决定(decide)相同的值,如下图所示:
在上面的图示可以看出,不同的进程p0,p1,p2以及p3分别输入一个数据值,然后通过执行程序来处理并交换输入值,保证最终输出的数据值都是一致的.即不同进程的输入值通过自身相同的一套程序进行交换处理输入数据并最终都输出一致的数据v.
摘录分布式共识的英文阐述如下:
1.Termination: Every non-faulty process must eventually decide
2.Agreement: The final decision of every non-faulty process must be identical
3.Validity: If every non-faulty process begins with the same initial value v, then their final decision must be v
对于分布式共识应用场景有:
关于ATC可以参考:https://science.howstuffworks.com/transport/flight/modern/air-traffic-control.htm
基于拜占庭将军问题,现假设有三个军队的将军,现在准备拟定攻城的计划,三个将军对此进行各自拟定计划(进攻或者是撤退的策略)并由信使负责消息的传递,最终通过“少数服从多数”原则来决定最终的决策方案.
A将军此时发起决策提案为进攻,对于B和C正常接收到的信息是进攻;B将军发起的决策提案为撤退,对于A和C正常接收到的信息为撤退,C将军发起的决策提案为进攻,那么这个时候对于A和B看到的提案为进攻,这个时候我们分别思考A,B,C三位将军接收到的提案为:
A将军: 自己进攻的提案 + B将军的撤退提案 + C将军的攻击提案,因此最终决定进攻.
B将军:自己撤退的提案 + A将军的进攻提案 + C将军的进攻提案,因此最终决定也是进攻.
C将军: 自己进攻的提案 + B将军的撤退提案 + A将军的进攻提案,因此最终决定也是进攻.
但是这个时候我们需要看到上述决策成功需要满足要求:
1.所有的将军都是忠诚的
2.在上述的半数投票过程中,需要满足参与投票的将军个数为2n+1,不然无法决定投票结果.
如果三个将军中有一个将军出现问题,那么此时的情况又被变成如下的情况:
1.其中一个将军为叛徒
2.其中一个将军的信使被间谍替换
3.其中一个将军的信使中途被杀
A将军: 自己进攻的提案 + B将军的撤退提案 + C将军的攻击提案,因此最终决定进攻.
B将军:自己撤退的提案 + A将军的进攻提案 + C将军的撤退提案,因此最终决定是撤退.
C将军: 因为自己本身是叛军,当然在战场上肯定也是撤退
这个时候三位将军采取最终方案是不一致的,这样会导致A将军直接受到伏击被敌军歼灭;
A将军: 只接收到B将军的撤退提案 + 自己攻击的提案, 这个时候是无法进行决策
B将军: 只接收到A将军的攻击提案 + 自己撤退的提案, 这个时候也无法进行决策
C将军: 接收到A将军的攻击提案 + 自己的攻击提案 + B将军的撤退提案,采取攻击提案.
这个时候可以看到A,B,C三位将军最后做决策的时候将无法保证最终的提案一致性而采取相同的行动.
通过上述的分析,我们将其转化为分布式系统集群三个服务节点A,B,C之间可能存在的问题如下:
当向分布式系统集群服务发起事务操作请求的时候,如果这个时候存在服务节点发生故障(信使被截杀)抑或是服务节点在消息通信过程被劫持,整个集群服务节点将无法对当前的事务请求操作采取一致性的行动.
1.连接两个服务节点之间的通信介质的故障与服务节点发生的故障是无法区分的.如超时网络不通/服务节点宕机均为不可用等均视为服务节点不可用
2.如果出现线路故障表示分布式系统中的集群服务节点多了一个不可用的服务节点.
不需要通过网络交换就能知道消息发送者的信息
需要有超时机制
算法定义
基于上述的假设,现有一个算法函数major满足fn=(V1,V2,…Vn-1),该函数表示集群服务节点中每个节点一个提案值vi,fn表示集群中vi占过半投票对应的提案值v,而口头消息解决算法有一个前提条件,那就是必须是集群服务节点不可用的个数m必须满足m 算法描述 现对于3m+1的集群服务节点选举一个具备指挥权的服务节点作为leader,其他节点作为replicate,这个时候存在以下两种情况 当m=0时,即不存在服务节点不可用时,其算法执行的策略为: 当m>0时,其执行的算法如下: 经过上述的算法,对于存在m个不可用或者是不可靠的服务节点,需要经过m+1次的递归发起提案请求,同时可以递归推导得出O(m)调用(n-1)次递归独立执行O(m-1). 基于上述的分析,如果仅有上述的集群服务的3个节点,基于口信消息的方案是无法解决拜占庭将军问题的,现分析如下: 对于上述集群服务节点A,B,C节点中,对于B而言不论A是叛变还是C是叛变的,都无法作出决策,说明信消息要达到交互的一致性在集群中只有3个服务节点要是无法做到. 基于此,我们需要将军队多划出一个独立军队,产生一个新的指挥官,而A,B,C作为副官,负责执行提案策略.这个时候基于上述的算法就有以下情况. 从上述可以看出: 不论是哪种结果对于忠诚的将士而言最终采取的行动是一致的. 对于我们分布式互联网而言,一般在企业内部的集群机器而言,由于对外存在防火墙以及安全的网关校验,因此对于企业服务内部都是采取当前的算法策略来解决我们集群服务选举,进程互斥以及分布式事务等问题提供解决方案的思路.对于口信消息的算法,一般用于系统容错故障但不存在恶意攻击的服务节点,即CFT算法,这个场景可能会丢失消息,或者有消息重复,或者是顺序一致性处理等场景,其对应的常用算法有Paxos算法、Raft算法、ZAB协议. 这个时候我们发现上述的解决方案需要在原有的集群服务中增加一个leader节点作为整个集群具备指挥权的服务节点.那么是否可以考虑不需要进行加服务节点就能够解决服务节点之间的共识问题呢?这个时候就需要运用到我们的签名消息解决方案. 1.集群服务节点之间的消息通信无法被伪造,任何被伪造的消息都能够被检测出来 算法要求 基于上述A1-A4的假设要求,如果存在m个不可用的服务节点,那么整个集群的服务节点必须是不少于m+2,否则无法得到问题的解决.该算法为空洞. 算法的定义 我们定义一个函数fn=choice(V)表示有序的集合中存在签名的消息元素v,如果集合中只有一条消息元素v,那么fn=v. 算法描述 在该算法中,指挥权的服务节点向其他服务节点发送一个按照一定规则签名的消息到其他服务节点中,其他服务节点接收到消息之后将其签名添加到有序的签名消息中并进行发送到其他服务节点中,其他服务节点以此类推.如果存在服务节点“叛变”,必须有效地接收签名的消息,并对签名消息生成多份副本,然后再将这些副本进行签名然后发送到其他节点中.最后不论副本是如何得到,其中单条签名的消息要么是被通过副本拷贝要么是与单条签名一致并正确分发过来的消息. 基于上述的算法,我们仍然用拜占庭将军为例子进行分析如下: 最后关于消息签名的算法,从上面我们可以看到是去中心化的一个分布式系统架构服务,因此对于公网环境下执行事务型操作可以考虑使用消息签名的算法,最大优势在于去中心化.
口头消息解决方案分析
小结
签名消息的解决方案
实现签名消息的要求以及含义
2.每一个服务节点都能够核实消息签名的真实身份.消息签名的算法
v:0:i
的形式发送到其他非指挥权的服务节点上.v:0:j1...:jk
并且v并不在集合V中,那么对于当前的服务节点将会把v添加到集合V中并当k
:i
的形式发送到其他服务节点,否则将以消息为`v:0:j1…:jk的形式发送到其他服务节点上.消息签名算法分析
小结