fabric中couchdb和leveldb混合使用的问题

文章目录

背景

在fabric联盟链的同一个通道中,同时使用couchdb和leveldb的peer,在执行多节点背书或者查询时,sdk可能会报错mismatch,两种数据库返回的同一key的查询结果居然不完全相同。

分析

​起初以为是couchdb会自动修改json的字段顺序为字母顺序,当时还在心里大骂couchdb。自己写了一个客户端尝试写入kv到couchdb,查询的结果字段顺序并无变化,只能怀疑是fabric自己做了额外排序。

​果不其然,fabric对json做了unmarshal。因为jsonMap是map[string]interface{},所以重新marshal时,按照字母顺序排序了。

// core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go

func keyValToCouchDoc(kv *keyValue) (*couchDoc, error) {
	type kvType int32
	const (
		kvTypeDelete = iota
		kvTypeJSON
		kvTypeAttachment
	)
	key, value, metadata, version := kv.key, kv.Value, kv.Metadata, kv.Version
	jsonMap := make(jsonValue)

	var kvtype kvType
	switch {
	case value == nil:
		kvtype = kvTypeDelete
	// check for the case where the jsonMap is nil,  this will indicate
	// a special case for the Unmarshal that results in a valid JSON returning nil
	case json.Unmarshal(value, &jsonMap) == nil && jsonMap != nil:
		kvtype = kvTypeJSON
		if err := jsonMap.checkReservedFieldsNotPresent(); err != nil {
			return nil, err
		}
	default:
		// create an empty map, if the map is nil
		if jsonMap == nil {
			jsonMap = make(jsonValue)
		}
		kvtype = kvTypeAttachment
	}

	verAndMetadata, err := encodeVersionAndMetadata(version, metadata)
	if err != nil {
		return nil, err
	}
	// add the (version + metadata), id, revision, and delete marker (if needed)
	jsonMap[versionField] = verAndMetadata
	jsonMap[idField] = key
	if kv.revision != "" {
		jsonMap[revField] = kv.revision
	}
	if kvtype == kvTypeDelete {
		jsonMap[deletedField] = true
	}
	jsonBytes, err := jsonMap.toBytes()
	if err != nil {
		return nil, err
	}
	couchDoc := &couchDoc{jsonValue: jsonBytes}
	if kvtype == kvTypeAttachment {
		attachment := &attachmentInfo{}
		attachment.AttachmentBytes = value
		attachment.ContentType = "application/octet-stream"
		attachment.Name = binaryWrapper
		attachments := append([]*attachmentInfo{}, attachment)
		couchDoc.attachments = attachments
	}
	return couchDoc, nil
}

总结

不同语言marshal的json字段顺序也往往不一致,所以fabric网络不同组织如果混用不同语言实现的同一个业务合约,可能会遇到类似的麻烦,解决方案也很简单,可以在sdk层做一下json字段的重排。
目前截止fabric2.2.x这个最新的LTS版本都有这个问题,但是新版的fabric已经在修复此问题,详见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Title: Node Patterns – Databases: Volume I – LevelDB, Redis and CouchDB Author: Pedro Teixeira Length: 149 pages Edition: 1 Language: English Publication Date: 2015-04-08 ISBN-10: B00VV93SV2 Node.js has been designed to do quick and efficient network I/O. It's event-driven streams make it ideal to be used as a kind of smart proxy, often working as the glue between back-end systems and clients. Node was originally designed with that intention in mind, but meanwhile it also has been successfully used to build traditional web applications: an HTTP server that serves HTML pages or replies JSON messages and uses a database to store the data. Even though web frameworks in other platforms and languages have preferred to stick with traditional open-source relational databases like MySQL or PostgreSQL, most of the existing Node web frameworks (like Express, Hapi and others) don't impose any database or even any type of database at all. This bring-your-own-database approach has been in part fed by the explosion in the variety of database servers now available, but also by the ease with which the Node module system and NPM allow you to install and use third-party libraries. In this book we will analyze some of the existing solutions for interacting with some types of databases and what interesting uses can you give them. This first short book on databases starts with some of my favourites: LevelDB, Redis and CouchDB. Table of Contents Chapter 1. The source code Chapter 2. Introduction Chapter 3. An embedded database using LevelDB Chapter 4. Redis Chapter 5. CouchDB

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值