写点什么

一文理解超级账本 Hyperledger Fabric 的架构与坑

  • 2018-04-23
  • 本文字数:4542 字

    阅读完需:约 15 分钟

接触区块链的童鞋都知道比特币或者说以太坊,但是了解超级账本(Hyperledger)的肯定不多。在区块链的世界观里,一直有公有链、联盟链和私有链的分别,但后两者没有公有链引起的反响大,也被很多公有链的拥趸所鄙视。

但是我们不应该采取非一即二的思想看待这个问题,世界上没有任何客观实体是非黑即白,站的角度不同,结论也不一样。联盟链(私有链)是现有中心化商业团体联盟之间(团体内部)进行商业活动的手段和渠道,B2B 的业务很难迁移到公有链上,不仅仅是性能更是因为商业机密等问题。我相信未来是公有链与联盟链(私有链)共存,各自都有自己的使用场景,正如广域网与局域网,互有利弊,各司其职。

拉扯完背景,拖上这篇文章的主角:Hyperledger Fabric,它是由 IBM 带头发起的一个联盟链项目,于 15 年底移交给 Linux 基金会,成为开源项目。Hyperledger 基金会的成员有很多大牌,诸如 IBM,Intel,思科等。基金会里孵化了很多区块链项目,Fabric 是其中最出名的一个,一般我们说超级账本(Hyperledger)基本上指的都是 Fabric。在接下来的篇幅里,我会讲解 Fabric 的架构,包括多链多通道、账本设计等等,以及链码的编写和部署流程,最后再讲讲遇到的坑和 Fabric 的一些不足。

Fabric 架构

Fabric 的架构历经了两个版本的演进,最初接触的 0.6 版本只能被用来做商业验证,无法被应用于真实场景中。主要原因就是结构简单,基本所有的功能都集中在 peer 节点,在扩展性、安全性和隔离性方面有着天然的不足。因此在后来推出的 1.0 正式版中,将 peer 节点的功能进行分拆,把共识服务从 peer 节点剥离,独立为 orderer 节点提供可插拔共识服务。更为重要的一个变化就是加入了多通道(multi-channel)功能,可实现了多业务隔离,在 0.6 版本的基础上可以说是质的飞跃。

多链与多通道

Fabric 中的链(chain)包含了链码(chaincode)、账本(ledger)、通道(channel)的逻辑结构,它将参与方(organization)、交易(transaction)进行隔离,满足了不同业务场景不同的人访问不同数据的基本要求。通常我们说的多链在运维层次上也就是多通道。一个 peer 节点可以接入多条通道,从而加入到多条链,参与到不同的业务中。如图所示:

图中(P1、PN)、(P1、P2、P3)、(P2、PN)组成了三个相互独立的链,peer 节点只需维护自己加入的链的账本信息,感应不到其他链的存在。这种模式与现实业务场景有诸多相似之处,不同业务有不同的参与方,不参与该业务,不应该看到业务相关的任何信息。多通道特性是 Fabric 在商用区块链领域推出的杀手锏,当然也不完美,虽然 peer 节点不能看到不相关通道的交易,但是对于 orderer 节点来说,还是所有通道的交易都可以看到,虽然可以使用技术手段分区,但无疑增加了复杂度。

账本结构

账本简单的说,是一系列有序的、不可篡改的状态转移记录日志。状态转移是链码(chaincode)执行(交易)的结果,每个交易都是通过增删改操作提交一系列键值对到账本。一系列有序的交易被打包成块,这样就将账本串联成了区块链。同时,一个状态数据库维护账本当前的状态,因此也被叫做世界状态。在 1.0 版本的 Fabric 中,每个通道都有其账本,每个 peer 节点都保存着其加入的通道的账本,包含着交易日志(账本数据库)、状态数据库以及历史数据库。

账本状态数据库实际上存储的是所有曾经在交易中出现的键值对的最新值。调用链码执行交易可以改变状态数据,为了高效的执行链码调用,所有数据的最新值都被存放在状态数据库中。就逻辑上来说,状态数据库仅仅是有序交易日志的快照,因此在任何时候都可以根据交易日志重新生成。状态数据库会在 peer 节点启动的时候自动恢复或重构,未完备前,该节点不会接受新的交易。状态数据库可以使用 LevelDB 或者 CouchDB。LevelDB 是默认的内置的数据库,CouchDB 是额外的第三方数据库。跟 LevelDB 一样,CouchDB 也能够存储任意的二进制数据,而且作为 JSON 文件数据库,CouchDB 额外的支撑 JSON 富文本查询,如果链码的键值对存储的是 JSON,那么可以很好的利用 CouchDB 的富文本查询功能。

Fabric 的账本结构中还有一个可选的历史状态数据库,用于查询某个 key 的历史修改记录,需要注意的是,历史数据库并不存储 key 具体的值,而只记录在某个区块的某个交易里,某 key 变动了一次。后续需要查询的时候,根据变动历史去查询实际变动的值,这样的做法减少了数据的存储,当然也增加了查询逻辑的复杂度,各有利弊。

账本数据库是基于文件系统,将区块存储于文件块中,然后在 LevelDB 中存储区块交易对应的文件块及其偏移,也就是将 LevelDB 作为账本数据库的索引。文件形式的区块存储方式如果没有快速定位的索引,那么查询区块交易信息可能是噩梦。现阶段支持的索引有:

  • 区块编号
  • 区块哈希
  • 交易 ID 索引交易
  • 区块交易编号
  • 交易 ID 索引区块
  • 交易 ID 索引交易验证码

Kafka 共识

基于 Kafka 实现的共识机制是 Fabric1.0 中提供的共识算法之一。之所以将 0.6 版本中提供的 PBFT 暂时取消,一是因为交易性能达不到要求;二一点是因为 Fabric 面向的联盟链环境中,因为节点都是有准入控制的,拜赞庭容错的需求不是很强烈,反而是并发性能最重要。因此,也就有了 Kafka 共识的出现。

一个共识集群由多个 orderer 节点(OSN)和一个 kafka 集群组成。orderer 之间并不直接通信,他们仅仅和 Kafka 集群通信。在 orderer 的实现里,通道在 kafka 中是以 topic 的形式隔离。每个 orderer 内部,针对每个通道都会建立与 kafka 集群对应 topic 的生产者及消费者。生产者将 orderer 节点收到的交易发送到 kafka 集群进行排序,在生产的同时,消费者也同步消费排序后的交易。

那么如何鉴别某个交易属于哪个区块呢?Fabric 的区块结块由两个条件决定,区块交易量和区块时间间隔。当配置的交易量达到阈值时,无论是否达到时间间隔,都会触发结块操作;另一方面,如果触发了设置的时间间隔阈值,只要有交易就会触发结块操作,也就是说 fabric 中不会有空块。结块操作是由 orderer 节点中的 kafka 生产者发送一条 TTC-X(Time to cut block x)消息到 kafka 集群,当任意 orderer 节点的 kafka 消费者接收到任意节点发出的 TTC-X 消息时,都会将之前收到的交易打包结块,保存在 orderer 本地,之后再分发到各 peer 节点。以上过程可由下图描述:

链码

前面介绍的 Fabric 架构更多的是针对 Fabric 平台运维工程师,而对更多的应用开发者来说,链码其实才是最重要的。链码(chaincode)是 Hyperledger Fabric 提供的智能合约,是上层应用与底层区块链平台交互的媒介。现阶段,Fabric 提供 Go、Java 等语言编写的链码,但不管是哪种语言编写的链码,套路都是差不多的。

所有的链码都继承两个接口,init 和 invoke。init 接口用于初始化合约,在整个链码的生命周期里,该接口仅仅执行一次。剩下的 invoke 接口是编写业务逻辑的唯一入口,虽然只有一个入口,但是可以根据参数传递的不同自由区分不同业务逻辑,灵活性很高。比如应用开发者规定 Invoke 接口的第一个参数是合约方法名,剩余的 Invoke 参数列表是传递给该方法的参数,那么就可以在 Invoke 接口方法体中根据方法名的不同分流不同业务了。

那么在合约里能够获取哪些内容呢?我把合约接口能获得数据分为三类:

  1. 输入参数获取。这点很好理解,我们只有知道此次调用的输入,才能处理逻辑,推导输出;
  2. 与状态数据库和历史数据库交互。在合约层,我们可以将区块链底层当做是一个键值对数据库,合约就是对数据库中键值的增删改查;
  3. 与其他合约的交互。在合约执行的过程中,可以与其他合约交换数据,做到类似跨链的效果。有了这种形式的数据获取方式,其实就可以将联系不紧密的业务逻辑拆分为多个合约,只在必要的时候跨合约调用,非常类似于现在提倡的微服务架构。

编写链码还有一个非常重要的原则:不要出现任何本地化和随机逻辑。此处的本地化,不是指语言本地化,而是执行环境本地化。区块链因为是去中心架构,业务逻辑不是只在某一个节点执行,而是在所有的共识节点都执行,如果链码输出与本地化数据相关,那么可能会导致结果差异,从而不能达成共识。比如,时间戳,随机函数等。这些方法是链码编程的禁地,除非你知道你的用意,否则慎用!

链码部署

在最初接触 Fabric 的那段时间,我其实是很混淆 peer、通道和链码间的关系的,直到我从头到尾完成了一次平台的部署。简单的说,peer 是一个独立存在的计算机节点,不管是物理机还是虚拟机,总之是独立实体。在 peer 没有加入任何通道之前,是不能够做任何业务的,因为他没有业务载体。而通道就是业务载体,是纯粹的逻辑概念,可以独立于 peer 存在,但也因此也没任何存在的意义了。最后链码就是业务,业务是跑在通道里的,不同的通道即便是运行相同的链码,因为载体不同,可认为是两个不同业务。peer 是地,通道是路,链码是车,三者相辅相成才能构建一套完整的区块链业务系统。经过以上分析,链码的部署也就如“把大象放进冰箱分几步”这么简单了:

  1. 创建业务载体通道;
  2. 将通道与 peer 节点绑定;
  3. 在通道上实例化链码。

从逻辑上来说,就是如此的简单。当然,在实际的操作过程中,肯定要复杂的多,感兴趣的读者可以对照着官方文档从头到尾撸一遍,之后再读这篇文章,我相信你会有更清晰的认识。

坑与不足

区块链是门新技术,Hyperledger Fabric 是更新的区块链实现,在我们调研实践的过程中,基本上除了官方文档以外再也找不到其他资料可供我们参考,我们唯一可行的学习途径就是:撸源码!通过撸代码去了解内部实现机制,出现未知错误,直接看源码反推,使用之路确实艰辛。在使用的过程中,我们也发现了很多坑,一些坑我们可以采用其他办法绕过,另外的就只能当做是 Fabric 的不足了。

  • 通道的管理:在 Fabric 的设计里,通道其实就相当于账本的概念。现阶段仅仅只有创建,而没有删除功能,当然这可以理解,区块链的一个重要特性是不可篡改,如果能直接将整个链删除了那还了得。但是在使用 kafka 共识的过程中,如果数据操作不当,直接在 kafka 中删除数据,而 orderer 没有逻辑去处理这种异常删除,因此会不断的重试,在达到重试极限后直接崩溃整个进程。因为一个通道的错误,影响了整个系统的运转,这不是一个好的设计;
  • 没有完善的数据管理方案:在我们的使用场景中,数据增长是很快的,如果使用 CouchDB 作为底层数据引擎,数据更是几何倍数的爆发。现有的解决方案只能是在云上部署节点,提供可持续扩充的云硬盘,再者使用 LevelDB 替换掉 CouchDB,避免使用模糊查询。

学习建议

之前因为学习资料的缺失,我们只能通过撸代码来学习。而现在这个时间点,Fabric1.0 版本已经推出有一段时间了,网络上已经有了很多学习资料,基本免费开源,此处不做推荐。之后也会具体的针对 Hyperledger Fabric 推出更有侧重点的文章,敬请期待。

参考资料:

Hyperledger Fabric 官方文档 2017: http://hyperledger-fabric.readthedocs.io/en/latest/index.html

A Kafka-based Ordering Service for Fabric 2017: https://docs.google.com/document/d/1vNMaM7XhOlu9tB_10dKnlrhy5d7b1u8lSY8a-kVjCO4/edit

作者介绍

自游,区块链底层架构师。16 年初接触区块链并全职投入,现供职于某世界 500 强企业做区块链底层研究及 BAAS 平台搭建。精通区块链底层存储、共识等技术,职业方向偏重联盟链体系。

2018-04-23 18:0571888

评论 6 条评论

发布
用户头像
感谢大佬经常文章
2019-09-29 21:23
回复
用户头像
有收获。安利个我写的Fabric区块链开发详解教程:http://t.cn/Eoz7J5B,看是否可以合作合作?
2019-05-07 19:33
回复
用户头像
您好,我是一名研究生,最近要开始学习超级账本,可以获得您的联系方式吗,以便学习交流,1137938666@qq.com这是我的邮箱
2019-04-07 20:40
回复
用户头像
您好,可以加您的微信与您交流学习吗
2019-03-26 20:48
回复
用户头像
还是看看quorum吧
2019-02-17 15:22
回复
用户头像
有什么渠道可以交流下
2019-02-14 15:35
回复
没有更多了
发现更多内容

强大的蓝光播放器 Aiseesoft Blu-ray Player激活最新

mac大玩家j

Mac软件推荐 蓝光播放器 视频播放器软件

详解GaussDB(DWS)通信安全的小妙招:连接认证机制

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 华为云GaussDB(DWS)

AI实践 | 一文简述语音克隆实践

云起无垠

万界星空科技家具制造业MES系统解决方案

万界星空科技

生产管理系统 mes 家居设计 万界星空科技mes 家具生产管理系统

2024律师课程推荐:iCourt律师执行实务集训营(赠《执行实务大礼包》)

科技汇

实战营|阿里云 x StarRocks 邀你现场体验云上极速湖仓--深圳站

StarRocks

数据库 数据仓库 数据分析 StarRocks

BACK Stack会成为平台工程的新趋势吗?

杨振涛

云原生 平台工程 内部开发者平台 平台工程社区 PECommunity

"5.25秒变0.023秒:小程序图片优化全攻略"

陇锦

小程序 微信小程序 前端 前端开发 js

户外交通LED显示屏必须具备的特点

Dylan

技术 网络 计算机 LED显示屏 led显示屏厂家

强大的iOS系统恢复:Fix My iPhone最新激活

胖墩儿不胖y

Mac软件 修复软件 iOS修复工具

幸福是什么

Geek_35a87b

自我

用友全球司库十问(完结篇)|如何构建司库信创体系化能力?

用友BIP

全球司库

graphpad prism for Mac(专业医学绘图工具) v10.1.1完美激活版

mac

苹果mac Windows软件 GraphPad Prism 科学和统计分析软件

如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 2

SEAL安全

Kubernetes 运维 Helm Prometheus

代码混淆:保护您的应用程序

雪奈椰子

【新手入门】软件工程师必备技能-代码review调试定位问题

极客罗杰

概念回顾:MQTT?

NGINX开源社区

nginx 物联网 HTTP TCP/IP mqtt

【分布式技术专题】「授权认证体系」深度解析OAuth2.0协议的原理和流程框架实现指南(授权流程和模式)

洛神灬殇

oauth2.0 分布式技术 2024年第七篇文章 授权认证协议

Google Adsense探索系列_第一弹

fkys

Google adsense ads.txt not found 未找到

极狐GitLab x 智众医疗 | 成为3.5亿慢病患者的健康管家

极狐GitLab

QCN9274: A new generation core force in wireless communications

wallysSK

性能持续突破!火山引擎ByteHouse上线向量检索能力

字节跳动数据平台

数据库 大数据 云原生 数仓 企业号 1 月 PK 榜

【第七在线】如何让智能商品系统提供深入的供应链决策支持?

第七在线

左耳听风 - 中年危机「读书打卡 day 03」

Java 工程师蔡姬

读书笔记 程序员 读书 中年危机 左耳朵耗子

数据采集才是MES系统中的核心功能

万界星空科技

数据采集 MES系统 mes 设备管理 万界星空科技mes

centos7下docx转为pdf

麦兜

系统存储架构升级分享

京东科技开发者

数据资产入表:工业数字化新机遇

用友BIP

数据资产

一文理解超级账本Hyperledger Fabric的架构与坑_语言 & 开发_自游_InfoQ精选文章