在HyperLedger Fabric中启用CouchDB作为State Database

简介: 回顾一下我之前的一篇博客,在Fabric 1.0中,我们存在3种类型的数据存储,一种是基于文件系统的区块链数据,这个跟比特币很像,比特币也是文件形式存储的。Fabric1.0中的区块链存储了Transaction订单读写集。

回顾一下我之前的一篇博客,在Fabric 1.0中,我们存在3种类型的数据存储,一种是基于文件系统的区块链数据,这个跟比特币很像,比特币也是文件形式存储的。Fabric1.0中的区块链存储了Transaction订单读写集。而读写集到底是读什么?写什么?其实就是我们的State Database,也叫做World State,里面以键值对的方式存储了我们在ChainCode中操作的业务数据。另外还有就是对历史数据和区块链索引的数据库。

区块链是文件系统,这个目前不支持更改,历史数据和区块链的索引是LevelDB,这个也不能更改。而对于State Database,由于和业务相关,所以提供了替换数据库,目前支持默认的LevelDB和用户可选择的CouchDB。这里要说到2点,一个是在0.6的时候其实用的RockDB,但是由于License的考虑,所以在1.0改成了LevelDB。另外就是CouchDB也不一定是最优的,很多人还考虑到MongoDB或者MySQL等,但是由于现在Fabric那边开发资源有限,所以在1.0还不会做,以后可能会实现。

CouchDB安装

下面我们来说一说这个CouchDB。

CouchDB是一个完全局域RESTful API的键值数据库,也就是说我们不需要任何客户端,只需要通过HTTP请求就可以操作数据库了。LevelDB是Peer的本地数据库,那么肯定是和Peer一对一的关系,那么CouchDB是个网络数据库,应该和Peer是什么样一个关系呢?在生产环境中,我们会为每个组织部署节点,而且为了高可用,可能会在一个组织中部署多个Peer。同样我们在一个组织中也部署多个CouchDB,每个Peer对应一个CouchDB。

HyperLedger在Docker Hub上也发布了CouchDB的镜像,为了能够深入研究CouchDB和Fabric的集成,我们就采用官方发布的CouchDB来做。

docker pull klaemo/couchdb

【注意,如果我们是docker pull couchdb,那么只能获得1.6版本的CouchDB,而要获得最新的2.0版,就需要用上面这个镜像。】

可以获得官方的CouchDB镜像。CouchDB在启动的时候需要指定一个本地文件夹映射成CouchDB的数据存储文件夹,所以我们可以在当前用户的目录下创建一个文件夹用于存放数据。

mkdir couchdb

下载完成后,我们只需要执行以下命令即可启用一个CouchDB的实例:

docker run -p 5984:5984 -d --name my-couchdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb:/opt/couchdb/data klaemo/couchdb
启动后我们打开浏览器,访问Linux的IP的5984端口的URL,比如我的Linux是192.168.100.129,那么URL是:
http://192.168.100.129:5984/_utils
这个时候我们就可以看到CouchDB的Web管理界面了。输入用户名admin密码password即可进入。
现在是一个空数据库,我们将CouchDB和Peer结合起来后再看会是什么样的效果。

配置CouchDB+Fabric环境

先删除刚才创建的CouchDB容器:
docker rm -f my-couchdb
首先我们是4个Peer+1Orderer的模式,所以我们先创建4个CouchDB数据库:
cd ~ 
mkdir couchdb0 
mkdir couchdb1 
mkdir couchdb2 
mkdir couchdb3 
docker run -p 5984:5984 -d --name couchdb0 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb0:/opt/couchdb/data klaemo/couchdb 
docker run -p 6984:5984 -d --name couchdb1 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb1:/opt/couchdb/data klaemo/couchdb 
docker run -p 7984:5984 -d --name couchdb2 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb2:/opt/couchdb/data klaemo/couchdb 
docker run -p 8984:5984 -d --name couchdb3 -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -v ~/couchdb3:/opt/couchdb/data klaemo/couchdb

然后我们需要启动Fabric了。Fabric的准备环境,可以参见我们这篇博客:http://www.cnblogs.com/studyzy/p/6973334.html

官方已经提供了多个Docker-compose文件,如果我们使用的是./network_setup.sh up命令,那么启用的就是docker-compose-cli.yaml这个文件。如果要基于这个yaml文件启用CouchDB的Peer,则打开该文件,并编辑其中的Peer节点,改为如下的形式:

peer0.org1.example.com:
  container_name: peer0.org1.example.com
  environment:
    - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
    - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=192.168.100.129:5984
    - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
    - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=password

  extends:
    file:  base/docker-compose-base.yaml
    service: peer0.org1.example.com

这里的192.168.100.129:5984是我映射CouchDB后的Linux的IP地址和IP。然后是设置用户名和密码。把4个Peer的配置都改好后,保存,我们试着启用Fabric:

./network_setup.sh up

等Fabric启动完成并运行了ChainCode测试后,我们刷新http://192.168.100.129:5984/_utils ,可以看到以Channel名字创建的Database,另外还有几个是系统数据库。

点进mychannel数据库,我们可以看到其中的数据内容。点击“Mango Query”可以编写查询,默认提供的查询可以点击Run Query按钮查询所有的数据结果:

CouchDB的直接查询

接下来我们使用Linux的curl来查询CouchDB数据库。
比如我们要看看mychannel数据库下有哪些数据:
curl http://192.168.100.129:5984/mychannel/_all_docs
可以看到我运行了一些ChainCode后的State DATABASE结果:

{"total_rows":7,"offset":0,"rows":[
{"id":"devincc\u0000a","key":"devincc\u0000a","value":{"rev":"2-a979bf6c2716ecae6d106999f833a59c"}},
{"id":"devincc\u0000b","key":"devincc\u0000b","value":{"rev":"2-ad1c549305fd277097180405f96bdcd8"}},
{"id":"lscc\u0000devincc","key":"lscc\u0000devincc","value":{"rev":"1-05d2cd0b344c4dd8a8d1a3ffd7332544"}},
{"id":"lscc\u0000mycc","key":"lscc\u0000mycc","value":{"rev":"1-2cba0344b1610b9d9254bbafbda5e9b1"}},
{"id":"mycc\u0000a","key":"mycc\u0000a","value":{"rev":"2-588a45b289359afa9dc6e5e7866eaf97"}},
{"id":"mycc\u0000b","key":"mycc\u0000b","value":{"rev":"2-54e6639a858b0f91298c9a354484513a"}},
{"id":"statedb_savepoint","key":"statedb_savepoint","value":{"rev":"10-6ccde2a55c71d7d6a70d9333d119fc8e"}}
]}

如果我们要查询其中的一条数据,只需要用/ChannelId/id来查询,比如查询:statedb_savepoint

curl http://192.168.100.129:5984/mychannel/statedb_savepoint

返回的结果:
{"_id":"statedb_savepoint","_rev":"10-6ccde2a55c71d7d6a70d9333d119fc8e","BlockNum":4,"TxNum":0,"UpdateSeq":"19-g1AAAAEzeJzLYWBg4MhgTmHgzcvPy09JdcjLz8gvLskBCjMlMiTJ____PyuRAYeCJAUgmWQPVsOCS40DSE08WA0jLjUJIDX1eO3KYwGSDA1ACqhsPiF1CyDq9mclsuJVdwCi7j4h8x5A1AHdx5kFAI6sYwk"}

麻烦的是业务数据是“ChainCodeName\u0000数据”这样的格式的ID,而如果我们要通过这个ID查询,那么就根本找不到啊!

curl http://192.168.100.129:5984/mychannel/mycc\u0000a
{"error":"not_found","reason":"missing"}

正确的做法是把\u0000替换为%00,也就是说我们的查询应该是:

curl http://192.168.100.129:5984/mychannel/mycc%00a

正确返回结果:
{"_id":"mycc\u0000a","_rev":"2-588a45b289359afa9dc6e5e7866eaf97","chaincodeid":"mycc","version":"4:0","_attachments":{"valueBytes":{"content_type":"application/octet-stream","revpos":2,"digest":"md5-hhOYXsSeuPdXrmQ56Hm7Kg==","length":2,"stub":true}}}

Fabric可能会遇到的问题

虽然区块链是一个只能插入和查询的数据库,但是我们的业务数据是存放在State Database中的,如果我们直接修改了CouchDB的数据,那么接下来的查询和事务是直接基于修改后的CouchDB的,并不会去检查区块链中的记录,所以理论上是可以通过直接改CouchDB来实现业务数据的修改。
我们以官方的Marble为例,看看修改CouchDB会怎么样?
具体操作步骤如下:
1.Install,instantiate和初始化数据:
peer chaincode install -n marbles02 -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02

peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C mychannel -n marbles02 -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 -c '{"Args":["init"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C mychannel -n marbles02 -c '{"Args":["initMarble","marble2","red","50","tom"]}'

peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'

我们可以看到通过curl直接查询CouchDB中的数据:

curl http://192.168.100.129:5984/mychannel/marbles02%00marble2

{"_id":"marbles02\u0000marble2","_rev":"1-a1844f47b9ed94294b430c9a9a6f543b","chaincodeid":"marbles02","data":{"docType":"marble","name":"marble2","color":"red","size":50,"owner":"tom"},"version":"6:0"}

如果我们要修改其中的数据,把颜色改成green,大小改成10,那么我们可以运行:

curl -X PUT http://192.168.100.129:5984/mychannel/marbles02%00marble2 -d '{"_id":"marbles02\u0000marble2","_rev":"1-a1844f47b9ed94294b430c9a9a6f543b","chaincodeid":"marbles02","data":{"docType":"marble","name":"marble2","color":"green","size":10,"owner":"tom"},"version":"6:0"}'

系统返回结果:
{"ok":true,"id":"marbles02\u0000marble2","rev":"2-6ffc6652cfc707f8352a5f06c3ce1ce6"}

我们在4个CouchDB中都运行这个命令,把4个数据库的数据都改了。
接下来我们通过ChainCode来查询,看看会怎么样。
peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'
返回结果:
Query Result: {"color":"green","docType":"marble","name":"marble2","owner":"tom","size":10}
可以看到数据已经变成新的值,那么接下来运行其他的Transaction会怎么样?我们试一试转账操作:
peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C mychannel -n marbles02 -c '{"Args":["transferMarble","marble2","jerry"]}'
系统返回成功,我们再查一下呢
peer chaincode query -C mychannel -n marbles02 -c '{"Args":["readMarble","marble2"]}'
Query Result: {"color":"green","docType":"marble","name":"marble2","owner":"jerry","size":10}
所以我们对CouchDB数据库的更改都是有效的,在Fabric看来似乎并不知道我们改了CouchDB的内容。
 
【本文章出自 博客园深蓝居,转载请注明作者出处,如果您觉得博主的文章对您有很大帮助,欢迎点击右侧打赏按钮对博主进行打赏。】
打个招聘广告,博主正在主导开发一个跨链区块链项目:PalletOne,一直在招Go程序员,待遇丰厚,坐标北京酒仙桥,希望有识之士加入!
目录
相关文章
|
SQL 分布式计算 监控
Sqoop数据迁移工具使用与优化技巧:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入解析Sqoop的使用、优化及面试策略。内容涵盖Sqoop基础,包括安装配置、命令行操作、与Hadoop生态集成和连接器配置。讨论数据迁移优化技巧,如数据切分、压缩编码、转换过滤及性能监控。此外,还涉及面试中对Sqoop与其他ETL工具的对比、实际项目挑战及未来发展趋势的讨论。通过代码示例展示了从MySQL到HDFS的数据迁移。本文旨在帮助读者在面试中展现Sqoop技术实力。
1259 2
|
6月前
|
SQL 开发框架 .NET
【全网最详细】.NET Framework 4.5官网下载安装教程|.NET 4.5环境搭建详细指南
.NET Framework 4.5是微软2012年发布的Windows平台运行时,支持异步编程、WinRT和WebSocket等新特性。虽已非最新版,但在运行旧软件、维护传统Windows应用中仍不可或缺,兼容Win7 SP1/8/10。
|
移动开发 安全 Java
钉钉企业应用网关了解一下
通过企业应用网关,即便该服务器完全在互联网上运行,我们也能够实现“零信任”访问。
3166 1
钉钉企业应用网关了解一下
|
7月前
|
算法 Java C语言
重新认识 C++:不止是 “难学的编程语言”,更是编程底层思维的基石
提到C++,很多编程新手的第一印象是“难、复杂、偏底层”,甚至会直接将其归为“劝退级”语言。但事实上,C++的“难”,本质是对编程底层逻辑的深度还原——它不似Python、Java那样封装了大量细节,而是让你直面内存、数据、执行流程的本质。
838 3
|
9月前
|
人工智能 自然语言处理 安全
AI心理咨询机器人技术解析:安全机制、适用边界与选型指南
深夜失眠、压力难解时,AI心理咨询正成为新选择。2024年全球市场规模达552亿美元,中国情感陪伴市场年增速高达148.74%。本文解析AI心理机器人的技术架构、安全边界与适用场景,揭示专业平台如何通过CBT干预、多模态情绪识别和危机预警保障用户安全,助你理性选择可靠工具。
|
10月前
|
CDN
阿里云CDN收费标准:流量价格、带宽峰值计费及月结95带宽峰值计费说明
阿里云CDN收费包含基础费与增值费。基础费默认按流量计费,支持阶梯价及资源包抵扣;也可选按带宽峰值或月结95带宽计费。增值费如HTTPS、QUIC、WAF、实时日志等按使用收费,不使用不计费。2024年最新价格详见官方页面。
1345 2
|
10月前
|
监控 安全 网络安全
VPC专有网络搭建与安全组配置
本文系统介绍VPC专有网络搭建与安全组配置,涵盖CIDR规划、子网划分、路由策略、NAT/VPN网关应用、安全组最小权限原则及混合云连接方案,结合多区域互联实战与安全检查清单,全面呈现云上网络安全架构最佳实践。
679 0
|
设计模式 前端开发 JavaScript
webpack实战之手写一个loader和plugin
该文章详细讲解了如何从零开始编写一个自定义的Webpack Loader和Plugin,包括它们的工作原理、开发步骤以及如何将自定义的Loader和Plugin集成到Webpack配置中。
webpack实战之手写一个loader和plugin
|
机器学习/深度学习 人工智能 编解码
《深度剖析:生成对抗网络中生成器与判别器的高效协作之道》
生成对抗网络(GAN)通过生成器与判别器的对抗学习,实现了数据生成和处理的革命性变革。生成器从噪声中创造逼真样本,判别器则判断数据真假。两者在训练中不断优化,最终达到纳什均衡。影响协作效率的关键因素包括网络架构设计、损失函数选择和超参数设置。采用先进的架构如DCGAN、优化损失函数如WGAN,并动态调整训练策略,可显著提升生成器与判别器的协作效果,推动GAN在图像生成、风格迁移等领域的应用发展。
803 5
|
自然语言处理 API Android开发
阿里Qwen2-72B大模型已是开源榜的王者,为什么还要推出其他参数模型,被其他模型打榜?
阿里云的Qwen2-72B模型在Hugging Face上荣登开源模型榜首,展现卓越性能,超越其他包括Meta的Llama-3在内的竞争者。Qwen2有多个参数版本,其中72B版本在自然语言理解、知识、代码等任务上表现出色。较小参数版本如7B模型在某些方面略逊一筹。推出不同参数模型可能是为了降低成本、加速迭代、构建丰富的模型生态。通过提供不同规模的模型,阿里云旨在促进技术研究和全场景应用,类似于微软Windows XP和阿里云OS生态的构建策略。
1122 1

热门文章

最新文章