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工程获取数据(分别附上获取块数据,和模拟执行合约的例子)

        

 

 

 

        

 
相关文章
相关标签/搜索