FLP不可能原理和CAP原理
FLP 不可能原理(FLP impossibility):在网络可靠,存在节点失效(即便只有一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性算法。1985年 FLP 原理实际上说明对于允许节点失效情况下,纯粹异步系统无法确保一致性在有限时间内完成。 科学告诉你什么是不可能的;工程则告诉你,付出一些代价,我可以把它变成可能。
CAP 原理最早由 Eric Brewer 在 2000 年,ACM 组织的一个研讨会上提出猜想,后来 Lynch 等人进行了证明。
分布式计算系统不可能同时确保一致性(Consistency)、可用性(Availability)和分区容忍性(Partition),设计中往往需要弱化对某个特性的保证。
一致性(Consistency):任何操作应该都是原子的,发生在后面的事件能看到前面事件发生导致的结果,注意这里指的是强一致性;
可用性(Availability):在有限时间内,任何非失败节点都能应答请求;
分区容忍性(Partition):网络可能发生分区,即节点之间的通信不可保障。
弱化一致性
对结果一致性不敏感的应用,可以允许在新版本上线后过一段时间才更新成功,期间不保证一致性。
例如网站静态页面内容、实时性较弱的查询类数据库等,CouchDB、Cassandra 等为此设计。
弱化可用性
对结果一致性很敏感的应用,例如银行取款机,当系统故障时候会拒绝服务。MongoDB、Redis 等为此设计。
Paxos、Raft 等算法,主要处理这种情况。
弱化分区容忍性
现实中,网络分区出现概率减小,但较难避免。某些关系型数据库、ZooKeeper 即为此设计。
实践中,网络通过双通道等机制增强可靠性,达到高稳定的网络通信。
什么是共识Consensus?
当多个主机通过异步通讯方式组成网络集群时,这种异步网络默认是不可靠的,那么在这些不可靠主机之间复制状态需要采取一种机制,以保证每个主机的状态最终达成相同一致性状态,取得共识。
为什么认为异步网络默认是不可靠的?这是根据FLP原理。Impossibility of Distributed Consensus with One Faulty Process一文提出:在一个异步系统中我们不可能确切知道任何一台主机是否死机了,因为我们无法分清楚主机或网络的性能减慢与主机死机的区别,也就是说我们无法可靠地侦测到失败错误。但是,我们还必须确保安全可靠。
达成共识越分散的过程,其效率就越低,但满意度越高,因此也越稳定;相反,达成共识越集中的过程,效率越高,也越容易出现独裁和腐败现象。
达成共识常用的一种方法就是通过物质上的激励以对某个事件达成共识;但是这种共识存在的问题就是容易被外界其它更大的物质激励所破坏。
还有一种就是群体中的个体按照符合自身利益或整个群体利益的方向来对某个事件自发地达成共识;当然形成这种自发式的以维护群体利益为核心的共识过程还是需要时间和环境因素的,但是一旦达成这样的共识趋势,其共识结果也越稳定,越不容易被破坏。
Paxos 问题是指分布式的系统中存在故障,但不存在恶意节点场景(即可能消息丢失或重复,但无错误消息)下的共识达成问题。因为最早是1990年 Leslie Lamport 用 Paxon 岛的故事模型来进行描述而命名。
Paxos过于晦涩难懂,和难以实现,之后有出现了各种改进算法:Egalitarian Paxos、Hydra、Fast Paxos、Ios、VRR(Viewstamped Replication Revisited)、 Multi-Paxos、Raft等
Raft 算法是Paxos 算法的一种简化实现,2013年才问世。
Paxos是一种无领导人Leaderless算法,而Raft算法是一种强领导力Leadership的算法。
PBFT是Practical Byzantine Fault Tolerance的缩写,意为实用拜占庭容错算法。该算法是Miguel Castro (卡斯特罗)和Barbara Liskov(利斯科夫)在1999年提出来的,解决了原始拜占庭容错算法效率不高的问题,将算法复杂度由指数级降低到多项式级,使得拜占庭容错算法在实际系统应用中变得可行。
这个算法在保证活性和安全性的前提下提供了(n-1)/3的容错性,也就是节点数需要达到3f+1个节点才能容错f个节点。
POW工作证明
Proof of Work,工作证明相关理念最早于1993年被Cynthia Dwork和Moni Naor提出,之后的几年,该概念在是否能有效对抗拒绝服务攻击的争论中不断被人们所知。PoW机制的核心在于强迫攻击者作出一定量的工作才能进行接下来的交互操作,这样无形中就给攻击者提高了攻击的成本。自然而然的,攻击者需要完成的工作可以按消耗的计算机资源种类分为以下三大类:
消耗CPU资源。例如,反垃圾邮件的Hashcash方案以及受此启发而诞生的比特币;
消耗内存资源。例如,为了防止与比特币采用相同的共识机制所可能导致的51%攻击,以太坊目前就使用了一种需要占用大量内存资源的PoW算法;
消耗网络资源。攻击者在进行拒绝服务攻击之前,必须要获取多个远程服务器发送的命令。
POW作为数字货币的共识机制于 1998 年在 B-money 设计中提出。2008年中本聪发表比特币白皮书,比特币采用POW共识,通过计算来猜测一个数值(nonce),得以解决规定的 Hash 问题(两次SHA256)。保证在一段时间内,系统中只能出现少数合法提案。 同时,这些少量的合法提案会在网络中进行广播,收到的用户进行验证后会基于它认为的最长链上继续难题的计算。因此,系统中可能出现链的分叉(Fork),但最终会有一条链成为最长的链。
Hash 问题具有不可逆的特点,因此,目前除了暴力计算外,还没有有效的算法进行解决。反之,如果获得符合要求的 nonce,则说明在概率上是付出了对应的算力。谁的算力多,谁最先解决问题的概率就越大。 当掌握超过全网一半算力时,从概率上就能控制网络中链的走向。这也是所谓 51% 攻击的由来。
比特币POW算法的资源浪费问题
中本聪为了解决拜占庭共识问题,在比特币系统中引入竞争挖矿的机制。同时,为了保证最大可能的公平性,采用了基于哈希运算的PoW共识机制。矿工如果想要得到一个合法的区块,则必须向区块头中填入不同的随机值,然后计算出区块头的哈希值,使得得到的哈希值小于目标值。这样,矿工在不断寻找合适随机值的过程中完成了一定的工作量。可以发现,矿工完成的这个工作量对于现实社会毫无意义。唯一的意义就是保障了比特币的安全性。
这是最新的比特币历史算力曲线,现在的算力已经相当惊人,这样就意味着,后面后200多万台专业的比特币矿机在运行!!!
POS权益证明
POW算法毕竟是要靠大量资源的消耗来保证共识的达成,有没有完全不需要靠计算机资源堆砌来保证的共识机制呢?在2011年,一个名为Quantum Mechanic的数字货币爱好者在Bitcointalk论坛提出Proof-of-Stake(POS)证明机制,该机制被充分讨论之后证明具有可行性。如果说POW主要比拼算力,算力越大,挖到一个块的概率越大,POS则是比拼余额,通俗说就是自己的手里的币越多,挖到一个块的概率越大。
POS共识算法存在一个漏洞,就是鼎鼎大名的Nothing-at-Stake攻击(常写作N@S)。
假设系统中出现了两个分支链,那么对于持有币的”挖矿者“来讲,最佳的操作策略就是同时在两个分支上进行“挖矿”,这样,无论哪个分支胜出,对币种持有者来讲,都会获得本属于他的利益,即不会有利益损失。而且由于不需要算力消耗,因此PoS中在两个分支上挖矿是可行的。这导致的问题是,只要系统存在分叉,“矿工们”都会同时在这几个分支上挖矿;因此在某个情况下,发起攻击的分叉链是极有可能成功的,因为所有人也都在这个分叉链上达成了共识;而且甚至不用持有51%的币量,就可以成功发起分叉攻击。而这在PoW中是不可行的,因为挖矿需要消耗算力,矿工只能在一个分支上进行挖矿。所以在实际POS算法中,还需要加入一些惩罚机制,如果矿工被发现两个分支同时挖矿,就会进行惩罚。
其他改进共识
以上介绍到的PBFT、POW、POS和DPOS各有各的优缺点:
POW的能耗问题
POS/DPOS的中心化问题
PBFT的节点数问题
IP投票制币不够安全
NEO的dBFT
NEO采用的是 Delegated Byzantine Fault Tolerance (dBFT) 共识算法,由于它目前只有 7 个 代理节点,而代表节点则是通过用户投票选出。dBFT参与记账的是超级节点,普通节点可以看到共识过程,并同步账本信息,但不参与记账。总共n个超级节点分为一个议长和n-1个议员,议长会轮流当选。每次记账时,先有议长发起区块提案(拟记账的区块内容),一旦有至少(2n+1)/3个记账节点(议长加议员)同意了这个提案,那么这个提案就成为最终发布的区块,并且该区块是不可逆的,所有里面的交易都是百分之百确认的。
以太坊的下一代POS共识:Casper
Casper(投注共识)是一种以太坊下一代的共识机制,属于PoS。Casper的共识是按块达成的而不是像PoS那样按链达成的。
为了防止验证人在不同的世界中提供不同的投注,我们还有一个简单严格的条款:如果你有两次投注序号一样,或者说你提交了一个无法让Casper合约处理的投注,你将失去所有保证金。从这一点我们可以看出,Casper与传统的PoS不同的是Casper有惩罚机制,这样非法节点通过恶意攻击网络不仅得不到交易费,而且还面临着保证金被没收的风险。
Casper协议下的验证人需要完成出块和投注两个活动。具体如下:
出块是一个独立于其它所有事件而发生的过程:验证人收集交易,当轮到他们的出块时间时,他们就制造一个区块,签名,然后发送到网络上。投注的过程更为复杂一些。目前Casper默认的验证人策略被设计为模仿传统的拜占庭容错共识:观察其他的验证人如何投注,取33%处的值,向0或者1进一步移动。
而客户端的确认当前状态的过程如下所示:
一开始先下载所有的区块和投注,然后用上面的算法来形成自己的意见,但是不公布意见。它只要简单的按顺序在每个高度进行观察,如果一个块的概率高于0.5就处理它,否则就跳过它。在处理所有的区块之后得到的状态就可以显示为区块链的“当前状态”。客户端还可以给出对于“最终确定”的主观看法:当高度k之前的每个块,意见要么高于99.999%或者低于0.001%,那么客户端就可以认为前k个块已经最终确定。
IOTA和Byteball的DAG和相关共识
IOTA和Byteball这种基于DAG结构的分布式账本技术,从概念上讲已经不能算是区块链了,因为在底层结构上,DAG中既没有区块也不是链。IOTA中使用Tangle(缠结)这种技术,使得每个交易在发出时也见证另外两个交易。Byteball采用的是11个见证人的方式,由见证人参与共识。
HyperLedger Fabric下一代共识:SBFT
PBFT在Fabric0.6的时候被采用,但是由于一些说不清的原因,在Fabric1.0中并没有采用PBFT,而是使用Kafka进行排序,作为共识节点。在Fabric的提案中,打算会采用SBFT(Simple BFT),这种BFT算法会对PBFT进行简化,具体什么时候实现还没准呢。