区块链系统架构核心简析: 一致性与共识机制
金融分析师
1 人赞同了该文章
区块链系统,首先是一个分布式系统。传统单节点结构演变成分布式系统,碰到的首要问题就是一致性的保障。
在很多时候,一致性会与共识放在一起讨论,但严谨地讲,两者含义并不完全相同。
一致性往往指分布式系统中多个副本对外呈现的数据的状态。如顺序一致性、线性一致性,描述的是多节点对数据状态的维护能力。而共识则描述的是分布式系统中多个节点之间,彼此对某个目标所达成的一致结果。总的来说,一致性代表的是一种结果状态,而共识则是一种手段。达成共识并不意味着保障了一致性。
对外——一致性
一致性问题是分布式领域最基础也是最重要的问题。如果分布式系统能够实现“一致”,对外就可以呈现出一个完美的、可扩展的“虚拟节点”,这也是分布式系统最想达到的目标。
何为一致性?
具体而言,是指针对分布式系统中不同节点,给予一定操作,在约定协议的保障下,试图使得它们对处理结果达成“某种程度”的认同。
在理想情况下,如果各服务几点严格遵循相同的处理协议,构成相同的处理状态,给定相同的初始状态及输入序列,则可以保证在处理过程中的每个环节结果均相同。
但值得注意的是,一致性并不代表结果正确与否,而是系统对外呈现的状态是否一致,如果所有节点都达成失败状态也是一种一致性。
对于区块链系统,想要达成一致性结果,必须满足:
(1)可终止性:结果在有限时间内能够完成;
(2)约同性:不同节点最终完成决策的结果是相同的;
(3)合法性:决策的结果必须是某个节点提出的提案。
但想要实现绝对理想的严格一致性(strict consistency)可能性不大,除非系统不发生任何故障,同时所有节点之间链接无需时间,整个系统实质上等同一台机器。从实际情况出发,越强的一致性往往会造成越弱的处理性能,以及越差的可拓展性。
进而,强一致性(strong consistency)开始被业界所提出,主要包括顺序一致性、线性一致性,但依旧比较难实现,而且从实际需求出发,需求性不大,同时强一致性的实现往往意味着高成本。
因此,目前市场大部分系统的实现往往是通过所谓的最终一致性(eventual consistency),即总会存在一个时刻,让系统达到一致的状态。
对内——共识算法
共识算法解决的是对某个提案,大家达成一致意见的过程。对于分布式系统来讲,各节点通常是相同的确定性状态急模型,从相同初始状态开始接受相同顺序的指令,则可以保证相同的结果状态。因此,系统中多个节点最关键的是对多个事件的顺序进行公示,即排序。
对于共识算法分类,主要是根据解决的是非拜占庭导致的错误情况,亦或者是拜占庭错误,可分为Crash Fault Tolerance(CFT)类算法和Byzantine Fault Tolerance(BFT)类算法。
其中针对常见的非拜占庭错误情况,可以使用一些经典的解决算法,包括Paxos、Raft及其变种。这类容错算法往往性能比较好,处理较快,容忍不超过一般的故障节点。
对于要容忍拜占庭错误的情况,主要包括PBFT(Practice Byzantine Fault Tolerance)为代表的确定性系列算法、及以PoW为代表的概率算法等。拜占庭类算法总体而言性能较差,容错不超过1/3的故障节点。
对于确定性算法,一旦达成对某个结果的共识就不可逆转,即共识是最终结果;而对于概率算法,共识结果多为临时性,随着时间推移或某种强化,共识结果被推翻的概率越来越小,最终成为事实上的结果。
拜占庭问题及算法
目前对区块链各类算法的讨论,核心也就是如何解决拜占庭问题,即在允许少数节点作恶(消息可能被伪造)情况下的一致性达成问题。
拜占庭容错算法(PBFT),是面向拜占庭问题的容错算法,解决的是在网络通信可靠但节点可能出现故障情况下如何达成共识。
其系统假设为异步分布式的,通过网络传输的消息可能丢失、延迟、重复或者乱序。但节点的失效必须是独立发生的,也就是说代码、操作系统和管理员密码这些东西在各个节点上是不一样的。
另外,PBFT算法使用了加密技术来防止欺骗攻击和重播攻击,以及检测被破坏的消息。消息包含了公钥签名(其实就是RSA算法)、消息验证编码(MAC)和无碰撞哈希函数生成的消息摘要(message digest)。
其算法的基本过程主要包括:
1.客户端向主节点发送请求调用服务操作 2.主节点通过广播将请求发送给其他副本 3.所有副本都执行请求并将结果发回客户端 4.客户端需要等待f+1个不同副本节点发回相同的结果,作为整个操作的最终结果。
具体实现过程,包括视图切换、Checkpoint机制等,有兴趣朋友可以参考一下其论文内容,在此不再赘述。
新解决思路与新问题
拜占庭问题之所以难解,是因为在任何系统中都可能存在多个提案(成本低),并且要完成最终一致性确认的过程也十分困难,容易受干扰。
怎么说?为什么PBFT,乃至所有的BFT都没法应用于超过100个节点?关键原因在于O(N^2)的消息复杂度。
点对点的消息传输需要发一个消息就够了,这是O(1)的消息复杂度,要是广播一个消息,需要把消息发给网络里所有人一人一份,就是O(N)的消息复杂度,而想要可靠地,在有拜占庭节点(恶意节点)存在的网络里广播一条消息的话,至少需要O(N^2)的消息复杂度,也就是说,如果网络有100个节点,如果你想让确认网络里的其他人都确实地收到你的消息,你至少要发10000条消息。这性能一看就好不了。
而比特币创新性的提出PoW概率算法思路,则很好的解决了上述问题。
首先,限制一段时间内整个网络中出现提案的个数(提高成本),其次是放宽对最终一致性确认的需求,用奖励,挖矿和最长链解决了,再大的网络也只是O(N)的消息复杂度,系统最终确认在概率意义上市存在的。
后来的各种POX系列算法的出现,如POS、DPOS、POU等等也都是沿着这个思路进行改进的,但是这里面又出现新的问题——大网络里传输效率和延迟有瓶颈,而这种瓶颈会制约可靠性。
具体而言,你广播的东西太大的话,POX系列中的那套奖励,挖矿和最长链的东西就不是那么好使了。于是,目前所有的提高scalability的方法基本上就是结合两者,也就是分层。
无论是叫分层也好,委员会选举也好,差不多想法就是我们把某一部分的可靠性用比特币的方法解决,剩下的部分用PBFT。这其实和代议制民主很像——所有人一起讨论事情太难了,那么我们让所有人选代表,然后选出来几个代表讨论事情就高效多了。
但是两部分如何对接?两个方法对于恶意节点的数量要求不一样(如PBFT必须严格少于1/3,POW的话是算力小于1/4),要不要奖励(私自挖矿算不算恶意呢?),共识类型不一样(PBFT是最终共识,POW是概率共识,也就是允许分叉)。这些都是处理起来很让人头疼的问题,基本上,所有的分层算法都得要给出这些东西。
而这个问题,无论是从学术上还是工程上都存在很高的研究价值,但是就目前而言,理想的解决方案仍不存在。在现实各种约束条件下,往往需要通过牺牲某些需求,来设计出满足特定场景的协议。
当然,随着计算机研究的不断深入,希望不久的将来能够出现一种高效、安全的共识算法,助力区块链技术能够大规模的应用到实际生活中。