当前位置: 首页 > 科技观察

区块链技术的起源与演进(下):HyperledgerFabric与分布式联盟数据库

时间:2023-03-18 01:25:24 科技观察

【.com原稿】前言说起当今最具代表性的数据通信技术,区块链无疑榜上有名。区块链作为当下最受关注的下一代分布式系统,可以说是众说纷纭,众说纷纭。有人将其视为引爆下一次互联网技术革命的突破口,也有人将其称为投机工具、惊天骗局。本文旨在尽可能地悬置那些技术层面之外的价值判断,将视角转回到区块链技术本身,完整追溯区块链1.0到3.0的技术原理和设计理念的演进。揭开笼罩在区块链上的神秘面纱。第二章HyperledgerFabric和分布式联盟数据库在上一章中,已经详细介绍了基于区块链1.0设计的比特币电子记账系统。没有接入机制和POW算法使得比特币兼具网络开放性和数据安全性。但是,POW算法的高计算开销也极大地限制了区块链网络的数据处理效率。区块链技术不仅可以应用于电子记账,还可以广泛应用于金融、安防等对数据安全高度敏感的领域。在强大的技术需求驱动下,一个为企业间信息共享量身定制的区块链项目应运而生。这就是Linux基金会旗下著名的HyperledgerFabric项目。一、HyperledgerFabric的技术背景HyperledgerFabric是Linux基金会主导的Hyperledger项目之一。除了Fabric,Hyperledger生态系统还包括Burrow、Sawtooth(以太坊扩容项目)、Indy(数字身份平台)等专业项目。不同于比特币网络的公链设计,Hyperledger采用了联盟链架构内外网隔离和业务接入,在区块链1.0网络架构的基础上进一步形成节点角色的分化。这样的设计避免了企业内部数据泄露的风险,同时尽可能的杜绝了潜在的安全风险。HyperledgerFabric是基于谷歌的gRPC框架开发的,它可以实现网络中任意节点之间的点对点通信。同时,使用Docker容器技术来承载构成基本交互逻辑的智能合约。简而言之,HyperledgerFabric是一个专门为企事业单位设计的通用业务系统。二、HyperledgerFabric的数据结构1.HyperledgerFabric的区块链结构图14:HyperledgerFabric的区块链结构HyperledgerFabric的区块链结构与比特币的区块链结构大致相同。每个区块由一个区块头和一个区块组成,并通过父区块的哈希码唯一链接。但HyperledgerFabric在区块链1.0的基础上进一步增加了一层状态缓存设计,以提高读写性能。与比特币网络一样,HyperledgerFabric本质上是一个分布式账本(HyperledgerFabric的账本交互逻辑可以由用户根据自己的业务进行定制,数据存储的灵活性优于区块链1.0系统)。在底层结构中,数据以键值对的形式存储。为了实现数据的时间溯源和数据的防篡改机制,区块链不保存数据在链上的状态,只保存数据的变化。这使得查询一条数据的状态需要遍历整条链,其查询性能难以满足一些企业级业务的性能需求。因此,HyperledgerFabric引入了“世界状态(WorldState)”的概念。当区块中保存一条记录时,相应Key的世界状态会同步更新。当需要查询某个键值时,只需要查询对应的世界状态即可,无需遍历整条链。需要强调的是,世界状态是链下存储在LevelDB/CouchDB结构中的,这是一种额外的链外缓存机制。世界状态的丢失不会影响区块链中的数据。2.HyperledgerFabric账本结构当网络中的排序节点将最新的区块打包分发到各个账本节点时,账本节点会更新本地区块链数据,其账本存储结构如下图所示:图15:HyperledgerFabric的账本结构首先,每个记账节点保存所有的历史区块信息。块以文件系统的形式存储,多个块以集合的形式存储在一个文件块中。区块链通过文件号、区块号、偏移量实现对历史区块的快速索引。区块链数据也是记账节点中唯一的持久化数据,永久保存,不可更改。某个块被硬编码为64M大小,用六位代码区分。理论上,单条链最多可以容纳64*1000000M的数据。当写入新的区块请求时,记账节点会先将新区块添加到本地区块链,然后将数据同步到状态数据库(世界状态是当前数据的最终状态,即原始状态+区块链中所有交易操作叠加后的最终状态)。每个节点在启动时,首先会检查区块链中的数据、世界状态、关键历史索引是否一致。如果没有,可以通过区块链信息重建状态数据库。当然,从创世块中重构世界状态的性能开销往往非常高,因此HyperledgerFabric增加了一个额外的历史状态模块,它记录了世界状态中每个键值对的操作(交易请求)编码,重构键值对时,只需要从区块链中过滤出对应的交易请求执行即可,无需遍历整个区块链)。3.HyperledgerFabric的读写集机制读写集是HyperledgerFabric数据更新所依赖的核心技术。背书节点在进行交易模拟时,会对交易请求进行验证。读写集分为读集(读取提交的状态值)和写集(要更新的状态键值对,状态键值对删除标记,如果多次更新同一个键值对,最后一个为准))。在进行交易验证时,对于更新操作,只有当读集版本号=世界状态版本号时,才会执行写集。写入集中每更新一次键值对,键值对的版本号也会同时更新。这样设计的目的是为了保证同一个区块中的多个事务不会引起对世界状态的重复操作(类似于Redis的乐观锁机制)。比如世界状态中有某个键值对(A,100,V1)。此时两个时间相似的交易请求被打包到同一个区块中执行:请求1:读取A的值为100后,执行扣减50的操作;请求2:读取A的值为100,执行减20操作;当请求1执行时,世界状态更新为(A,50,V2),此时如果执行请求2,仍然会按照之前读取的(A,100,V1)的世界状态进行操作.操作后世界状态更新为(A,80,V2),然后擦除request1的操作。所以版本校验的目的是避免高并发情况下出现数据丢失。三、实用拜占庭容错(PracticalByzantineFaultTolerance)1、PBFT的基本模型在上一篇文章中,我们介绍了分布式系统必须面对的数据一致性问题——拜占庭将军问题。区块链1.0的网络架构主要通过POW算法实现全网共识,通过强制记账节点以实物费用换取记账权来避免作弊。但是,POW算法的解谜设计也造成了大量的资源浪费,大量的算力被浪费在没有实际意义的数字谜题上。HyperledgerFabric作为联盟链,更侧重于满足企业分布式数据存储和数据共享需求,因此性能成为网络架构设计层面不得不考虑的问题。HyperledgerFabric在区块链1.0的基础上引入了网络访问机制。只有授权的节点才能访问区块链中的数据。节点数量远小于公链系统。POW不再适合联盟链系统的设计。发展。因此,HyperledgerFabric采用了一种成本更低、性能更高的共识算法——“实用拜占庭容错算法(PBFT)”。LeslieLambert提出的BFT算法只是从理论上证明了拜占庭容错的可行性,但在实际的分布式系统设计中,由于网络阻塞等原因,BFT算法很难得到应用。因此,在BFT的基础上,Castro、Miguel和BarbaraLiskov三位计算机科学家进一步提出了一种可以在实践中使用的PBFT算法。PBFT算法首先区分了分布式系统的三种基本模型:强同步(Synchrony)模型,任意节点发送的消息都可以在一定时间内投递到目标节点。强异步(Asynchrony)模型,任何节点发送的任何消息都可能无法到达目标节点。弱同步(PartialSynchrony)模型,任何节点发送的消息最终都会在可能的延迟范围内到达目标节点。强同步和强异步模型设置的条件过于极端,实际分布式系统中的情况更接近于弱同步模型。PBFT算法是基于弱同步模型设计的,即消息可能会延迟,但不会无限延迟。假设分布式网络中有F个故障/恶意节点,节点总数为N,在弱同步模型中,PBFT需要保证两点:当一个节点收到一条消息时,考虑到最多可能有F节点保持静默状态,所以当收到N-F个消息时,就会开始校验,N-F个消息中至少要有超过F个消息一致才能完成容错判断。因此,N和F需要满足:N-F>F另外,N-F消息可能包含F条来自恶意节点的虚假消息,所以真实消息的数量至少要多于F才能完成容错判断,所以N和F需要满足:N-F-F>F总结:因此,当恶意/故障节点不超过总结点数的1/3时,PBFT算法可以实现全局一致性。2.PBFT网络拓扑模型图16:PBFT网络拓扑模型PBFT实现的分布式网络需要满足两个条件:每个节点的初始状态相同;在相同的状态下,相同的操作产生相同的结果。在使用PBFT算法实现的分布式网络中,选择一组节点中的一个节点作为主节点(Primary),其他节点作为备份节点(Backup)。选择一个节点作为主节点的状态称为系统的视图(View)。当主节点出现故障时,会重新选举主节点,当主节点发生变化时,就认为系统的视图更新了一次。假设网络约定了某个消息m在View1视图下的排序n,即Order?view1,m,n?,那么视图更新后,m的排序仍然是Order?view2,m,n?,即视图转换前后的消息顺序不会改变。3.PBFT消息处理流程图十七:PBFT消息处理流程PBFT消息处理流程大致分为请求(Request)、预处理(Pre-prepare)、准备(Prepare)、提交(Commit)、响应(Reply)五种阶段。我们通过一个四节点一个客户端的简单网络模型来说明PBFT信息传输验证过程:在这个网络模型中,Primary节点和Backup1、Backup2节点都是正常节点,Backup3节点没有响应。满足N>3F的要求。首先在Request阶段,Client向Primary发送请求,消息格式为:其中o代表操作请求的内容,t代表当前时间戳,c代表Client节点。当Primary收到并验证消息后,进入Pre-prepare阶段。Primary赋予消息m一个序号n,并将预处理消息广播给Backup1、Backup2、Backup3。消息的格式为:其中v代表当前系统视图,n为消息排序,m为消息内容,d为消息m的哈希值。当Backup1和Backup2节点收到Primary节点的消息时,会先验证系统视图是否更新,消息签名是否合法,sortn是否在当前视图的高低水位之间(为了保证n没有最大值或最小值,在同一个视图下,系统会限制n的取值范围,使得n∈(h,H)),以及是否收到其他消息排序按n(以确保不同的消息不会得到相同的排序)。验证通过后,进入PREPARE阶段,节点会向其他节点(包括Primary节点)发送准备消息,并将消息存储在本地日志中,消息格式为:其中i代表当前节点。其他节点收到消息后,会进行如下检查,并将消息存入本地日志:第一步,检查本地日志中是否存在消息m。第二步,查看本地日志中是否有m的PRE-PREPARE消息。第三步,查看本地日志中是否至少有2F条关于m的PREPARE消息。如果验证通过,则称该节点已达到消息m的PREPARED状态。此时节点会广播给其他节点,消息格式为:当其他节点收到COMMIT消息后,会进行如下检查,并将消息保存在本地日志中:第一步,检查节点是否收到消息m达到PREPARED状态。第二步检查本地日志中是否至少有2F条来自其他节点的关于m的COMMIT消息。如果验证通过,则意味着m的排序已经达成全局共识。此时,节点对于消息m就说已经到达COMMITTED-LOCAL(m,v,n,i)状态,可以直接返回给Client。消息格式为:其中r和t相同,用于时间验证。当Client收到F+1条一致的REPLY消息时,共识过程结束。图18:节点本地日志库的状态迁移图为了更直观的理解这个过程,我们制作了各节点本地日志库的状态迁移图。蓝色标记的消息由节点自身产生,绿色标记的消息来自其他节点。首先Client发送REQUEST消息,保存在Primary的日志库中。然后Primary向Backup1、Backup2、Backup3发送PRE-PREPARE消息。Backup1和Backup2分别将PRE-PREPARE消息保存在logstore中。然后向其他节点发送PREPARE消息。Primary从Backup1和Backup2收到两条PREPARE消息,保存在日志库中。Backup1和Backup2除了自己产生的PREPARE消息外,还会收到来自其他节点的PREPARE消息。此时三个正常节点的日志库都满足了:有一条消息m的日志;有消息m的PRE-PREPARE日志;有消息m的2FPREPARE日志。此时三个节点都已经达到m的PREPARED状态,然后向其他节点发送COMMIT消息。从图中可以看出,三个正常节点除了自己产生一条COMMIT消息外,还收到了两条来自其他节点的COMMIT消息,并且都进入了COMMITTED状态,向客户端返回一条REPLY消息,完成共识过程。4.PBFT的垃圾回收机制PBFT算法对信息的周期性验证需要使用节点的日志库。随着信息的增多,日志库中的冗余数据会越来越多。因此,PBFT会通过定期的Garbagecollection来释放内存空间。PBFT垃圾回收是通过Checkpoint机制完成的。Checkpoint设置是某个常数K的整数倍。假设当前消息排序值n的范围是h到H。当排序的消息数超过H时,节点将发送CHECKPOINT消息。消息格式为:当节点收到2F+1CHECKPOINT消息后,将高低水位重置为n∈(H,H+K),排序值小于H的消息记录将被删除以释放内存空间。5.PBFT的视图更新机制由于PBFT是通过主节点完成消息的排序,因此存在主节点故障的风险。为此,PBFT设计了相应的视图更新机制,以保证在主节点故障时整个系统的可用性。当节点i检测到主节点响应超时,进入视图更新流程,发送VIEWCHANGE消息。消息格式为:其中n为最新Checkpoint的序号,C为对应的2F+1CHECKPOINT消息集。P是一组达到PREPARED状态的消息:Pm表示一组至少有1条PRE-PREPARE消息和至少2F条序列号大于n的消息m的PREPARE消息达到PREPARED状态(即所有使消息m达到PREPARED状态的预置消息(处理消息和准备消息的集合)。当新的主节点Primaryv+1收到2F条有效的VIEWCHANGE消息时,会广播一条新的View消息,消息格式为:其中V是Primaryv+1收到的所有VIEWCHANGE消息的集合,O用新的构造viewPRE-PREPARE消息的集合,至此视图更新过程结束。这种机制有效的保证了PREPARED状态的消息在视图更新前后的顺序不变。4.HyperledgerFabric的网络拓扑和共识机制HyperledgerFabric使用PBFT作为其共识算法的底层实现。对于分布式系统,数据一致性策略可以分为强一致性策略和最终一致性策略。所谓强一致性策略是指系统能够在极端条件下实现数据一致性,涉及到复杂的数据交互,给系统带来很大的压力,因此不适合商业级的数据存储。因此,HyperledgerFabric采用最终一致性策略。所谓最终一致性,是指系统能够在短时间内容忍不同节点之间的数据不一致。整个区块链网络只需要保证在一定时间内达成共识即可。图19:HyperledgerFabric的网络拓扑如图所示。HyperledgerFabric采用多中心网络架构模型,独立的排序节点定时处理来自不同终端的交易请求,然后将其封装成块,再发送到整个区块链网络。HyperledgerFabric网络下主要有四类节点:客户端节点(clientnode),主要用于为应用程序提供访问区块链网络的入口,负责系统与区块链的数据交互。Peer节点包括Anchor节点(锚节点)、Endorser节点(背书节点)和Committer节点(记账节点)。每个组织最多有一个锚节点,负责与其他组织和订单节点进行交互。组织网络中的非锚节点不直接参与与外部网络的信息交互。背书节点负责模拟用户交易请求的执行,并对请求进行验证和签名。记账节点负责保存区块链信息,更新世界状态等。需要强调的是,这三个角色并不相互排斥。一个Peer节点可能同时具有背书节点和记账节点等多种角色,所有Peer节点都是记账节点。订单节点是共识机制的核心节点,负责对用户的交易请求进行排序,打包成块分发给其他组织的锚定节点。CA节点(authenticationnode),非必要节点,主要负责证书颁发、身份验证和用户认证。也可以通过第三方证书认证机构来实现。就HyperledgerFabric的网络拓扑结构而言,它不同于比特币、以太坊等常见公链的网状拓扑结构,而是更接近树形拓扑结构,具有一定的层次关系(在这一点上,HyperledgerFabric不是一个去中心化网络,而是多中心网络)。不同的组织属于不同的网络域,每个组织结构下只暴露一个锚节点作为与其他组织交互的接口。这样的设计主要是出于一些企业的数据安全考虑。很多企业的核心数据往往不方便直接暴露在公网中。内外网隔离设计,充分保证敏感数据的安全。除了不同的组织,区块链网络中还有一个由Order节点组成的排序网络。订单节点有两种运行模式:Solo和Kafka。Solo模式由单个Order节点提供排序服务,通常只用于网络测试和节点数量较少的场景。在商业应用中,一般采用Kafka模式。Order节点将接收到的事务请求发送给Kafka集群,Kafka集群对请求进行排序后返回给Order节点。这种设计大大提高了Order集群的排序和分发效率。图20:HyperledgerFabric的多通道排序机制在企业应用场景中,可能会出现一个区块链网络需要承担多种服务的情况,因此HyperledgerFabric采用了多通道的设计。所谓渠道,就是指一个封闭的业务群。一个HyperledgerFabric网络中可能有多个业务组处理不同的服务,它们在逻辑上和物理上相互隔离。如果有多个业务组,就会有几个不同的区块链,每个节点只会保存自己加入的通道的区块链数据,从而消除了多业务跨场景的数据泄露风险。排序节点也会根据不同的通道,将交易请求分发到不同的Kafka队列中,从而实现业务间的链级隔离。HyperledgerFabric网络中一个完整的交易流程是:客户端首先提交一个交易提议,发送给背书节点(至少两个,可以在背书策略中设置,用户可以指定要使用的背书节点),背书节点收到交易提议后,启动链码(运行在隔离的安全容器中,无法被人为干预),模拟交易(只是模拟,不会更新到区块链网络)。身份验证通过后,背书节点会添加数字签名返回给客户端(理论上多个背书节点返回的执行结果应该是一致的)。客户端将签名后的交易请求发送给Order节点,Order节点对其进行排序打包成块分发给各个机构的锚节点。锚节点分发给组织中的记账节点。记账节点验证通过后,将最新的区块添加到本地区块链,更新世界状态。5.智能合约图21:发起交易和智能合约调用流程智能合约(链码)是HyperledgerFabric用于应用程序与区块链网络交互的媒介。链码部署在独立隔离的Docker容器中,不受外界干扰和篡改,通过gRPC与背书节点通信。背书节点向链码容器发送交易请求后,链码容器将交易的执行结果返回给背书节点。智能合约类似于应用系统中的对外接口,交易就是对接口的调用。链码中的对外接口只提供了Init方法和Invoke方法两个方法。Init方法在区块链网络启动时只会在任何一个节点上执行一次,Invoke方法用于应用程序与区块链网络的具体交互。Chaincode有五个生命周期,打包(chaincode的编译)、安装(上传到背书节点)、实例化(Init方法的执行)、升级(chaincode的功能扩展和bug修复)、交互(应用程序调用)。企业用户可以根据自己的业务场景编写不同功能的智能合约,实现应用与区块链网络的数据交互。6.HyperledgerFabric的业务应用HyperledgerFabric是一套专门为机构和企业设计的通用业务解决方案。相比区块链1.0、2.0,可以根据用户业务灵活定制。模块化和插件化的服务模式也大大降低了用户的组网成本。非常适合金融、支付等高度敏感的业务场景。HyperledgerFabric的底层键值对存储结构也具有很强的可扩展性。HyperledgerFabric理论上可以存储可以存储在传统数据库中的数据。其多通道设计可以实现物理层面的业务解耦,多个业务可以挂载在同一个区块链网络下互不干扰。在实现资源复用的同时,也避免了组织间跨业务带来的数据泄露风险。HyperledgerFabric的另一个优势是用户可以根据自己的业务编写智能合约,自定义应用系统与区块链网络的数据交互方式。这有利于复杂业务场景与区块链技术的拼接,让“区块链+”真正进入企业级应用。结语区块链技术自问世以来,十余年间经历了三次迭代,其间流言蜚语层出不穷。只有拨开笼罩在区块链上的神秘面纱,深入探究其技术原理,才能一窥其真面目。纯粹作为一种技术,区块链本身是无价值的。一个工具能释放出什么样的社会价值,最终取决于它的用户。我们或许会惊叹设计师的巧思,但绝对没有必要赋予它太多超越技术的神秘感。区块链或许是通往未来的入口,但任何技术奇点的引爆都不是来自单点的技术突破,而是随着时间的推移酝酿的渐进演进。勤奋踏实是推动社会进步的最终动力。在科技日新月异、飞速发展的时代,我们更应该坚守这份心。参考文献[1]中本聪:比特币:一种点对点电子现金系统[EB/OL][2]Castro,Miguel,BarbaraLiskov:实用拜占庭容错。OSDI。Vol.99.1999[3]Kwon,Jae:Tendermint:Consensuswithoutmining.Draftv.0.6,fall(2014)作者简介:王翔,2018年毕业于安徽大学电子信息工程专业,现就职于知名的世界500强互联网公司。致力于服务器系统的架构设计、多活部署、性能优化、业务开发等。【原创稿件,合作站点转载请注明原作者及出处.com】