雖然想把標題取得大一點,但終究不是什麼太大不了的工作,還是安分守己的開始介紹吧。
專案組成
這個專案叫做LightDB
由三個部分構成
Lightdb.lib 是對rocksdb做了一層封裝,主要的修改是追加了儲存的資料型別,和表的概念
https://github.com/lightszero/lightdb.lib
Lightdb.server 就是一個遠端資料庫啦,Lightdb的伺服器版本
https://github.com/lightszero/lightdb.server
Lightdb.SDK 是方便客戶端接入LightdbServer 提供的,目前只提供了C#版本實現,後續還會提供Typescript版本實現,通訊協議比較簡單,任意支援websocket的方案都可以連線。
https://github.com/lightszero/lightdb.sdk
專案特點
要說專案特點的話,
一、追加了資料型別和表概念。
二、有伺服器,採用websocket通訊,對js友好
三、資料的儲存以taskblock為單位,方便資料庫互相驗證和同步
其實最重要的特點還有一個關於讀的快照snapshot。快照的需求來源是資料處理的事務化,或者說一批操作的原子性要求。
傳統資料庫一定程度支援事務化,而KeyValue資料庫這邊支援事務化的程度就更差一些。
而NEO使用的嵌入式資料庫,LevelDB因為採用LSM儲存方式,提供讀取的snapshot 非常容易,代價也小。
這也就造成了在NEO的實現中,儲存部分對Snapshot的依賴非常強。
創立這個專案的初衷,有一部分是要改造NEO的儲存部分為網路儲存,並且可以用輕型節點直接找網路資料庫去執行InvokeScript
也就是把Neo的一個節點一個程式的模式,改造為一個節點一個叢集。
完成這個目標的基礎,就是這個網路資料庫需要一個類似的很低成本的讀snapshot支援。
所以我選擇了rocksdb作為這個基礎,rocksdb是facebook 基於leveldb魔改的一個改進版本。
那麼為什麼要追加資料型別和表的概念?因為leveldb使用中儲存的東西都是byte[],而很多時候我們使用neo中得到的byte[] 都不知道是什麼東西,要靠相應的約定。
我覺得這個很不方便,所以我們儲存的單位不是byte[] 而是一個結構體 DBValue,他可以描述自己是什麼資料型別,整數,string,byte[],bigint,小數,等等。
這個結構體裡面還預留了給每一個值附加資訊的功能,也記錄了這個值最終修改的時間戳(儲存高度)
至於表就更好理解了,這是使用leveldb的一個自然需求,keyvalue資料庫是一個字典,可是我們存進去的東西,從邏輯上是分為幾個字典的,交易字典,utxo字典,等等等。
我們只是把這個分字典的自然需求,在資料庫層面直接提供了。
然後是網路層,選擇了websocket作為通訊方法,完全是基於將來是網頁的天下的考慮。因為儲存這個功能被獨立出來,甚至可以寫一條鏈,他完全是在網頁中執行的。
當然目前還沒有想那麼多,但可以預見到越來越多的業務會在網路中執行,因為這個資料庫的出現,nel目前的至少50%的查詢需求可以不通過後臺伺服器,js直接完成。
比如nep5資產的blanceof,比如交易UTXO資料的確認。
其三,資料庫的儲存模仿了區塊鏈的結構,以taskblock為單位,首尾相接。畢竟一開始這個專案的名字就叫lightchain.
後來一想,這個名字有點爛大街了,資料庫還是老老實實的叫DB吧
為什麼要以taskblock為單位呢,因為便於同步。資料庫讀寫分離是效能擴充套件的必然走向,而把每一個操作記錄下來,從資料庫只要從主資料庫取得每一個block,自己執行一遍,就同步完了。
對了還有一點也很像NEO區塊鏈,我們的寫入許可權控制不是用密碼,而是用私鑰,而且還是和NEO完全相容的私鑰
最後,還有一個很重要的功能,checkpoint,這也是rocksdb提供的禮物,可以快速的在本地產生一個新的資料庫副本。這樣我們做鏈上資料快照的手段就更多了,傳統手段是用爬蟲爬取要快照的資料,爬到指定高度,停。現在又多了一個手段,約定時間快照,到時間了,啪,一個checkpoint,整個資料庫都備份下來了。
不過當資料量達到G的級別,這個checkpoint效能是怎樣的,還是需要測試確認的
專案使用方法
一、開伺服器
獲取lightdb.server,生成
啟動之前看一下config
Server_port 服務埠
Server_storage_path 資料庫儲存路徑
Server_type 讀寫分離用,從機模式還沒開發呢,只能Master
Storage_maindb_magic 提供一個魔法字串,好讓這個庫特立獨行
會寫入庫中,資料庫建立之後,改這個值就沒意義了
Storage_maindb_firstwriter_address 提供一個NEO地址,他將成為第一個有寫入許可權的人,實際上還沒開發追加寫入人的功能,他就是唯一一個。
會寫入庫中,資料庫建立之後,改這個值就沒意義了
然後啟動server,支援linux windows,在win10,unbutu,centos測試過,linux下需安裝依賴庫,參考facebook rocksdb專案的說明
https://github.com/facebook/rocksdb/blob/master/INSTALL.md
中的Supported platforms一節
如果路徑裡沒有建立過資料庫會新建,否則會開啟
控制檯目前只有db.state 和 db.block 兩個功能
Db.block 會把block解析開,我們可以看到每個block都幹了些啥,value都是DBvalue,用DBValue結構體去檢視就能看到型別
二、客戶端使用
首先引用lightdb.sdk,可以下原始碼,可以nuget
New一個client物件
註冊,斷線事件,然後Connect
如果連線成功,就OK
不需要登陸啥的,讀隨便,寫的時候,需要你先簽好名
Ping 與dbstate
所有的讀操作都是通過snap來進行的
所以先要獲取一個snapshot
然後就可以getblock
Getblockhash
Getvalue
client.Post_snapshot_getvalue(snapshotid, tableid, key);
要寫資料就比較複雜了
首先建立個writetask物件,所有的寫入,都通過writetask物件完成,
然後建立signdata物件,進行簽名
然後將這兩個東西post給伺服器。有對應的私鑰才能完成簽名,成功寫入資料