Hyperledger Fabric - 如果两次更新几乎同时发生,则第二次更新

问题描述 投票:0回答:2

我只是想学习Hyperledger Fabric并做了一点测试:

type Valami struct {
        ObjectType string `json:"docType" binding:"required"`
        Value string `json:"value" binding:"required"`
        ID string  `json:"id" binding:"required"`

}

func (t *SimpleChaincode)  test(stub shim.ChaincodeStubInterface)  pb.Response {
        id := "104"
        asbytes, err := stub.GetState(id) //get the marble from chaincode state
        obj := &Valami{}
        if err != nil {
                return shim.Error("Failed to get state ")
        } else if asbytes == nil {
                fmt.Println("not found")
                objtype := "test"
                obj = &Valami{objtype, "", id}

        } else {
                fmt.Println("found")
                err = json.Unmarshal(asbytes, obj)
                if err != nil {
                        return shim.Error("Can not process to a JSON type!")
                }
        }

        now := time.Now()
        value := now.String()
        fmt.Println("value: "+value)
        obj.Value = value


         // update
        JSONasBytes, err := json.Marshal(obj)
        if err != nil {
                return shim.Error("Can not update the " + obj.ID + ". Reason: "+err.Error())
        }
        // save in state
        err = stub.PutState(obj.ID, JSONasBytes)
        if err != nil {
                return shim.Error("Can not save "+ obj.ID + ". Reason: "+err.Error())
        }
        return shim.Success([]byte("value: "+obj.Value))
}

我在彼此之后快速提交两次之后:

docker exec -e CORE_PEER_LOCALMSPID=Org1MSP -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp cli peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mur2 -c '{"Args":["test"  ]}'
  docker exec -e CORE_PEER_LOCALMSPID=Org1MSP -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp cli peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mur2 -c '{"Args":["test"  ]}'

回报:

2019-03-13 09:33:05.297 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"value: 2019-03-13 09:33:05.292254505 +0000 UTC m=+391.210396576"
2019-03-13 09:33:05.776 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"value: 2019-03-13 09:33:05.770792084 +0000 UTC m=+391.688934322"

所以看起来一切都很好。但是当我检查值时:

"{\"docType\":\"test\",\"id\":\"104\",\"value\":\"2019-03-13 09:33:05.292254505 +0000 UTC m=+391.210396576\"}"

所以实际上第二次提交没有遇到。如果我在两次提交之间休息,他们就会工作。所以我猜第一个没有在第二次开始之前完成,有些原因是第二次开始。我没想到这一点,因为它可能会在网络上随时发生。有人可以向我解释后台发生了什么,以及我们如何处理这种情况?

hyperledger-fabric
2个回答
2
投票

简单的解释:你不能在同一个块内多次更新相同的密钥:如果你发送多个事务更新相同的密钥并且所有事务都在同一个块中处理,那么只有其中一个(我认为第一个)将是已处理,其他交易将被拒绝。这就是为什么在你的情况下,当你发送txns非常接近时,只处理一个,如果你在调用之间添加一个睡眠,两者都得到正确处理(睡眠必须等于或高于你的阻塞时间)。有几种方法可以处理这种情况,一种可能是使用队列,当然也可以设计内部架构,以最大限度地减少此类问题。

更新:

是否无法将块大小设置为最多1个事务?

没有进一步的阅读/调查,不能放心回答。不确定使用这种配置对网络的稳定性和性能的影响。有一篇关于HLF性能和优化的有趣论文一年前(可能是2018年)写在这里https://arxiv.org/pdf/1805.11390.pdf可能有所帮助。也许这个周末我可以抽出时间来进行自己的测试。如果你找到关于这个主题的其他内容,请告诉我,因为它对我来说似乎很有趣,虽然我觉得它不会很好,因为网络本身具有固有的延迟,所以你不能在接近0时达成共识。

Sawtooth也一样吗?

没有使用该平台的经验,但我认为同样的想法也适用:区块链是一个需要时间就事实达成共识的网络,所以试图在比网络的固有延迟加上更短的时间内达成共识执行共识算法的时间在任何情况下都不起作用。


0
投票

Hyperledger Sawtooth也一样吗?

不,此限制不适用于Hyperledger Sawtooth。使用Sawtooth,您可以在一个块或几个连续的事务中甚至在同一个事务中多次更新相同的状态变量。但是,执行此操作时,Sawtooth Validator无法并行处理事务。冲突的事务(在相同的状态下运行)将被串行处理。

© www.soinside.com 2019 - 2024. All rights reserved.