井然有序,就得等到没有分区--分布式系统
区块链的世界里,常常会看到认知的新边边界,这让我们不得不用类比这样的方法才能高效地溶解新知。还没开学,你就被拉去操场军训。教官喊:向右看齐。除非你是排头兵,否则多少要踩出些小碎步,给他点面子。教官只向
区块链的世界里,常常会看到认知的新边边界,这让我们不得不用类比这样的方法才能高效地溶解新知。
还没开学,你就被拉去操场军训。教官喊:向右看齐。除非你是排头兵,否则多少要踩出些小碎步,给他点面子。教官只向你发出看齐指令,但如何对齐的命令实际来自你右边战友的耳根。
两周后的你精疲力尽,全班的耳根都被晒黑,但每天第一把向右看齐,总要扑腾好多次。教官照常数落你们:这半个月都练了什么,为什么老是不能马上排齐?
如果你能掐会打,完全可以怼教官:队伍本身作为一个分布式系统,能马上排齐那叫奇怪,因为有CAP定理。
什么是CAP定理?
分布式系统中,必然无法同时满足一致性、可用性和分区容忍性。
分布式系统指一组电脑连成的网络。
一致性(Consistency,简称C)指同一时刻全网数据完全一致,相当于军训队伍整齐划一,越整齐一致性就越高。
可用性(Availability,简称A)一部分节点更新数据后,分布式系统能基于最新数据响应用户读写请求。排头兵挪动后,没跟上的队伍走样越小、排齐耗时越少,可用性就越高。
分区容忍性(Partition Tolerance,简称P)只有两个可选参数:不容忍和容忍。
不容忍分区好比你一个人在word里打字,无需穿行网络,一台电脑全盘搞定;容忍分区就是分布式系统,至少有两台计算机联机组成,比如你保存word文档的瞬间,如果我的电脑没和你交互,就读不到你刚写的文字。
CAP定理意思是:C、A、P三者最多得二。
具体来说:分布式系统必然容忍分区(P),所以一致性(C)与可用性(A)注定互斥。如果你想左拥右抱C和A,那就别指望分布式系统,只能用单机版的中心化方式(不容忍分区,无P)。
但是,分布式系统中C和A的不可兼得,与中文语境下鱼和熊掌的不可兼得不同。CAP定理是说:一条队伍永远存在可能不齐的瞬间。这看着像句废话,但只有理解这点,才能避免对CAP原理最习以为常的误解:现在不齐,所以永远无法整齐。
你不是教官脑中的提线木偶,不会根据教官意念自动排齐。排头兵一个喷嚏把自己打出去半步,二号兵才能开始反应,跟出瞄齐,而他脖子位置的变化向三号兵发出指令:来,跟上。
最后才轮到你,怎么可能快?所有人的反应时间之外,还要加上挪步用时,于是耗时必然大于零。
映射到分布式系统:如果想要严格一致的数据,那分布式系统就没法用了,因为你无法确保使用数据的瞬间,网络中其他节点不会更新数据;如果你想用相对新的数据,那就得候着。
所以,分布式系统天生就慢。
这种慢,更像是迟钝,原因很简单:分布式系统范围一大,节点间的通信耗时就长。
如果你想获得可靠的最新信息,就得等所有节点汇集出最新数据,这样能保住一致性、放弃可用性。可如果你说全网这么多节点,等到什么时候才能一致?CAP原理告诉你:别等了,你就放弃点一致性,先用着吧,否则你啥也用不了。
开学前,你被拉到操场军训。教官喊道:向右看。除非你是急先锋,否则你得采取一些小步骤,给他点面子。教官只给你对准指令,但怎么对准的指令其实是从右边战友的耳朵里发出来的。
两周后,你筋疲力尽,全班同学的耳朵都晒黑了。但是每天第一对都是右对齐的,你总是要扑很多次。教官照常骂你:这半个月你都练了什么?为什么总是不能马上安排好?
如果能掐能打,完全可以打得过教官:作为分布式系统,队伍本身能马上排好队就很奇怪了,因为有上限定理。
什么是CAP定理?
在分布式系统中,一致性、可用性和分区容忍度是不能同时满足的。
2000年加州大学伯克利分校计算机教授布鲁尔提出了CAP的三选二猜想,两年后被麻省理工学院的两位教授基尔伯特和林奇证明。
他们的反证法让证明过程出奇地简单:
假设存在一个算法同时满足一致性、可用性和分区容忍性,那么在两个节点的网络中,存储的信息分为不相关的非空集合{G和G'},假设G和G'间没有通信,那么,一个节点读的操作将无法访问另一节点稍早前写的结果。
类比一个你熟悉的场景:
妈妈和儿子一起把两只蛋关进冰箱,妈妈回房看电视,儿子一饿之下把蛋全煮了扒光吃尽,此时爸爸在房里问妈妈:冰箱里还有多少蛋?
妈妈关上房门的刹那,本来共享的鸡蛋余额数据就发生了分区。
如果妈妈追求严格一致性,那她应该跑去冰箱检查余额后再答复爸爸,可妈妈追起剧来特别专注,所以直接回答:还有两个。这个回复没有基于准确的最新余额,但为了可用,放弃了一致。
可这并不影响爸爸第二天就去超市买蛋,因为不管零个蛋还是两个蛋,都不够全家吃。
所以,一致性并非不可放弃,只是需要权衡。放弃追求一致性,就能少打断一次电视剧情,少跑一个来回所增加的便利,如果大于因为蛋数认定不一致带来的不便,那不一致就不一致吧。
这是很简单的取舍,但正如“去中心”常被人们误解为“去掉所有中心”一样,人们也常常误读CAP定理中“三者只能居其二”的含义:
CAP定理的确告诉我们:分布式系统中抓走可用性就意味着放手一致性,但并不说明用户想要的一致性被冲进了马桶,再也捞不回来。真实情况是,我们可以在短时间内追回些一致性,就像经过严格训练的队伍可以比普通队伍用更短的时间排齐一样。
很可惜,即使我们只用一刹那的时间就能追回先前所有的不一致,我们也没有办法追回这一刹那本身所产生的不一致,这是分布式系统命中注定的无奈。
但这只是CAP定理在理论上的陈辞,实际场景中我们需要关注的是如何在C、A之间权衡利弊,最终获得最大的经济收益。在这方面,银行业贡献给我们两个案例:
ATM机和支票
设计ATM时,强一致性是必然选择,因为算不清楚钱对银行来说是件很丢脸的事情。可实际场景中,对可用性的渴求却超越了一致性,银行的理由很直白:更高的可用性意味着更高的收入。
ATM有三个基本功能:存钱、取钱、查余额。无论发生什么,只有一个规则必须遵守:用户借记卡余额不得小于零。
考虑到存款或余额查询都不能打破这条戒律,我们可以放弃一致性,照顾更多的可用性:我们可以随时存款,虽然存款后的余额不能马上扩散到全网;您可以随时查看余额,尽管屏幕上显示的余额可能不是最新鲜、最准确的。
只有取款操作会被区别对待。
银行本可以在分区制发生时选择禁止取款,因为他们无法知道准确的余额。但如果他们坚持这样,会扭伤用户的感情,所以权衡之后只能放手。
银行可以做两件事:一是提高内部通信速度,减少节点间的通信时间;二是设置限额,比如单笔最高5000。
当提现低于限额时,无需拘泥于严格的一致性。让用户根据当前余额取钱是考虑周到的,即使余额不是最新最准确的。所以用户可以及时取钱,银行可以承担风险。
你一定看到了,这是放弃了用户随时获取借记卡内所有余额的可用性,转而去捕捉另一种可用性:能够随时取出零用现金,因为后一种可用性对双方都更有价值。
内部通信完全完成,分区结束,全网信息最终一致。如果发现此时任何一个用户的余额小于零,银行就会开始补。
可用户通常并非恶意。比如账户余额6000元时,用户父母在老家柜面用存折取出4000,此刻余额应是2000,但此余额信息尚未在分布式网络中传播开,用户当时在外地ATM机上本想取300,结果多按了一个零,如果ATM机依据非最新的余额,会吐出3000块钱,那银行就担着1000元的风险。
银行一般会好意通知用户,如果不还只能认栽,可因为概率低损失小,所以没什么了不起,而且银行也会收点费用,就算存取款都免费,每台ATM机还在扮演广告牌机的角色,7×24小时地为银行高大上的形象加油充电。
总之,ATM能用就好。
另外一个例子是支票。
作者十年前做柜员时,支票只能在开户网点使用,这是银行单方面选择一致性的结果,能彻底避免银行自己吃到空头支票。
后来为提升用户体验,支票在全市任意网点都能用,唯一的代价是支票没有一般业务利索,总会遇到卡顿,这是因为系统想要咬出更多的一致性。
在分布式场景应用最密集的区块链世界,全网共享一致的最新数据是普通用户的诉求,但普通用户和教官一样,不太可能听说过CAP定理,一时半会无法理解必须折损可用性的事实。
用户不理解不代表问题不存在,于是各路商业精英纷纷出动,对注定丢失的可用性围追堵截,集中体现在对共识算法的设计上。
各显其能的共识算法
十年前,作为一个分布式应用,比特币悄无声息地降生。长大之后,大家被它的慢条斯理震惊了,连小卖部老板都看不起它,买包牛肉干这种小事都要等上一个小时。
比特币的慢是有道理的,道理就是CAP定理:为了在一个分布式系统内追求全网账本的严苛一致,可用性理所当然地被牺牲,所以只能闷等,直到交易信息被深深刻进链上,老板才敢把牛肉干交付客户。
速度方面,比特币的用户体验低落到极致,但以此为代价能坚守全网账本信息一致,最终保证系统安全,那这点慢就忍了吧。
先天的迟钝性毕竟不是先天性心脏病,但各路英雄为解决这一缺陷都曾脑浆沸腾,主要落实到两个方案上:
一是拓宽渠道:把原来双车道改成八车道,这样单位时间内能承载更多的信息流,这种方案的结晶分叉出了比特币现金BCH。
二是离线交易:矿工忙的时候不会例会压箱底的那堆小额交易,这是因为手续费激励不足导致的动力不够,那高频小额交易就由“小银行”帮你划转了吧,你就省钱省心吧,这种方案的结晶就是闪电网络。
比特币、BCH和闪电网络三者都没有违背CAP原理,后两者在比特币原有的严格一致性上给予用户更多可用性,但在更大交易量的冲击下,可用性和安全性是否会变形,还要让时间去考验它们。
保证比特币一致性的共识算法是POW,起点思路在于追求完美的一致性,于是只能牺牲很多的可用性。POW发动全网矿工边记账边猜数,猜到才能奖到,于是猜数字的算力逐渐演化为系统内的权力。
最终这种格局牢不可破,因为通过军训你也明白了同样的道理:面对强权只能服从。
后来发展出大家围坐一起客客气气的POS共识算法,系统挑出一些区块生产者,去掉POW的猜随机数环节,产生的区块交给符合条件的持币者验证上链。
这大大降低了达成一致所需的时间,可代价却藏在另外的角落里。一些POS算法会产生一个反直觉的结果:一个块可以在其后的块都最终确定后,依然处于未确认的状态,这样可能会折损系统层面的安全或稳定。
没有足够的时间验证,所以还没有定论。
POS之后,又降生了DPOS。所有持币者天然都有等比例的投票权,以此选出一定数量的区块生产者,不称职的生产者可被投出局,以此确保全系统的高效安全稳定。
从Steemit和Bitshares两个分布式应用顺利运行一到三年的结果来看,DPOS是当前扩展区块链最出挑的共识算法。但它依然无法跳出CAP定理的五指山:再快的DPOS也无法在当下瞬间反馈全网其他节点的最新状态。
重回我们的军训场景,教官让你前后左右地转,不是让你晒得更均匀,而是让你更加习惯服从,让你不经思考、用神经反射回应他的口令。
你看,多军训的确可以让队伍更快排齐,但代价是你可能会逐渐失去深入思考的习惯,你会得意于教官嘴里那条廉价的表扬,但另外那一条条简单的口令,是我们这代人无处可逃、但要深深警惕的教导。
面对越来越复杂的世界,我们不能不保持深入思考。
结语
作为科学,CAP定理宣判了分布式系统天生的残缺,但工程学站出来说,我们可以在科学划出了白线上向外再凸两步。即使CAP定理将一直都在,用把力也许能让一般用户感觉不到这根天条的存在。
实际场景中需要思考的是:牺牲的一致性能获得多大的可用性,于是问题最终变成架在损益天平上的权衡。
权衡就是比大小,日常生活中,我们常常会用一点不那么要紧的代价,换得非常耀眼的好处。用做数学题的手法去做每个决策,看着很累,可一旦形成习惯就会给人生增色,因为你的决策系统会发生跃迁。
权衡是基于边际效用的决策思维,可以让你摆脱非黑即白的传统视野,帮你站到高处,理解原本思路的局促。
区块链的世界里,常常会看到认知的新边边界,这让我们不得不用类比这样的方法才能高效地溶解新知。我们专栏的风格也一贯如此:站在知识的精准性和可理解性两端左攀右比,让你能用最少的耗时溶解新知。
然而,类比本身并非最好,因为像的意思是不是。不带成见地观察、不失理性地校正,才是最好的学习方式。
——和菜头
我们不应该忘记和菜头的提醒,类比最终只是追求可用性的折衷,我们必须寻找更多方式和区块链世界的成长,保持一致。