Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

32.4. 超級賬本的硬傷

在使用超級賬本的過程中我發現一個問題,超級賬本無法並發操作一個 key,stub.PutState 是非同步執行,我們無法確認它是否執行完成,在沒有執行完成之前再發起操作,就會產生覆蓋。這個問題限制了超級賬本的很多場景應用,這是超級賬本的硬傷。

下面舉一個例子來說明超級賬本的問題

		
func (s *SmartContract) counter(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	key  := "counter"
	count,err = stub.GetState(key)
	count = count + 1
	stub.PutState(key,count)
	return shim.Success(count)
}
		
		

使用多綫程請求chaincode中的counter函數100次。你會發現最終 count 並不等於 100。學習過多綫程的朋友一定很清楚出了什麼問題。

問題出在 stub.PutState 函數count還沒有被寫入,其他綫程就開始讀取stub.GetState(key),導致讀取舊數據,最終計數器數字混亂。

很多場景需要更新區塊中的數據,如果頻繁操作,就會產生覆蓋,目前Hyperledger Fabirc 並沒有提供解決方案。

1. 我們不知道 stub.PutState是否執行完成,因為存儲過程需要共識排序。

2. 超級賬本沒有提供事物處理或者互斥鎖。

golang 提供的 mutex 也無法解決上面的問題,因為 mutex 鎖只能工作在一個進程中。Peer / Orderer 節點不止一個。

使用 redis實現分散式鎖或許能實現,但思考過後決定放棄,轉為傳統資料庫。

總結,超級賬本只適合一次寫,多次讀的場景,和極低頻修改的場景