LightDB項目的探索和開發

前言

        NEO節點是一個功能很是複雜的項目,它包含了P2P網絡,RPC接口,數據庫讀寫,執行智能合約等功能。不一樣的功能相互協做,才能確保節點及時同步數據,而且提供準確的數據給使用者。節點經過P2P網絡,請求和得到塊數據,並將之驗證分析存入leveldb數據庫。當此節點正確同步到鏈上最新高度時,就意味着節點保存了一份鏈上數據能夠供用戶使用。git

       做爲開發者,對於節點的使用需求第一個是經過節點發送交易上鍊,第二個是經過RPC服務獲取節點中的數據或者模擬執行合約。在實際使用場景中,獲取數據或模擬執行合約的需求會更大一點,單個節點有時會扛不住請求的壓力。由於RPC服務和數據庫存在一個進程中,因此不存在開啓多個數據庫負載均衡提供數據給接口服務器的狀況,也不存在啓動多個接口服務器從同一個數據庫中獲取數據的狀況。github

        咱們在開發一些dapp時,會遇到節點RPC請求的瓶頸。部署多個節點負載均衡時,因爲每一個節點拿到最新的塊數據並存入leveldb的時間不同,很容易形成在某一個時間點,訪問不一樣的節點拿最新的交易數據有不一樣的返回。基於此,咱們作了一個設想,將數據庫功能從節點中獨立出來,將數據庫作成網絡數據庫(若是須要部署多個數據庫則從同一個源頭同步,保證數據庫內數據的統一)。並將RPC服務和執行智能合約的虛擬機構形成一個輕型節點提供接口服務。簡單的來講就是將Neo節點的存儲部分改成網絡存儲,而且能夠經過輕型節點直接找網絡數據庫執行InvokeScript。mongodb

項目介紹

       因爲數據處理有事務化的要求,所以須要的數據庫必需要有快照的功能。Neo節點使用的LevelDB由於採用LSM存儲方式,提供讀取的快照很是容易,代價也很小。而關係型數據庫支持事物化的程度就差了一些,咱們原本想使用的mongodb也由於讀快照功能的限制被捨棄。最終,咱們選擇了以rocksdb(rocksdb是facebook基於leveldb改進的一個版本,讀寫性能都有明顯的提高)爲基礎開發本地數據庫,並加上網絡層實現一個網絡數據庫。數據庫

        節點在獲取數據存入leveldb的時候,是有一個分類的。存儲塊數聚,utxo數據,合約數據等不一樣的數據時會追加不一樣的修正前綴,以示區分。這個是使用leveldb的一個天然需求,kv數據庫是一個字典,咱們存進去的東西,從邏輯上是分爲諾幹個字典的。如今咱們將這個需求直接在數據庫層面提供,增長了一個表的概念。用戶在讀寫時,就能夠更精準的讀取某張表內某個key的值。此外,數據庫的存儲還模仿了區塊鏈的結構,在每次寫操做的時候都會加入一個高度,模擬塊的概念,方便和區塊鏈中的塊高度對應。這樣接口服務器就能夠較容易的用塊高度來作索引,獲取對應的快照執行數據。json

        咱們將節點分析存儲每一個塊數據進入leveldb的操做都視爲一個集合,能夠確認的是不一樣的leveldb執行這個集合都必然能存儲進相同的數據。基於此,咱們將網絡數據庫的讀寫分離。將主節點每一個塊存儲進leveldb的操做都記錄下來,網絡數據庫只要獲取這些塊的操做集,本身執行一遍就同步到了數據。有了這些網絡數據庫以後,咱們的輕型節點就能夠從這些數據庫中獲取數據並返回給調用者。api

        目前這個項目仍是屬於一個探索研發階段,這裏附上這個項目的github地址:https://github.com/NewEconoLab/NEL.LightDB服務器

        下圖是項目中包含的全部的工程,NEL.Peer.*是網絡層;SDK是爲了方便客戶端接入而包裝的方法;SimpleDB是沒有附加網絡層的本地數據庫;API是實現了簡單RPC接口的輕型節點;Server是網絡數據庫。網絡

         

        

流程演示       

        咱們首先編譯Server項目,打開config.json進行配置。app

        

        port是訪問數據庫的端口;     bindAddress是容許訪問的地址;    server_storage_path是數據庫數據存放於本地的路徑;    Conn_Track,DataBase_Track,Coll_Track 這三個是mongodb的連接和庫名,咱們暫時將每一個塊應該怎麼操做數據庫的集合存放在了咱們NEL的mongodb中進行管理,目前開放性不是很高。暫時這個樣子,後續可能會將這些操做集用另外一種方式提供出來,方便使用。負載均衡

        配置完成後,啓動

        

        網絡數據庫正在快速的恢復數據。

 

        此時再編譯API工程,配置config.json

         

        port是訪問api端口,bindAddress是Api容許訪問的ip;dbServerPort是數據庫訪問的端口,dbServerAddress是數據庫所在的ip;dbServerPath是數據庫開啓的actor的路徑。(確保連接的數據庫已經同步到最近的數據高度)

        啓動api服務

        

        此時咱們藉助PostMan工具來經過api工程獲取數據(分別附上獲取塊數據,和模擬執行合約的例子)

        

 

 

 

        

 
相關文章
相關標籤/搜索