bitcoin區塊數據的獲取及mysql的優化加速

距離找到獲取比特幣餘額的方法已經過去四個多月了,中間停頓了一段時間,沒有深入研究,最近又重新拾起這個需求來,遇到了一些大大小小的問題,記錄下來,作爲自己一個成長的見證

 

開始時的代碼結構是這樣

每個getblock返回的tx可能是幾個到幾千個,每個tx可以根據gettransaction生成詳細的交易記錄older,根據交易信息獲取當前接收方的utxo及address地址,這樣從頭連到尾便會形成比特幣這個特殊的餘額。

當然,在成功之前遇到了各種問題,然而都合理解決掉了

 

首先是圍繞性能問題,ps:主要是性能問題,其他問題都不大,本文就不羅嗦了。

性能瓶頸1

由於每次找到一個交易詳情後,需要向前一步找到send,也就是每一個txid對應的是至少兩次操作。

相對的時間至少會增加兩倍,實際肯定會超出兩倍。

解決方法

遍歷一次txid,通過兩種不同的數據表存放send及rece,用相對較小的空間換取時間,性能提高兩倍有餘。

算法複雜度由O(n*N)縮小爲O(n)。

實際上這個方法也改變了數據存放的結構,間接影響了mysql的性能。

 

性能瓶頸2

bitcoin的API命令gettransaction命令會去index文件夾下遍歷levelDB數據庫

鎖定到這一行代碼後,研究了一番levelDB,發現levelDB的寫性能十分強勁,而隨機讀就有點相形見絀了。

要知道bitcoin截至到目前爲止將近4億個txid,而我每次通過gettransaction訪問txid的交易記錄便是一次隨機讀。

根據實際測試,平均讀取速度是每次70ms左右,要知道,光是讀取txid就要1000個小時,這肯定是不可以的.

解決方法

解決方法是通過getblock獲取整個tx下的txid交易詳情,執行一次大約需要400ms,但是getblock對應的數據量只有區區56萬多個塊,獲取同樣數量的txid只需要72個小時,性能提升有多高不需要細說了吧。

 

性能瓶頸3

mysql插入語句insert,開始時使用go庫中sql的事務,後來檢查sql語句在執行事務時是每個value執行一次insert語句。

要知道,mysql資源佔比中,語句的重複插入佔比非常高。

解決方法

將value值用字符串拼接方法拼接,一個數據表只執行一次insert語句便將所有對應的value插入

在這個方法下,性能提高5-10倍,由於預計將有20多億條數據存放,所以mysql分表數量爲512個。

多個表的情況下確實會降低mysql的insert性能,不過這些相對數據量來說是不可避免的。

 

性能瓶頸4

mysql中的主鍵索引隨着數據量的增加也會直接影響性能,經過測試,當每個表中的數據量達到幾萬時,便會大大降低insert速度

解決方法

索引在insert時不設置,當數據插入完成後設置

性能相對來說,提高几倍-幾十倍,這個沒有實現完整的表數據無法獲取到精確數值

 

性能瓶頸5

由於以上所有的硬盤操作都是採用win10下的機械硬盤,所以考慮到服務器的c盤是固態硬盤,將mysql的數據移到c盤的固態中

解決方法

經過測試,由原來的機械硬盤100%佔用率到固態硬盤的5%佔用率,看到後大喜。

直接開10個併發,因爲一開始寫代碼時就考慮到了以後要併發,所以併發只是一個參數的問題。

開啓併發後,cpu佔用率到70%,固態佔用50%。

性能相比最開始的提高整整幾千幾萬倍。

 

經過計算抓取完整區塊信息時間不超過2天48小時,整個過程包括getjson,解析,分類,存庫,最後大功告成。

這個過程非常的舒服,很有成就感,本次分享到此結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章