使用Java开发一个做数据共享的联盟链思路
起因
公司要開發(fā)區(qū)塊鏈,原本是想著使用以太坊開發(fā)個合約或者是使用個第三方平臺來做,后來發(fā)現(xiàn)都不符合業(yè)務(wù)需求。原因很簡單,以太坊、超級賬本等平臺都是做共享賬本的,有代幣和挖礦等模塊。而我們需要的就是數(shù)家公司組個聯(lián)盟,來共同見證、記錄一些不可篡改的交互信息,如A公司給B公司發(fā)了一個xxx請求,B公司響應(yīng)了什么什么。其實要的就是一個分布式數(shù)據(jù)庫,而且性能要好,不能像比特幣那種10分鐘才生成一個區(qū)塊。我們要的更多的是數(shù)據(jù)庫的性能,和區(qū)塊鏈的一些特性。
經(jīng)過
項目于3月初開始研發(fā),歷時一月發(fā)布了第一版。主要做了存儲模塊、加密模塊、網(wǎng)絡(luò)通信、公鑰私鑰、區(qū)塊內(nèi)容解析落地入庫等。已經(jīng)初步具備了區(qū)塊鏈的基本特征,但在共識機制、merkle tree、智能合約以及其他的一些細節(jié)上,尚不到位。
希望高手不吝賜教,集思廣益,提出見解或方案,來做一個區(qū)塊鏈平臺項目,適合更多的區(qū)塊鏈場景,而不僅僅是賬本和各種忽悠人的代幣。
理想中的區(qū)塊鏈平臺:?
項目說明
主要有存儲模塊、網(wǎng)絡(luò)模塊、加密模塊、區(qū)塊解析入庫等。
該項目屬于"鏈",非"幣"。不涉及虛擬幣和挖礦。本質(zhì)上類似于騰訊區(qū)塊鏈項目trustsql。
存儲模塊
Block內(nèi)存儲的是類Sql語句。聯(lián)盟間預(yù)先設(shè)定好符合業(yè)務(wù)場景需要的數(shù)據(jù)庫表結(jié)構(gòu),然后設(shè)定好各個節(jié)點對表的操作權(quán)限(ADD,UPDATE,DELETE),將來各個節(jié)點就可以按照自己被允許的權(quán)限,進行Sql語句的編寫,并打包至Block中,再全網(wǎng)廣播,等待全網(wǎng)校驗簽名、權(quán)限等信息的合法性。如果Block合法,則允許生成,生成后再全網(wǎng)廣播,各節(jié)點拉取新區(qū)塊。新區(qū)塊生成后,各節(jié)點進行區(qū)塊內(nèi)容解析,并落地入庫的操作。
場景就比較廣泛了,可以設(shè)定不同的表結(jié)構(gòu),或者多個表,進而能完成各自類型信息的存儲。譬如商品溯源,從生產(chǎn)商、運輸、經(jīng)銷商、消費者等,每個環(huán)節(jié)都可以對某個商品進行ADD信息的操作。
存儲采用的是key-value數(shù)據(jù)庫rocksDB,了解比特幣的知道,比特幣用的是levelDB,都是類似的東西。最近發(fā)現(xiàn)在部分Windows下,rocksDB加載失敗。也可以替換為levelDB,只需要修改2個類即可。
結(jié)構(gòu)類似于sql的語句,如ADD(增刪改) tableName(表名)ID(主鍵) JSON(該記錄的json)。
網(wǎng)絡(luò)模塊
網(wǎng)絡(luò)層,采用的是各節(jié)點互相長連接、斷線重連,然后維持心跳包。網(wǎng)絡(luò)框架使用的是t-io,也是oschina的知名開源項目。t-io采用了AIO的方式,在大量長連接情況下性能優(yōu)異,資源占用也很少,并且具備group功能,特別適合于做多個聯(lián)盟鏈的SaaS平臺。并且包含了心跳包、斷線重連、retry等優(yōu)秀功能。
在項目中,每個節(jié)點即是server,又是client,作為server則被其他的N-1個節(jié)點連接,作為client則去連接其他N-1個節(jié)點的server。同一個聯(lián)盟,設(shè)定一個Group,每次發(fā)消息,直接調(diào)用sendGroup方法即可。
共識模塊
分布式共識一直都是個難題。
比特幣采用了POW工作量證明,需要耗費大量的資源進行hash運算(挖礦),由礦工來完成生成Block的權(quán)利。還有一些是采用選舉投票的方式來決定誰來生成Block。分布式共識算法有好幾種,具體的可以去查查。共同的特點就是只能特定的節(jié)點來生成區(qū)塊,然后廣播給其他人。
而我這里的場景不同,這是一個聯(lián)盟,各個節(jié)點是平等的,而且性能要高。所以我不想讓每個節(jié)點都生成一個指令后,發(fā)給其他節(jié)點,再大家選舉出一個節(jié)點來搜集網(wǎng)絡(luò)上的指令組合再生成Block,太復(fù)雜了。對于學(xué)習(xí)區(qū)塊鏈的新手來說,幾乎無法完成這個模塊。
那么我這里就簡單多了,任何節(jié)點都可以構(gòu)建Block,然后全網(wǎng)廣播,只要過半節(jié)點校驗后同意即可。其他節(jié)點需要校驗格式、hash、簽名、和table的權(quán)限,校驗通過后,過半同意了,就可以構(gòu)建Block并廣播全網(wǎng),通知各節(jié)點更新Block。
生成Block后,再全網(wǎng)廣播,拉取Block,然后執(zhí)行Block內(nèi)的sql語句。
區(qū)塊信息查詢
各節(jié)點通過執(zhí)行相同的sql來實現(xiàn)一個同步的sqlite數(shù)據(jù)庫(或mysql等其他關(guān)系型數(shù)據(jù)庫),將來對數(shù)據(jù)的查詢都是直接查詢sqlite,性能高于傳統(tǒng)的區(qū)塊鏈項目。
由于各個節(jié)點都能生成Block,在高并發(fā)下會出現(xiàn)區(qū)塊不一致的情況。如果因為某些原因?qū)е骆湻植媪?#xff0c;也提供了回滾機制,sql可以回滾。原理也很簡單,你ADD一個數(shù)據(jù)時,我會在區(qū)塊里同時記錄兩個指令,一個是ADD,一個是回滾用的DELETE。同理,UPDATE時也會保存原來的舊數(shù)據(jù)。區(qū)塊里的sql落地,譬如順序執(zhí)行1-10個指令,回滾時就是從10-1執(zhí)行回滾指令。
每個節(jié)點都會記錄自己已經(jīng)同步了的區(qū)塊的值,以便隨時進行sql落地入庫。
對區(qū)塊鏈信息的查詢,那就簡單了,直接做數(shù)據(jù)庫查詢即可。相比于比特幣需要檢索整個區(qū)塊鏈的索引樹,速度和方便性就大不同了。
簡單使用說明
使用方法:先啟動md_blockchain_manager項目,然后修改application.yml里的name、appid和managerUrl和manager項目數(shù)據(jù)庫里的一一對應(yīng),作為一個節(jié)點啟動即可。
可以通過訪問localhost:8080/block?content=1來生成一個區(qū)塊,至少要啟動2個節(jié)點才行,生成Block時需要除自己外的至少過半同意才行。生成Block后就會發(fā)現(xiàn)別的節(jié)點也會自動同步自己新生成的Block。目前代碼里默認設(shè)置了一張表message,里面也只有一個字段content,相當(dāng)于一個簡單的區(qū)塊鏈記事本了。
可以通過localhost:8080/sqlite來查看sqlite里存的數(shù)據(jù),就是根據(jù)Block里的sql語句執(zhí)行后的結(jié)果。
我把項目部署到docker里了,共啟動4個節(jié)點,如圖:?
manager就是md_blockchain_manager項目,主要功能就是提供聯(lián)盟鏈內(nèi)各節(jié)點ip?
四個節(jié)點ip都寫死了,都啟動后,它們會相互全部連接起來,并維持住長連接和心跳包。?
我調(diào)用一下block項目的生成區(qū)塊接口,http://ip:port/block?content=1
別的節(jié)點會是這樣,收到block項目請求生成區(qū)塊的請求、并開始校驗,回復(fù)是否同意?
當(dāng)block項目收到過半的同意后,就開始生成區(qū)塊,并廣播給其他節(jié)點自己的新區(qū)塊,其他節(jié)點開始拉取新塊,校驗通過了則更新到本地。
這個生成區(qū)塊的接口是寫好用來測試的,正常走的流程是調(diào)用instuction接口,先生產(chǎn)符合自己需求的指令,然后組合多個指令,調(diào)用BlockController里的生成區(qū)塊接口。
項目開源地址:https://gitee.com/tianyalei/md_blockchain
總結(jié)
以上是生活随笔為你收集整理的使用Java开发一个做数据共享的联盟链思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跟班学习JavaScript第二天———
- 下一篇: 架构师小跟班:推荐一款Java在线诊断工