State Database options(状态数据库选项)
状态数据库选项包括LevelDB和CouchDB(默认库是leveldb)。 LevelDB是嵌入在peer进程中的默认键值状态数据库。 CouchDB是可选的替代外部状态数据库。与LevelDB键值存储一样,CouchDB可以存储以链代码建模的任何二进制数据(CouchDB附属功能在内部用于非JSON二进制数据)。但作为JSON文档存储,当链代码值(例如资产)被建模为JSON数据时,CouchDB还能够对链代码数据进行丰富的查询。
LevelDB和CouchDB都支持核心链代码操作,例如获取和设置密钥/键值/keys(资产)以及基于密钥/键值/keys查询。可以按范围查询密钥/键值/keys,并且可以对复合密钥建模以启用针对多个参数的等效查询。例如,所有者的复合键,asset_id可用于查询某个实体拥有的所有资产。这些基于密钥的查询可用于针对分类帐的只读查询,以及更新分类帐的事务。
如果您将资产建模为JSON并使用CouchDB,您还可以使用链代码中的CouchDB JSON查询语言对链代码数据值执行复杂的富查询。这些类型的查询对于理解分类账上的内容非常有用。针对这些类型的查询的提议响应通常对客户端应用程序有用,但通常不作为事务提交给orderer服务。实际上,无法保证结果集在链代码执行和富查询的提交时间之间是稳定的,因此丰富的查询不适合在更新事务中使用,除非应用程序能够保证链码执行时间和提交时间之间的结果集是稳定的,或者可以处理后续事务中的潜在更改。例如,如果您对Alice拥有的所有资产执行富查询并将其传输给Bob,则可能会在链代码执行时间和提交时间之间通过另一个事务将新资产分配给Alice,您将错过此“幻像”项。
CouchDB作为一个独立的数据库进程与peer一起运行,因此在设置,管理和操作方面还有其他考虑因素。您可以考虑从默认的嵌入式LevelDB开始,如果需要其他复杂的富查询,请转到CouchDB。将链码资产数据建模为JSON是一种很好的做法,因此您可以选择在将来需要时执行复杂的富查询。
JSON文档不能在顶层使用以下字段名。这些是供内部使用的。
_deleted
_id
_rev
~version
Using CouchDB from Chaincode(使用链码的couchdb)
大多数链码填充程序API可以与LevelDB或CouchDB状态数据库一起使用,例如, GetState,PutState,GetStateByRange,GetStateByPartialCompositeKey。此外,当您在链码中使用CouchDB作为状态数据库,并将资产建模为JSON时,您可以通过使用GetQueryResult API并传递CouchDB查询字符串对状态数据库中的JSON执行富查询。查询字符串遵循CouchDB JSON查询语法。
marbles02 fabric示例演示了使用来自链码的CouchDB查询。它包含一个queryMarblesByOwner()函数,该函数通过将所有者id传递到链码来演示参数化查询。 然后,它使用JSON查询语法查询状态数据以查找与“marble”的docType和所有者id匹配的JSON文档的状态数据。
{"selector":{"docType":"marble","owner":<OWNER_ID>}
为了提高JSON查询的效率,CouchDB中的索引是必需的,对于任何具有排序的JSON查询都是必需的。索引可以与链码一起打包在/META-INF/statedb/couchdb/ Indexes目录中。每个索引必须在其扩展名为*.json的文本文件中定义。索引定义采用JSON格式,遵循CouchDB索引JSON语法。例如,为了支持上述marble查询,提供了docType和owner字段的示例索引:
{"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}
链代码的META-INF / statedb / couchdb / indexes目录中的任何索引都将与用于部署的链代码打包在一起。当链代码安装在peer上并在peer的一个通道上实例化时,索引将自动部署到peer的通道和链代码特定的状态数据库(如果它已配置为使用CouchDB)。如果首先安装链代码然后在通道上实例化链代码,则索引将在链代码实例化时进行部署。如果链代码已在通道上实例化,并且您稍后在peer上安装链代码,则索引将在链代码安装时部署。
部署后,链代码查询将自动使用索引。 CouchDB可以根据查询中使用的字段自动确定要使用的索引。或者,在选择器查询中,可以使用use_index关键字指定索引。
在安装的链码的后续版本中可能存在相同的索引。要更改索引,请使用相同的索引名称,但要更改索引定义。在安装/实例化时,索引定义将重新部署到peer的状态数据库。
如果您已经有了大量的数据,并且稍后安装了链代码,那么在安装时创建索引可能需要一些时间。类似地,如果您已经有大量数据并实例化了链码的后续版本,那么创建索引可能需要一些时间。避免调用查询状态数据库的链码函数,因为在初始化索引时,链码查询可能超时。在事务处理期间,当块提交到分类帐时,索引将自动刷新。
CouchDB Configuration(couchdb 配置)
通过将状态数据库配置选项从goleveldb更改为CouchDB,可以将CouchDB作为状态数据库启用。 此外,couchDBAddress需要配置为指向peer使用的CouchDB。 如果CouchDB配置了用户名和密码,则应使用admin用户名和密码填充用户名和密码属性。 couchDBConfig部分提供了其他选项,并记录在案。 对core.yaml的更改将在重新启动peer后立即生效。
您还可以传入docker环境变量来覆盖core.yaml值,例如CORE_LEDGER_STATE_STATEDATABASE和CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS。
以下是core.yaml的stateDatabase部分:
state:
# stateDatabase - options are "goleveldb", "CouchDB"
# goleveldb - default state database stored in goleveldb.
# CouchDB - store state database in CouchDB
stateDatabase: goleveldb
couchDBConfig:
# It is recommended to run CouchDB on the same server as the peer, and
# not map the CouchDB container port to a server port in docker-compose.
# Otherwise proper security must be provided on the connection between
# CouchDB client (on the peer) and server.
couchDBAddress: couchdb:5984
# This username must have read and write authority on CouchDB
username:
# The password is recommended to pass as an environment variable
# during start up (e.g. LEDGER_COUCHDBCONFIG_PASSWORD).
# If it is stored here, the file must be access control protected
# to prevent unintended users from discovering the password.
password:
# Number of retries for CouchDB errors
maxRetries: 3
# Number of retries for CouchDB errors during peer startup
maxRetriesOnStartup: 10
# CouchDB request timeout (unit: duration, e.g. 20s)
requestTimeout: 35s
# Limit on the number of records to return per query
queryLimit: 10000
托管在Hyperledger Fabric提供的docker容器中的CouchDB能够使用Docker Compose脚本使用COUCHDB_USER和COUCHDB_PASSWORD环境变量传入环境变量来设置CouchDB用户名和密码。
对于Fabric提供的docker镜像之外的CouchDB安装,必须编辑该安装的local.ini文件以设置admin用户名和密码。
Docker编写脚本仅在创建容器时设置用户名和密码。 如果要在创建容器后更改用户名或密码,则必须编辑local.ini文件。
在每个peer节点启动时读取CouchDB peer选项