分布式一致性是一个很“古典”的话题,即在分布式系统中,如何保证系统内的各个节点之间数据的一致性或可以就某个提案达成一致。这个问题想必对于不少技术同窗而言并不陌生,几乎在全部的分布式系统中都会遇到,好比hdfs、mq、zookeeper、kafka、redis、elasticsearch等。然而这个问题却历久弥新,随着分布式网络的蓬勃发展与复杂化,对于该问题解法的探索也一直在进行中。html
而近年来,随着区块链技术的兴起,特别是开放网络中的公有链与有权限网络中的联盟链的蓬勃发展,一致性问题再次获得关注,并重新的视角来审视该问题。node
本文将从传统的分布式一致性问题提及,再次重温咱们须要面对的问题挑战、已有的理论研究、以及相应的一致性算法,并简要分析这些一致性算法的适用性与局限性,以及这些传统一致性算法与崭新的区块链技术的结合。另外,将从区块链中一致性问题的全新视角“人的可信”出发,重点阐述公有链领域中的共识算法与机制。所以,本文围绕“一致性”技术问题,重点从技术视角阐述传统计算机科学中的分布式一致性算法与区块链中的共识机制的关联,以及公有链对于一致性问题的从新思考。mysql
要清楚理解分布式一致性,首先须要对分布式网络的特性有清晰的认识。那么分布式网络具备哪些特色呢?或者通俗理解,在分布式网络中,可能遇到哪些问题呢?git
故障错误(Crash Fault)很好理解,就是说分布式网络中:github
这些问题,其实就是咱们在分布式环境中最常实际遇到的问题,这些问题实质上都是因为分布式系统中的物理硬件的不可靠、不稳定所带来的必然风险,好比:网络(信道)不多是永远稳定可靠的、物理机磁盘或CPU等不多是永远良好的。故障错误能够说是分布式系统中必须考虑并解决的最基本、最多见的一类错误。redis
上文的故障错误,仍然基于一个很简单的假设:节点要么不正常工做或响应,要么能正常工做或响应,但不能口是心非、阳奉阴违、表里不一,便可以不干事、但不能干坏事。一旦网络中存在做恶节点,可能会随意篡改或伪造数据,那么一致性问题的难度就大幅增长。咱们常把这类存在“捣乱者”,可能会篡改或伪造数据或响应信息的错误,称之为拜占庭错误(Byzantine Fault),而前面所说的故障类错误也称之为非拜占庭错误。算法
拜占庭这一称呼,源于Lamport最初的论文,能够说是分布式领域最复杂、最严格的容错模型。简而言之,n个将军准备一块儿进攻某个城堡,每一个将军均可以选择进攻或是撤退,但全部将军必须行动一致才能成功。各个将军之间相隔很远,不能直接通信,必须经过信使来传递消息。可是信使并不可靠,信使可能过了好久才送到消息、可能一直也没有把消息送到、甚至可能会故意篡改消息;而将军也并不可靠,里面可能存在叛徒,并不按照提案来行动。显然,这个故事中的信使用来表明分布式网络中的不可靠信道,而将军就是各个不可靠的节点。sql
如何在充满风险与不肯定的分布式网络中,寻找到某种肯定性与一致性,使得整个分布式网络输出稳定可靠的一致性结果,就是分布式一致性算法要解决的核心问题。显而易见,解决故障类错误更容易一些,一般把这类一致性算法叫作故障容错算法(Crash Fault Tolerance)或者非拜占庭容错算法。而拜占庭类错误,由于有恶意篡改的可能性存在,复杂性更高、解决难度更大,一般把解决这类问题的算法称做拜占庭容错算法(Byzantine Fault Tolerance)。数据库
那么咱们忍不住要问,两类容错算法的界限在哪里?或者说两类错误都在什么样的场景下出现?恶意篡改这种状况真的须要考虑吗?问题的答案可能取决于咱们所处的网络环境与业务场景。安全
一般而言,若是系统处于可信的内部网络环境中,只须要考虑故障容错(CFT)可能就足够了。好比咱们常常见到的公司内的分布式存储、消息队列、分布式服务等各类分布式组件,其实只须要考虑故障容错就足够了。由于公司内整个网络是封闭的,又有多重防火墙的保护,外界很难接入或攻击;各个节点是由公司统一部署的,机器或运行的软件遭到篡改的可能性极小;此时的分布式网络环境相对“单纯”,咱们惟一的敌人只是:通讯网络与机器硬件。咱们须要考虑的是网络的延迟、不稳定,以及机器随时可能出现的宕机、故障。
而拜占庭类错误(BFT),是把整个分布式网络放到了更大的环境中去看,除了物理硬件以外,还考虑了一些“人”的因素。毕竟,机器是不会做恶的,做恶的只有人。假如咱们所处的分布式网络是较为开放的网络,好比行业内几十上百家公司组成的联盟网络;或者是彻底开放的网络,好比任何人均可以随意接入到网络中;而节点机器和上面部署的软件也是由各个公司或我的本身提供和部署的,那么若是利益足够大,极可能会有人对网络中的某个节点发起DDoS攻击、故意篡改软件代码改变其执行逻辑、甚至可能故意篡改磁盘上持久化的数据。显然,咱们此时面临的挑战更大了,咱们除了要考虑通讯网络和机器硬件的不可靠以外,还必需要考虑和应对系统中的“捣乱者”。
这些实践中遇到的问题,也引起了诸多计算科学家进行了很是多的理论研究。这些理论研究对于工程技术人员而言或许过于抽象繁琐,有些甚至是无趣的数学问题,但这些理论对于指导咱们解决这些问题意义重大。这些理论至关因而告诉了咱们这类问题解法的理论极限,以及哪些方向能够探索、哪些方向是死路一条。站在前人的肩膀上,才不至于花毕生精力去研制“永动机”。这些理论你们应该都有所了解,这里只简单回顾。
早在1985年,Fisher、Lynch、Paterson三位科学家就发表了关于分布式一致性问题的不可能定理:在彻底异步的分布式网络中,故障容错问题没法被解决。( We have shown that a natural and important problem of fault-tolerant cooperative computing cannot be solved in a totally asynchronous model of computation. )说得更直白点:在异步网络中,不可能存在可以容忍节点故障的一致性算法,哪怕只有一个节点故障。而且这里并无考虑拜占庭错误,而是假设网络很是稳定、全部的消息都能被正确传递、而且仅被传递一次,即使如此都不可能找到能容忍哪怕只有一个节点失效的一致性协议,可见该结论有多强。( In this paper, we show the surprising result that no completely asynchronous consensus protocol can tolerate even a single unannounced process death. We do not consider Byzantine failures, and we assume that the message system is reliableit delivers all messages correctly and exactly once. )
固然了,这只是理论上的。它的意义在于告诉咱们此类问题的理论极限,并不意味着此类问题在实践中也不可能被“解决”。若是咱们愿意放宽限制、作出牺牲,在工程上是能够找到切实可行的解法的。
FLP不可能定理的最大适用前提是异步网络模型。何为同步、异步模型呢?
所幸的是,咱们所处于的真实的网络世界更接近同步模型,在不少场景上,咱们均可以经过经验或采样肯定最大超时时间。举个通俗点的例子:你给朋友快递了一本书,朋友过了3天还没收到,此时朋友很难判断究竟是快递延迟了,仍是快递出问题送丢了。可是若是过了一个月,朋友仍没收到书,基本就能够判定快递送丢了。而背后的推论就是基于经验或统计:一般快递都能在1-2周内送达。显然,异步模型实际上是反映了节点间通信的最差状况、极端状况,异步模型包含了同步模型,即能在异步模型上有效的一致性协议,在同步模型上也一样有效。而同步模型是对异步模型作了修正和约束,从而使得更接近真实世界,也使得在实践中一致性问题有可能获得有效解。
另外,即使是在异步网络模型下,FLP也并不意味着一致性永远没法达成,只是说没法保证在有界的时间(in bounded time)内达成。在实践上,若是放宽对bounded time的限制,仍然是有可能找到实践中的解法的。
而根据DLS的研究,一致性算法按照网络模型能够分为三大类:
从另外一个角度来理解,FLP实际上考虑了分布式系统的3个属性:安全(safety)、活性(liveness)、容错:
FLP不可能定理其实意味着在异步网络中,不可能存在同时知足这三者的分布式一致性协议。由于分布式环境中,节点故障几乎是必然的,所以容错是必需要考虑的因素,因此FLP不可能定理就意味着一致性协议在能作到容错的状况下,没办法同时作到安全性与系统活性。一般在实践中,咱们能够作出部分牺牲,好比牺牲一部分安全性,意味着系统总能很快达成结论,但结论的可靠性不足;或者牺牲一部分系统活性,意味着系统达成的结论很是可靠,但可能长时间、甚至永远都在争论中,没法达成结论。所幸的是,不少时候现实世界的鲁棒性很强,使一致性协议失效的倒霉事件发生的几率也极可能极低。
另外,FLP并未排除Las Vegas类随机算法,许多一致性算法采用了这种随机性来规避FLP不可能定理对于肯定性异步网络的限制。此类非肯定性一致性算法涉及Las Vegas规则:网络最终必定能达成一致,可是达成一致所须要的时间多是无界的。此类算法每轮共识决策都有必定的几率,而且系统在T秒内可以达成一致的几率P随着时间T的增长而指数增加并趋近于1。事实上,该方法被许多成功的一致性算法所采用,是在FLP不可能定理笼罩下的安全地带(escape hatch),后面将会讲到比特币的共识机制就是采用了这样的方法。
众所周知、大名鼎鼎的CAP原理,从另外一个维度,简单明了、直截了当地告诉咱们:可用性、一致性与网络分区容错性这三者不可能同时实现,而只能实现任意其中的两个。( "Of three properties of shared-data systems (data consistency, system availability and tolerance to network partitions) one can only achieve two at any given time".) CAP与FLP看起来有类似之处,其实两者并不尽相同,两者是从不一样的维度思考问题,另外即便是很类似的概念,内涵也并不彻底同样。好比:
理论上,只能从CAP三者中选择二者,然而,这种选择的边界并不是是非此即彼的(not binary),不少时候混合考虑不一样程度的各个因素,结果多是更好的。( The whole spectrum in between is useful; mixing different levels of Availability and Consistency usually yields a better result.)
在实践中,咱们一般须要根据实际业务场景作折中权衡。好比:
固然,这些并非定论,各个系统都在各自不断的进化完善中,今天的结论明天可能就会被打破。更好的系统必定是不断探索适合本身的场景,找到更佳的平衡点。
面对分布式环境中各类真实、复杂的问题与挑战,基于理论上的指引,各类应对现实问题的解法也被提出。咱们这里不探究各种算法的实现细节与具体差别,仅作大致介绍,以便放到更大的维度,从总体上作比较。
最大名鼎鼎的分布式一致性算法当属Lamport提出的paxos算法,虽然其复杂性也一样“臭名昭著”。Lamport开创性地提出了一种在工程实践上切实可行的、可以最大程度地保证分布式系统一致性的机制。paxos被普遍应用在诸多分布式系统中,如Chubby、Zookeeper等。在basic paxos(单一法令,即每次仅对一个值进行决策)中有两种角色:proposer能够处理客户端请求、主动提出某个议案值;acceptor被动响应proposer发出的信息、对提案进行投票、持久化存储决策过程当中的值和状态。(为简化模型,能够忽略learner角色,不影响模型决策。)
如图所示,共识决策过程采用了两阶段提交:
Paxos之因此在实践中可行,其实也作了诸多假设和约束。从处理的问题上来看,Paxos仅能处理故障容错,并不难处理拜占庭错误,因此属于非拜占庭容错算法。从FLP的视角,Paxos作到了故障容错和安全性,但放弃了liveness(safe but not live),也就是说该算法可能永远没法结束,或者说永远没法达成共识,虽然这种可能性极小。从CAP的视角,Paxos只保证了CP,即作到了分区容错性和一致性,但弱化了可用性。有时为了加强paxos系统的可用性,能够考虑增长learner角色的数目。
即使并不完美,Paxos在实践中仍然是可靠、有效且久经考验的。Paxos本质上是异步系统的分布式一致性协议,而且在该领域具备支配地位。Chubby之父甚至声称世界上只有一种一致性算法,那就是paxos( there is only one consensus protocol, and that’s Paxos),其余一致性算法都是paxos的broken version。Paxos之因此在实践中有效是由于可能影响paxos系统liveness和可用性的条件并不容易被触发,即使真的出现,所带来的代价也可能并不是是难以接受的。
有感于Paxos的晦涩难懂,Ongaro在2014年提出了更容易理解的Raft算法。Raft把易于理解、易于工程实现提到了很高的重要级别,甚至是raft的初心和存在理由,于是在不影响功能性的前提下,尽量多地作了易于理解的精细设计。
Raft算法是leader-based的非对称模型,系统中的任意一个节点在任意时刻,只能处于leader、follower、candidate这3种状态之一。初始状态全部节点都是follower状态,follower想变成leader必须先成为candidate,而后发起选举投票;若是投票不足,则回到follower状态;若是投票过半,则成为leader;成为leader后出现故障,若故障恢复后已有新leader,则自动下台,回归follower状态。
Raft还引入了term的概念用于及时识别过时信息,相似于zookeeper中的epoch;term值单向递增,每一个term内至多一个leader;若不一样term的信息出现冲突,则以term值较大的信息为准。
Raft还采用了心跳包和超时时间,leader为了保持本身的权威,必须不停地向集群中的其余节点发送心跳包;一旦某个follow在超过了指定时间(election timeout)仍没有收到心跳包,则就认为leader已经挂掉,本身进入candidate状态,开始竞选leader。
不难发现,raft的leader选举是经过heartbeat和随机timeout时间来实现的;而日志复制(log replication)阶段是以强leadership来实现的:leader接收client的command,append到自身log中,并将log复制到其余follower;而raft对安全性的保证是经过只有leader能够决定是否commit来实现的。
详细的竞选、复制等过程,这里再也不赘述,有兴趣的同窗能够参考笔者以前的文章(https://yq.aliyun.com/articles/675031 )。值得一提的是,raft中的leader选举过程和leader任期内的正常运做过程都比较简单,复杂的实际上是leader的变动过程。
然而,虽然raft的原理机制与paxos不尽相同,但两者所解决的问题,以及所采起的折中权衡策略,能够认为是相似的。也就是说raft仍然只能解决故障错误,仍然强调了故障容错与安全性、一致性,弱化了liveness和可用性。
自从1982年Lamport提出拜占庭将军问题以后,虽然有诸多关于拜占庭容错解决方案的讨论,但长期以来,此类问题的解决方案都效率低下、运行缓慢、复杂度太高,直到1999年Castro和Liskov提出实用拜占庭容错算法(Practical Byzantine Fault Tolerance),首次将此类算法的复杂度从指数级降到了多项式级,TPS能够达到几千,也使得节点故意做恶类问题在实践中找到了可行的解法。能够证实,若是系统内做恶节点数目不超过总节点数目的1/3,PBFT算法就能生效。
在PBFT中,全部的节点被顺序编号,其中1个是leader,其他的都是backup。系统内的全部节点间都互相通信,依据多数原则达成一致。PBFT中的每轮共识都被称为一个view,而在不一样的view之间,leader都会发生变化;若是超过给定的时间,leader没有广播出消息,则leader就会经过view change协议被替换掉。经过这种replica timeout机制,保证了crashed或malicious leader会被检测出来,从而经过从新选举新的leader,而进入到新的view中。
如图所示,从客户端发起请求到收到回复结果,能够分为5个阶段,而共识过程采用了3阶段协议。下面简要叙述5个阶段的大体过程:
PBFT基于异步网络模型作到了安全性,但须要依赖消息超时时间来作周期性的同步。由于采用了leader-based方案,消息同步过程很快,也作到了彻底的顺序写入。可是leader的从新选举过程很困难,某些恶意leader能够在临近timeout窗口期时才发送消息,这样会致使系统严重缓慢。而利用这一不利特色,能够攻击网络使正确的leader看起来也出问题,从而致使无穷无尽的leader选举过程。
PBFT与Paxos、Raft相比,所能处理应对的问题更为完备,除了能应对故障崩溃类错误以外,还能处理存在“捣乱者”的恶意篡改类拜占庭错误。然而,从所采起的折中权衡策略来看,PBFT仍然与Paxos、Raft很相似。从FLP的视角来看,PBFT一样更关注容错性和安全性,而弱化了liveness。从CAP的角度,PBFT一样强调网络分区容错与一致性,而弱化了可用性。
即使如此,只要故障或做恶节点不超过总节点数的1/3,PBFT在实践中仍是有效可行的。而拜占庭容错算法(BFT)也不止PBFT一种,BFT类算法也在不断进化,如Lamport就提出过改进版的Paxos算法BFT Paxos以处理拜占庭错误,近来也有人结合PBFT与Raft提出了 BFT Raft 算法。但从问题领域与原理机制上来讲,仍然与原有的思路和框架较为相似,再也不一一赘述。
从Paxos、Raft到PBFT,再到目前层出不穷的Paxos变种、Raft变种、BFT类混合新算法,分布式一致性算法在不断发展、完善、进化。甚至各大公司也在结合本身的业务实际,研发各类适合本身场景的分布式一致性算法。这些算法虽然并不完美,但都在适合本身场景的业务实践中发挥着重大做用。那么这些算法的适用场景究竟是什么?自身又有哪些局限性呢?
对于Paxos、Raft这类非BFT算法而言,只能处理机器硬件故障,而没法处理存在做恶节点的状况。显然,这类非BFT算法只能运行在很是可信的网络环境中,好比公司内部网络中,在这样的较为封闭的网络中,访问须要严格受权,从而保证各个节点的身份是已知的、可信的,基本排除了节点做恶的可能性,这类算法才能有效运行。
而BFT类算法,对于网络环境的要求再也不那么苛刻,即便存在做恶节点,只要做恶节点数目不超过总节点数的1/3,整个系统依然是安全的。但问题就在于,你怎么知道网络中到底有多少做恶节点?做恶节点占总节点的比例到底有多高?显然,若是网络的接入是须要权限控制的,那么这个问题就相对容易解决。好比10家业务关联公司组成的联盟网络,只有这10家受权的公司才能访问,即使里面有个别公司(少于3家)蓄意做恶、妄图篡改数据,整个系统仍然是安全可靠的。在这种permissoned网络中,隐含着对于网络中可能做恶节点数目的预估,即使真的做恶了,也能方便快速地定位出其真实身份,间接提升了网络的安全性。
然而,在permissonless(开放权限、无权限控制)的公有网络中,BFT类算法极可能会有问题。由于,若是分布式网络是开放的,谁都能进进出出,而接入网络系统的成本又很低,那么没人知道网络中到底可能有多少做恶节点,即使真有做恶,也很难定位出真实身份。好比,一种比较典型的女巫攻击(Sybil attack)场景,做恶者能够经过大量伪造身份来控制集群中的大量节点,从而控制整个分布式网络。
另外,BFT类算法最大的局限性还在于仅能协调少许的节点,如几个到几十个,若节点数目成千上万,整个系统的性能将会很是低下,甚至可能没法达成共识,从而影响系统的liveness和可用性。想必你们已经注意到,在PBFT的三阶段协议中,都须要多点广播(multicast):在pre-prepare阶段,主节点向全部备节点广播;在prepare节点,备节点向其余全部节点广播;在commit阶段,各个节点向其余全部节点广播。因而可知,通信次数的数量级是节点数目的平方,当节点数目庞大时,这种两两广播的机制将会是灾难,系统几乎不可能在较短期内达成一致。
综上可知,这些传统的分布式一致性算法,不管是Paxos、Raft,仍是PBFT,一般适用于存在权限控制的、节点数目较少的、较为可信的分布式网络环境中。
事实上,这些传统的一致性算法在区块链时代也焕发了新的活力,获得了进一步的认识和使用。在网络环境较为可信的联盟链场景中,这些一致性算法获得了大量的应用。联盟链因以下特色而被业内看好其应用前景:
在当前阶段,联盟链不失为快速落地、解决行业痛点的不错选择,也是对区块链后续发展的积极探索。由于联盟链须要受权才能参与,这其实至关于已经提早创建了至关程度的信任,网络环境较为可信,网络中的恶意行为和攻击行为发生的可能性都很是低,而且即使发生也很容易快速追责。所以在这样的场景下,传统的一致性算法也能够获得应用。好比:
那么咱们忍不住要问,若是网络是彻底开放的、无需权限许可的(permissionless),谁均可以随时进出,那么整个系统还能在有限的时间内达成一致吗?若是网络中的节点数目再也不是几十个,而是一万个,那么又该如何协调这些数量庞大的节点呢?
在回答这些问题以前,其实更应该反问:为何须要网络是彻底开放、无需许可的?什么场景会须要一万个节点?这究竟是伪需求,仍是真实存在的场景?这个问题的答案直接关系到区块链中公有链的存在乎义,而要回答这个问题,咱们须要回到分布式系统的初心和目的。
咱们为何须要分布式系统?显然,这个问题不难回答,一般的理解,分布式系统能够加强容错能力(Fault tolerance),毕竟系统依赖众多不一样的节点,而众多节点同时失败的可能性远低于一个节点发生故障的可能性;另外,分布式系统还能够抵御攻击(Attack resistance),毕竟攻击或摧毁众多节点的难度远大于攻击单点的难度。
然而,以上这些依然是局限在物理硬件的维度,都是用来下降机器物理硬件发生故障的可能性,而没有考虑“人”的因素。若是一个系统足够重要,好比电子货币系统等,除了考虑机器故障以外,更多须要考虑的是人的因素。部署节点的人会不会故意做恶呢?如何防止系统内不一样节点间的腐败串通呢?
以下图所示,以太坊创始人Vitalik Buterin曾经深刻地探讨过去中心化的含义。若是说传统的分布式系统作到了architectural decentralization(系统有多少物理机器构成?系统可以容忍最多多少台机器同时故障?),考虑的是fault tolerance和attack resistance;那么如今咱们须要考虑的是如何作到political decentralization,如何可以collusion resistance? 到底有多少人或组织最终控制了系统内的节点?如何防止这些人之间的腐败串通?若是说传统的分布式系统考虑的问题是网络或机器硬件的可信,那如今咱们想考虑的是“人的可信”:是否存在这样的技术手段来防范人的做恶?如何确保重要网络中的大部分节点不被一我的或一个组织恶意控制?
值得一提的是,这个问题的必要性依然充满争议,不少人根本未曾想过、或者认为根本没有必要考虑人的腐败串通,也可能认为对于这个问题技术也无能为力,毕竟这与咱们生活的真实世界相去甚远。咱们生活在一个中心化平台拥有极高声誉、提供信用背书、控制一切规则流程的世界,好比极少有人担忧银行会故意作假帐,侵吞你在银行的资产,毕竟你们广泛认为银行是值得信赖的。若是认为银行都不可信,那极可能一切商业活动都没法开展。
然而,咱们只是“假设”银行是可信的,在“信任”与“怀疑”之间,咱们只是被迫选择了信任,毕竟不信任银行,商业活动没法开展,经济也将停滞。然而实际上,并无切实可行的措施来向全部人“证实”银行是可信的。
若是你认为这个问题是必要的、有意义的,那么可否找到一种解决方案,可让这个世界变得更可信,让你再也不须要“被迫相信”某个陌生人,而是提供一种“证实”,足以确保与你交易的某个陌生人是可信的?Don’t Trust, Please Verify. 你不须要相信我,你也没必要相信我,你只须要去验证我。
若是要解决这个问题,全部人的身份应该是对等的,每一个人均可以平等、自由地参与决策过程,每一个人均可以自由地进出“议会”,这事实上是一种技术上的democracy,隐含的技术要素是:网络必须是permissonless的,谁均可以随时加入随时离开;节点之间必须是对等的,能够直接通信;无任何中间人,无任何中心权威存在,彻底的点对点(peer to peer);每一个节点都有但愿成为记帐者。
由于网络无权限控制,彻底的开放、透明、民主,因此参与的节点数目极可能很是众多,节点做恶的可能性也很高。那如何在这种permissionless的、节点数目众多、存在较大做恶可能的分布式网络环境中,经过某种机制协调节点间的行为,保证整个系统的一致性呢?显然,如前所述的一致性算法并不能作到这一点,咱们须要寻求新的解法。
另外,去中心化多是区块链领域最充满争议的词汇。一些人认为去中心化是区块链的价值观和公有链的灵魂与存在前提,应该尽量地保证系统的去中心化程度;而另外一些人认为彻底的去中心化过于理想、不太可能实现,应该结合实际场景,在兼顾效率的状况下考虑弱中心化或多中心化。这里抛开价值判断,单纯从技术角度理性分析,去中心化程度越高确实系统的安全性会越高,因此在公有链的系统设计中确实应该尽量地保证系统的去中心化程度。不过,结合Vitalik Buterin对于去中心化含义的诠释,在追求去中心化的过程当中,咱们不该该停留在单纯的表面上看起来的去中心化,而应该综合考虑去中心化的各个维度,结合实际状况,作出必要的trade-off。
对开放网络中的分布式一致性问题比较创新的解法当属比特币中的Proof-of-work(PoW、工做量证实)机制。
2008年10月31日,中本聪发表了比特币白皮书《Bitcoin: A Peer-to-Peer Electronic Cash System》,天才般地为此类问题提供了创造性的解决思路,使得协调复杂网络环境中的成千上万节点成为可能。事实上,中本聪并非为了解决这个技术问题而发表了比特币白皮书。相反,中本聪想象的更加宏大,他创造性地发明了比特币这种彻底点对点的电子现金系统,以消除传统支付中须要依赖的可信第三方中间人,而在实现的过程当中刚好依赖并解决了开放网络中众多节点间的一致性问题。也能够说,比特币所解决的最核心问题是点对点网络中电子货币的双花问题。然而,比特币的实现机制毫不仅仅是分布式网络技术问题,还结合了密码学、经济学、博弈论等思想,并以一种非肯定性的几率方式实现了节点间的一致性。所以,单纯地称为算法已不太能准确表达其含义,可能叫做共识机制(consensus mechanism)更为恰当,由于其实现的确依赖了一整套的完整策略与制度。这里咱们不过多阐述比特币的思想意义与实现细节,而仅聚焦在其共识机制的实现上。
比特币其实是电子签名链,币的owner能够经过对前一个交易的哈希值和下一个owner的公钥进行签名,并将签名添加到币的末尾,从而实现转帐。接受者经过校验签名来验证币的owner构成的链。然而,问题是币的接受者没有办法确保币的owner没有进行双花(double-spend),即有可能某个币的owner将同一个币前后转给了两我的。所以咱们须要一种机制来让接收者确保币的前一个owner并无在此以前将币转给其余人,为了确保这一点,惟一的办法就是让全部人知晓全部的交易。而在无可信第三方的状况下,想实现这一点,全部的交易必须广播给全部人。所以咱们须要一个系统,其中的全部参与者对他们接收币的顺序达成一致,造成惟一的顺序记录历史。不难发现,这其实就是分布式一致性问题。
而比特币提供的方案就是须要一个由全部节点组成的时间戳服务器(timestamp server),时间戳服务器能够对交易区块的哈希加盖时间戳,并将该哈希广播出去。每个时间戳都在其哈希中包含了前一个时间戳,从而造成一条链,而每个新的时间戳都是对其以前全部时间戳的确保与强化。为了在点对点的网络中实现分布式的时间戳服务器,比特币采用了工做量证实机制(proof-of-work,PoW)。PoW涉及在作哈希运算时,须要寻找某个值,使得整体哈希值的开头前几位都为零,而所须要的平均工做量随着零位数目的增多而指数增长。另外,该哈希没有任何规律,为了保证开头前几位为零,只能经过暴力的方法不断地随机试错。一旦消耗了足够的CPU的算力,找到了符合条件的哈希值,则该区块就没法变动,除非再耗费CPU重作一遍。
另外,PoW也解决了大多数决策问题。在比特币中,最长的那条链就表明了大多数的决策。由于若是诚实的节点控制了大部分的算力,则诚实的链就会快速增加并超过其余链。若是想篡改某个过去的区块,攻击者必须重作相应的区块和其后面全部区块的PoW任务,而后追赶并赶超诚实的节点。这种难度是很是巨大的,从数学上不难证实,随着后续节点数目的增多,较慢的攻击者想追遇上来的几率指数降低,通常认为通过6个区块以后,想追遇上来几乎是不可能的。另外,PoW任务的难度并非固定的,而是用移动平均的方法动态调整的,这主要是考虑到硬件运算速率的提升和挖矿人数的增减变化,算的快就加大难度、算的慢就减少难度,经过动态调节难度使得比特币的出块时间大体稳定在10分钟左右。
整个网络的运行过程以下:
关于交易、挖矿等细节,这里不过多阐述,有兴趣的同窗能够参考笔者以前的入门介绍文章。简而言之,在比特币中老是以最长链的信息为准,若某个节点发现了比本身更长的链会自动切换到最长的链工做。
咱们忍不住要问,既然PoW成本如此之高,那如何激励你们贡献算力、成为节点,以保证整个比特币网络的安全呢?比特币中提供了两种激励策略:
这些激励策略也隐含地鼓励了节点保持诚实,若某个贪婪的攻击者真的拥有了过半的CPU算力,他不得不作出选择:究竟是篡改交易记录,把他已经花出去的比特币再转回来呢?仍是老老实实地挖矿赚钱新币和手续费呢?极可能,老老实实地挖矿是更有利的,毕竟能赚到的币比其余全部节点加起来都要多;而破坏比特币体系也将会破坏自身财富的有效性,毕竟若比特币再也不可靠,其价值也会迅速崩溃。这里多提一点,攻击者并不像通常人想象的那样能够随心所欲、任意篡改或伪造交易记录,他能作的只多是将其最近花出去的比特币偷回来。
比特币在没有任何组织或团体维护的状况下,仅仅依靠社区志愿者自发维护,稳定运行了10年之久,期间从未发生太重大问题,这不能不说是个奇迹,也足以证实了比特币背后共识机制的有效性。咱们忍不住要问,为何比特币可以作到?为何比特币背后的共识机制可以如此有效?bitnodes数据显示目前比特币节点数目超过1万(比特币节点类型较多,不一样口径数量可能不一致,这里仅考虑全节点)。为何比特币可以在permissionless的网络环境中,协调上万的节点保持一致性?
笔者粗浅的认为,可能有如下几个缘由:
显然,比特币的共识机制再也不拘泥于分布式算法层面,而是包含了更多经济学、博弈论、几率论等思想,所以可能叫做共识机制更为恰当。不过,咱们仍然能够将比特币的PoW共识机制放到一致性问题的框架内来思考,从FLP和CAP的角度来看:
综合来看,不难看出,比特币的PoW共识机制在FLP和CAP的限制下,作到了比较好的折中权衡,在实践中确实提供了开放复杂网络中分布式一致性问题的可行解法,比特币近十年来的稳定可靠运行也有力地证实了这一点。
另外,比特币的PoW算法也被Miller等人(https://socrates1024.s3.amazonaws.com/consensus.pdf:Anonymous Byzantine Consensus from Moderately-Hard Puzzles: A Model for Bitcoin)严谨地分析并证实:
可见,PoW算法不只在实践中可靠,在理论上也能经受考验。PoW算法采用了同步模型与随机几率来规避FLP的肯定性异步模型不可能定理。而PoW独立于网络大小的可扩展性,与PBFT算法O(n2)复杂度相比优点巨大:节点越多,系统效率并未下降,而系统却更安全。
咱们忍不住要问,PoW机制到底有何神奇之处呢?
其实,你们可能也意识到了,PoW的思想并不高深,事实上也并不是是中本聪独创。早在1993年这一思想就被提出用于对抗垃圾邮件(Pricing via Processing or Combatting Junk Mail),但直到中本聪创造比特币以前,这一思想都还没有获得普遍应用。PoW思想的精髓就在于故意制造障碍、增长参与者的成本,以尽可能下降参与者的恶意企图。好比要求请求者作些额外的工做以检测DDoS攻击、垃圾邮件等,也好比最多见的登陆网站须要输入验证码,也是为了增长登陆成本,防止网站被攻击。这类任务最核心的特征是非对称:对于服务请求者来讲,完成任务必须有必定难度;而对服务提供者来讲,验证任务必须很简单快速。对于比特币PoW而言,显然符合非对称性:不断试错,寻找使哈希符合条件的nonce(随机数)须要消耗大量算力,而验证寻找到的nonce是否符合条件只须要作一次简单的哈希运算验证便可。
比特币的PoW本质上是one-CPU-one-vote,一个CPU投一票。为何选择CPU,而不是IP地址呢?这仍然是基于任务难度考虑,如果one-IP-one-vote,则系统能够被拥有大量IP地址的人(如ip供应商)轻易控制。相对而言,至少在当时(还没有出现ASIC和FPGA)CPU仍然是比较昂贵的硬件,想拥有大量的算力(CPU+电力)并不容易。固然,这其实也隐含地为比特币的价值提供了现实锚定:虚拟的货币体系经过算力找到了现实物理世界的价值锚定,虽然在不少人看来这种算力的消耗是毫无心义、浪费能源的。
也有不少人提出如何下降比特币的挖矿成本,固然这种思考尝试有其积极意义,这种工做量证实的成本须要适宜:难度过大、成本太高确实浪费能源较多,不过比特币网络的安全性也获得了提升;难度太小、成本太低则会起不到防攻击的目的,进而也会下降比特币网络的安全性。这实际上是一个须要作tradeoff的问题,也是一个偏主观的价值判断,取决于大众对比特币的认识和定位。价值判断老是充满了主观偏见,目前对于比特币的争论如此之大,其实也正是由于社会大众还没有达成共识,还没有构建出对于比特币将来共同一致的想象。
简言之,比特币的PoW是一整套的机制,包含了技术上的权衡、经济和博弈的考量,这一整套的策略和机制共同保障了比特币网络的安全可靠。
凡事没有完美,PoW机制也不可例外地存在局限,其实从你们对比特币的诸多批评也可见一二,一般地你们认为PoW机制存在如下局限性:
在这些新的解决思路中,无疑最引人注目的就是Proof-of-stake(PoS、权益证实),一样面对开放复杂网络中的一致性问题,提出了全新的解决方案。
2011年在bitcointalk论坛一个名为QuantumMechanic的用户率先提出了proof-of-stake的思想,然后不断发展完善,获得愈来愈多人的信赖。
PoS的基本思想大体以下:
不难发现,PoS也是采用了经济和博弈的思想,经过激励策略和惩罚机制来确保了网络的安全可靠。
PoS协议仍然符合传统的拜占庭容错算法研究的结论。目前围绕PoS的研究能够分为两条主线:一条围绕同步网络模型、一条围绕部分异步网络模型。而基于链的PoS算法几乎老是依赖于同步网络模型,而且其有效性与安全性能够像PoW算法同样被严格证实。
另外,从CAP的角度来看,基于链的PoS算法与PoW算法相似,也是尽量地作到了容错性,另外在可用性与一致性之间,更多地保证了可用性。
若是说传统的一致性算法(Paxos、Raft和PBFT)实现的是肯定性的最终性(finality)或一致性,那么PoS与PoW相似,转而寻求几率性的最终一致性。从传统CAP的视角,这实际上是对一致性的弱化,然而从实践可行性的视角来看,也是一种全新的思惟和突破。
而从PoS的设计策略来看,也能够分为两大阵营:
PoS的思想并不复杂,而其中比较容易被诟病的偏偏就是这种与现实世界相似的按出资比例获取收益的制度。你们对现实世界的马太效应已经很是警戒,这种制度显然容易带来富者越富、穷者越穷的结果:拥有更多代币的人,将会有更多机会成为validator,从而参与网络并得到更多收益。
然而,对这一问题的见解争议很大,不少人提出了彻底不一样的见解,认为PoS相比PoW更公平、更有助于对抗中心化趋势。理由主要是:PoW挖矿依赖现实世界的物理硬件和电力资源,而这很容易带来规模经济(Economies of scale)优点。购买10000台矿机的公司相比购买1台矿机的我的更有议价权,甚至能够自主研发成本更低的矿机;而拥有10000台矿机的矿场,对电费的议价权也更高,甚至能够搬迁到电费便宜的国家和地区的电站旁边,甚至能够自建成本更低的电站。由此带来的后果就是越庞大的组织的综合挖矿成本越低,而这正是现实世界真实已经发生的事实。相比之下,PoS不须要依赖现实硬件,不存在规模经济优点,在不考虑价格操纵的状况下,买1个币的价格和买10000个币的价格是线性增长的,从这个角度理解,PoS可能更公平,更有助于去中心化。
对PoS的另外一个担心是其安全性,毕竟PoS再也不像PoW那样作复杂的CPU运算以证实本身。在PoW中,若想发动攻击,须要控制51%的算力(近来也有研究发现只需25%算力即有可能攻击成功),这也就意味着须要拥有大部分的矿机和算力资源。而在PoS中,若想控制整个体系,须要拥有51%的代币。究竟哪一个更安全?其实也不太好讲,不过能够从现实世界的例子来看,若是比特币算法切换为PoS,则控制比特币体系须要大约比特币市值的一半,大概是400~1600亿美金(比特币价格区间5000~20000美金),显然这一数字远远高于矿机成本,想拥有这么大资金量发动攻击几乎是不可能的,从这个角度来说,PoS可能更安全。
除此以外,PoS由于部署成本很低(对硬件要求很低),在真实世界中会致使代币很是容易分叉,从而产生一堆山寨币,而PoW不存在这个问题。由于PoW依赖硬件挖矿,若想把比特币的某个参数改改,这很容易;但真想跑起来,则须要大量算力的支持,须要争取大量miner的支持,好比bitcoin cash从bitcoin中分叉出来就历经波折。而PoS彻底没这个顾虑,随便某我的均可如下载开源代码、随意改下,拉几个节点就能够声称本身创造了一种全新的代币,好比从EOS(代币名)中能够轻易分叉出几十上百个山寨兄弟币,每一个都声称本身很独特。这确实是事实,不过也不太容易说孰好孰坏。
PoS机制中最关键的当属下一个区块validator或creator的选择机制,究竟谁来作这个幸运儿?前文所说的根据帐户资金按比例按几率选择实际上是最简单的一种方式,这种方式确实容易致使有钱人得到一劳永逸的收益,从而损害网络中其余参与者的积极性。目前有不少种思路来改善这一问题,其中比较有意思的是coin age-based方法,在选择creator的时候,除了考虑资金量,还会考虑coin age(币龄)。所谓的coin age指的是币在某个帐户上的停留时间,好比1个币转入指定帐户通过10天,能够认为币龄是10,而每次币发生变更币龄都会从0开始从新计算。经过这样,能够限制大资金量节点频繁成为creator,好比能够设定币龄达到30才有机会成为creator,而成为creator以后币龄当即清零。这实际上是限制了大参与者的利益,为其余中小参与者提供了更多的参与机会。
基于PoS改进的比较有名的方案当属Delegated Proof-of-Stake(DPoS),其中采用了代理人委托机制。在DPoS中再也不是全部节点都有可能成为creator,而是节点间相互投票,只有得票最高的一些节点才可能参与区块创造过程。具体以下:
不难发现,DPoS经过引入投票机制,尽量地保证了节点的普遍参与;而对validator数目的限制(通常是21-101个),尽量地提升了系统的运行效率。虽然充满很大争议,DPoS仍然不失为一种可行的解法,愈来愈多的区块链系统也在尝试对其进行改进和探索。
在公有链中,众多项目都采用了PoS机制,比较有名的有:
其实,PoS机制的兴起除了其自己具有的低成本、高效率、去中心化等特色以外,还在于它打开了一扇新的大门——基于博弈论机制来设计如何下降中心化风险的一系列技术,如何预防中心化垄断巨头的造成,以及在已有巨头的状况下如何防范它们损害网络( Proof of stake opens the door to a wider array of techniques that use game-theoretic mechanism design in order to better discourage centralized cartels from forming and, if they do form, from acting in ways that are harmful to the network)。
而随着近年来区块链(特别是公有链)的蓬勃发展,其余各类Proof of机制也层出不穷。从这里面的诸多机制中均可以看到PoS思想的影子,即如何从经济角度和博弈视角来设计制度尽量地保证去中心化、安全性与高效率。下面对这些机制作简要说明:
不难发现,虽然这些Proof-of机制层出不穷、不尽相同,但其要解决的核心本质问题是相同的,即:让谁来成为可以记帐的幸运儿?这些Proof-of机制只不过是采起了各类不一样的策略来制定游戏规则,让各个节点尽量公平地证实本身,从中公平地选出幸运儿。全部这些策略,包括基于CPU算力、持有代币数量、存储空间大小、随机等待时间、销毁代币数量、节点活跃度、节点贡献度等,都是在特定的场景下对于开放网络中一致性问题的探索。
从PoW到PoS,再到Proof of "Everything you can think",对于permissionless网络中的一致性问题一直在探索中。“一致性”的内涵也在发生变化,从传统的如何防范网络与机器硬件的故障,保证网络节点间的数据一致性,到开放网络中,如何防范网络中人的做恶,保证网络中节点数据间的真实一致。能够说是从硬件的可信,迈进了“人的可信”,公有链技术也被视为“信任的机器”。不过显然,人的可信问题过于复杂,甚至也超越了单纯的技术范畴。目前阶段所能作到的也远远未能保证“人的可信”,更多的仍停留在人对于机器的信任、人对于“协议”的信任。不过可喜的是,咱们终于迈出了这一步,开始直面这个棘手的问题,探索创新性的解法。
这个世界充满了不肯定性,计算机科学也同样。从计算机出现开始,咱们就不得不面对机器硬件的不肯定性:意外故障可能带来的问题。从互联网兴起开始,咱们就不得不面对网络的不肯定性:通信消息可能的延迟、乱序、丢失。而应对不肯定性问题最天然的解法就是冗余,经过大量节点来实现系统总体的安全性,避免单点故障,加强容错能力和抵御攻击的能力。正是基于此,才带来了大型分布式网络的蓬勃发展,而如何在不肯定的网络和节点间寻找到某种肯定性,协调众多节点间的一致性,正是分布式一致性算法须要解决的问题。可以应对故障类错误的CFT算法包括最经典的Paxos算法和更简单的Raft算法,能够在网络中正常节点超过一半的状况下保证算法的有效性。这类算法一般应用在环境可信的封闭网络中,协调几个到几十个节点间的一致性,如公司内部的分布式存储、分布式服务协议、分布式消息系统等。另外,也能够应用于由少数机构组成的须要受权才能访问的联盟链网络中。
然而,不肯定的不止是网络与机器自己,还有控制网络中各个节点的人的行为。如何在可能存在捣乱者恶意篡改数据或攻击网络的状况下,保证分布式网络的一致性,正是拜占庭容错类算法BFT须要考虑的问题。BFT类算法中最多见的就是PBFT算法,能够在网络中正常节点超过1/3的状况下保证算法的有效性。即使如此,PBFT对于网络中恶意行为的应对能力仍然是有限的,另外其性能也会随着网络中节点数目的增多而显著降低。这些局限性也致使PBFT算法仅能用于环境较为可信的、有权限控制的网络中,协调几个到几十个节点间的一致性,好比联盟链场景中。
而在无权限控制的permissionless开放网络中,不肯定性更加严峻,特别是网络节点背后的人的行为的不肯定性。如何防止网络中的控制人之间经过腐败串通组成寡头,从而控制网络中的过半节点,达到控制、损害、攻击网络的目的,便是开放网络须要考虑的问题。从这一角度看,开放网络中的一致性还隐含了安全性的前提:即不只要求节点间可以达成共识,还要求该共识确实是由节点众多控制人真实表达而造成的。而为了达到这种一致性与安全性,不只须要实现物理硬件节点在结构上的decentralization,还须要尽量地保证节点背后实际控制人的decentralization。为了实现这一点,须要保证任何人均可以随时部署运行网络协议而成为网络中的节点、能够随时进出网络;节点之间点对点通信,无任何中心化控制节点;节点的角色是彻底对等的,按照规则有公平的可能性参与记帐。而如何协调开放网络中数量庞大的上万个节点间的行为,保证网络的一致性与安全性,便是公有链共识机制要解决的问题。其中,最典型的当属比特币独创的基于工做量证实的PoW共识机制,以及随后兴起的基于权益证实的PoS共识机制。这些共识机制再也不局限于技术上的一致性自己,而是更多地引入了经济学和博弈论的思想,从经济和博弈的角度尽量保证网络的一致性与安全性。
从传统的封闭分布式网络环境中的一致性,到有权限控制的联盟链场景中的一致性,再到无权限控制的公有链开放网络环境中的共识机制,面对的问题愈来愈复杂,应对的挑战也愈来愈严峻。从单纯的技术视角来看,其中对于consensus的研究是一脉相承的,这些一致性算法或共识机制一样也都受到传统分布式一致性理论研究中FLP impossibility和CAP theorem的制约。Paxos、Raft和PBFT都强调了fault tolerance与safety/consistency,而弱化了liveness与availability。而PoW与PoS则采用了全新的视角来考虑该问题,尽量地保证了fault tolerance,以及liveness与availability,放弃了对于安全性与一致性肯定性的追求,而仅仅以几率性的方式追求最终的safety与consistency。
另外,对于consensus的思考,也在不断深刻,从单纯的节点间的数据一致性,到强调节点背后的人之间的共识与认同;从保证网络与硬件的可信,到尽量地确保组成网络的节点背后的人的可信。虽然人与人之间的可信很是复杂,也超越了单纯的技术范畴,可喜的是咱们已经走在路上,而目前在该领域正在进行的创新性的积极探索,也必将让世界变得更加可信。
原文连接 本文为云栖社区原创内容,未经容许不得转载。