分布式系统是由多个计算机节点协同工作,共同完成一个任务或提供一个服务的系统。这些节点通过网络进行通信和协调,彼此之间相互独立且具有一定程度的自治性。分布式系统的设计旨在提高系统的可靠性、可扩展性和性能。
然而,分布式系统也面临一些挑战和困难:通信和协调、一致性和同步、容错性和可靠性、可扩展性、安全性和隐私保护、故障诊断等等。
解决这些挑战需要采用适当的架构设计、协议和算法,以确保分布式系统的可靠性和性能。其中解决一致性和可用性可以说是最重要的事情,需要选择合适的共识算法。
1),故障错误(Crash Fault)
这些都是由于分布式系统中的物理硬件的不可靠,不稳定带来的风险,是我们系统设计中必须考虑的问题。
2),拜占庭错误(Byzantine Fault)
伪造信息
维基百科:分布式系统的一个基本问题是在存在一些故障进程的情况下实现系统的整体可靠性。这往往需要协调进程来达成共识,或者就计算过程中需要的一些数据值达成一致。共识的应用实例包括同意以何种顺序向数据库提交哪些事务、状态机复制和原子广播。
简单说在分布式系统中,共识就是系统中的多个节点对某个值达成一致。即使出现部分节点故障,网络延时等情况,也不影响各节点,进而提高系统的整体可用性。
举个生活中例子,你和几个朋友要去吃饭,你说“咱们去吃烧烤吧”,大家都同意即达成了共识。
真正意义上的共识算法需要满足以下特性:
终止性,描述了算法必须在有限时间内结束,不能无限循环下去;一致性描述了我们期望的相同决议;合法性是为了排除无效或无意义的值。
本文限于篇幅,不会对算法部分细节展开讨论,希望能帮助读者对于共识算法有个整体上的认知。
拜占庭将军问题实际上是一个共识问题。通过类比的方式来描述分布式系统中最困难的一类问题:
拜占庭帝国派出多支军队去围攻一个强大的敌人,每支军队都有一个将军,但是由于彼此之间距离较远,他们之间只能通过信使传递消息。敌方实力强大,只有超过半数的拜占庭军队一起参与进攻才能击败敌人。在这个过程中,将军们彼此之间需要通过信使传递消息并协商一致,然后在同一时间点发起进攻。
问题难点:这些将军们困扰于不确定自己中是否存在叛徒,叛徒可能会擅自改变进攻意图或进攻时间。在这种情况下,拜占庭的将军们能否找到一种分布式协议,让他们能够远程协商并取得胜利?
回顾上述问题:
一群将军希望达成某个目标(一致进攻或一致撤退),但单独行动无法实现,必须合作达成共识。由于叛徒的存在,将军们不知道如何达成一致。
需要注意的是,在拜占庭将军问题的探讨中,重点在于"一致性"。如果叛徒的数量已经多到问题无法解决的程度,那就是"反叛"的问题了。同时,我们的目标是让忠诚的将军能够达成一致,对于这些忠诚的将军来说,进攻或撤退都是可以的,只要他们能够达成一致就行。
但是,仔细想想:仅凭“一致性”就可以解决问题吗?
考虑这样一种情况:假设一切都准备就绪,客观上每个忠诚的将军只要进攻就一定能够胜利,但由于叛徒的存在,他们无法达成一致性而无法进攻;相反地,条件并不利,将军们不应该进攻,但由于叛徒的存在,却出现了所有人都一致性进攻的情况。因此,我们还需要提出一个"正确性"要求。
那我们该如何定义这个“正确性”呢?
我们可以简单地说,正确性意味着每个忠诚的将军都能正确表达自己的意图,并且其他将军不会因为错误地认为忠诚的将军是叛徒而忽略他传达的消息。最终,所有忠诚的将军应该能够相互传达自己的真实意图并达成共识。形式上的要求就是“一致性”和“正确性”。
对应到实际应用场景,我们不仅需要考虑网络问题和一致性问题,还需要考虑数据的正确性和是否被篡改问题。
通常情况下,发生故障(如崩溃或停止响应)但不产生伪造信息的情况被称为“非拜占庭错误(Non-Byzantine Fault)”。
提出并证明该定理的论文《Impossibility of Distributed Consensus with One Faulty Process》是由 Fischer、Lynch 和 Patterson 三位科学家于 1985 年发表,该论文后来获得了 Dijkstra 奖。
“It is impossible to have a deterministic protocol that solves consensus in a message-passing asynchronous system in which at most one process may fail by crashing.”
在一个完全异步的消息传递分布式系统中,最多有一个进程可能因崩溃而失败,不存在一个可以解决一致性问题的确定性共识算法。
简单来说,这意味着在异步系统中,不可能设计出能够满足协议、终止和容错的确定性共识算法。
deterministic protocol:
● 即对于一个特定的输入,始终产生相同的输出
asynchronous:
● 不假设进程的相对速度或传递消息的延迟时间
● 进程无权访问同步时钟
● 无法检测进程的死亡
crashing:
● 非拜占庭问题,非 fail-stop,只是崩溃问题。
● 所有进程遵循协议,除了崩溃的进程。
solve:
● 意味着同时满足一致性和终止性。
不可能的根本原因在于,在异步网络模型的定义中,消息传递的延迟和节点处理的延迟没有上限。因此,在节点实际崩溃时,我们无法确定是否有节点发生崩溃,只能无限等待下去,使共识算法无法满足“终止性”。然而,在实际环境中,我们可以允许共识算法使用超时、随机化、故障检测或其他方法来识别可疑的崩溃节点(即使有时怀疑是错误的)。这样就避免了无限等待,并使得达成共识成为一个可行的任务。Paxos 和 Raft 就是这样的共识算法的例子。
FLP 不可能性原理告诉我们,不要浪费时间尝试为异步分布式系统设计适用于任何场景的共识算法。换句话说,我们需要有边界思维,并根据实际情况设计可行的工程方案。
FLP 不可能原理告诉我们要有边界思维,不要存有妄念去追求完美的共识方案,那么,退一步,在付出一些代价的情况下,共识能做到多好?回答这一问题的是:CAP 理论。
CAP 定理指出对于任何分布式数据存储系统来说,只能提供以下三项保障中的两项:
由于节点间的分区故障是必然发生的。也就是说,分区容错性(P)是前提,是必须要保证的。
澄清几个误解:
1,即只有在发生分区故障时,才会在 C 和 A 之间选择一个,正常运行的时候 C 和 A 是能够同时保证的。分区故障概率很低的。
2,C 和 A 的选择不是针对整个分布式系统,子系统可以选择不同的指标。
3,这三个指标的选择不是极端的,比如 AP 系统里,C 只是被弱化,不意味着完全不考虑。
BASE 理论是 CAP 理论中 AP 的延伸,考虑了网络时延和系统恢复正常后的状态,是对互联网大规模分布式系统的实践总结,强调可用性。
BASE 理论通过放松一致性要求并将可用性和最终一致性作为分布式系统设计原则的重点,对 CAP 定理进行了扩展。它承认在存在故障和网络分区的情况下实现强一致性可能具有挑战性,并且在某些情况下为了改善可用性和分区容忍性而牺牲严格一致性是合理的权衡。
BASE 理论核心思想是:既然无法达到强一致性,就采用合适的办法达到最终一致性。
BASE 理论主要是针对 NoSQL 数据库而言的,它是对 CAP 理论中一致性(C)和可用性(A)进行权衡的结果。最终一致性是 BASE 原理的核心,也是 NoSQL 数据库的主要特点,通过弱化一致性,提高系统的可伸缩性、可靠性和可用性。而且对于大多数 Web 应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是多数分布式数据库产品的方向。
以下是一些符合 BASE 理论的系统:
需要注意的是,BASE 理论并非对于特定系统或领域的具体要求,而是一种设计思想和权衡考虑。在实际应用中,BASE 理论的具体实现和应用可能因系统的特点和需求而有所不同。因此,在选择和使用系统时,应根据具体情况评估系统的可用性、一致性和分区容忍性等要求,并根据需求做出合适的选择。
限于篇幅,这里只列出几个常用的共识算法并简单描述。
拜占庭容错算法(比如 PoW 算法、PBFT 算法),在相对开放的场景中应用广泛,比如公链、联盟链。
非拜占庭容错算法(比如 Paxos 算法、Raft 算法),主要用于封闭、绝对可信的场景中,比如私链、公司内网的 DevOps 环境。
Paxos 算法包含 2 个部分:
在 Basic Paxos 中,有提议者(Proposer)、接受者(Acceptor)、学习者(Learner)三种角色,他们之间的关系如下:
达成共识:
整个共识协商是分 2 个阶段进行的,简单描述如下:
上面提到 Multi-Paxos 是多个 Basic Paxos 实例,就一系列值达成共识,结合 Basic Paxos 算法的流程描述会发现将存在几个问题:
针对这两个问题,Multi-Paxos 的解决方案:
Raft 算法现在是分布式系统开发首选的共识算法。Raft 可以看成是 Multi-Paxos 的改进和具体实现算法。
成员身份,也叫节点状态:分为领导者(Leader)、跟随者(Follower)和候选人(Candidate)3 种状态。
因为领导者是唯一的,因此需要有选举流程,大致如下:
其它说明:
PBFT 是一种能在实际场景中落地的拜占庭容错算法,在区块链中应用广泛。
拜占庭错误,在网络问题的基础上,还需要处理伪造信息的问题。上面的半数以上节点达成共识的算法解决不了这种问题。
PBFT 引入了签名机制 + 三阶段协议来达成共识:
签名,可以保证消息发送者的身份和消息内容不被伪造和篡改。
三阶段协议分为,预准备阶段、准备阶段、提交阶段。因为拜占庭将军们是分散的,没有一个中心的领导机构,所以需要多个阶段达成一致。
PBFT 算法能容忍 (n - 1)/3 个恶意节点 (也可以是故障节点)
在准备和提交阶段,每个节点是要把消息广播给其它节点的,消息数量还是比较多的。因此适合在中小型分布式系统中使用。
PBFT 算法能够容忍(n - 1)/3 个恶意节点,在中小规模且相对可信的场景下已足够,但在公共网络中运行则不够安全。
工作量证明(Proof of Work)通过增加恶意行为的成本来解决这个问题。防止坏人作恶的最佳方式是让其付出更高的成本,使其利益小于成本,甚至无法承担成本。
具体而言,工作量证明通过执行哈希计算(比特币使用 SHA-256 算法)来完成,经过一段时间的计算后,得到符合特定条件的哈希值,然后将该信息广播给网络中的所有节点。其他节点在验证后将该区块添加到区块链中。
存在的问题
本文先介绍了分布式系统面临的挑战以及共识算法可用于解决其核心难题和痛点;
然后表述了共识算法的定义,并说明了其关键特性:终止性、一致性和合法性;
拜占庭将军问题和非拜占庭将军问题提供了对分布式共识问题的情景化描述;
FLP 不可能性原理为共识问题设定了界限,告诉我们不要浪费时间追求完美的共识算法;
CAP 定理和 BASE 原则提出了现实可行的理论指导;
最后,简要介绍了 Paxos、Raft、PBFT 和 PoW 算法。
领取专属 10元无门槛券
私享最新 技术干货