Commit 34b791b6 authored by 张振华's avatar 张振华

add files

parent 2660eff6
-- "a/Store\346\226\260\345\242\236\346\224\257\346\214\201MVCC\347\232\204KVDB\345\256\236\347\216\260.md"
# 一、现状 #
# 一、现状 #
## 1.Store与外部的交互消息接口 ##
![Store接口时序](./resource/kvdb-sequence.png)
###EventStoreSet
该消息接口实际未被调用
###EventStoreGet
(1)接口由rpc接口调用时,逐层调用,比如GetAddrOverView/GetBalance/GetTokenBalance等,调用到channelClient的accountdb.LoadAccounts、accountdb.LoadExecAccountQueue等接口时,触发调用QueueProtocol的StoreGet接口,触发向Store发起EventStoreGet消息。
(2)执行器框架调用StateDB.Get接口时,如果系统配置不支持MVCC,则将通过EventStoreGet消息接口向Store发起数据查询。
Store在收到EventStoreGet消息时,将根据系统配置调用KVDB或者Mavl的Get接口查询数据,并返回结果。
###EventStoreMemSet
当同步区块或者生成区块时,Chain模块将调用connectBlock->ExecBlock->ExecTx->ExecKVMemSet将执行区块交易的kvset结果通过消息EventStoreMemSet写入Store的缓存。
Store在收到EventStoreMemSet消息时,将根据系统配置调用KVDB或者Mavl的MemSet接口将中间结果放入缓存,并返回kvset对应的StateHash。
###EventStoreRollback
Chain在ExecBlock的处理中,校验EventStoreMemSet响应消息中的StateHash,如果不一致,则触发ExecKVSetRollback调用,将通过EventStoreRollback消息发起回滚。
Store收到回滚消息后,会将上一步缓存的内容删除。
###EventStoreCommit
Chain在ExecBlock的处理中,校验EventStoreMemSet响应消息中的StateHash,如果一致,且后续执行正确,触发ExecKVSetCommit调用,将通过EventStoreCommit消息,通知Store持久化对应数据,Store根据系统配置调用KVDB或者Mavl的Commit接口将数据落盘。
###EventStoreGetTotalCoins
RPC接口调用GetTotalCoins,将通过channelClient调用accountdb.GetTotalCoins接口->调用QueueProtocol的StoreGetTotalCoins接口->通过消息EventStoreGetTotalCoins向Store发起数据查询
Store目前只有在配置为Mavl时,才支持该消息接口。(Mval实现了IterateRangeByStateHash接口,KVDB未实现该接口)
## 2.Store相关的类图关系 ##
![Store类图结构](./resource/kvdb-class.png)
##配置文件中和Store相关的配置
[store]
name="mavl"
driver="leveldb"
dbPath="datadir/kvdb"
dbCache=128
##结合类图关系有如下要点说明:
1.Store根据系统配置决定选择KVStore还是Store(Mavl)。
2.Store的底层最终使用的db类型根据配置文件来定,可以是GoLevelDB或者GoMemDB,它们都实现的DB interface。
3.KVStore的实现中,对数据的最新值进行存储,无法保存KV历史值,不能进行版本回滚。
4.Store(Mval)的实现中,使用merkel avl树形结构存储数据,可以通过statehash索引主键的历史值,但树形结构需要不断的建树、销毁来应对数据变更及查询,当存储数据量多到一定程度后,程序运行速度越来越慢,整体性能受此影响比较大。
## 3.MVCC现状
![mvcc现状](./resource/mvcc.png)
上图展示了新增区块和删除区块的主要处理逻辑及消息交互。
###MVCC的控制开关
[exec]
enableMVCC=true
上述字段置为true,则说明系统开启了MVCC能力。
开启该功能,需要重新开始同步区块,因为系统对于数据的存储格式及存储位置都有变化调整,如果不重新开始,会出现问题。
###新增区块
1.ExecBlock的处理中,通过EventExecTxList触发执行器,执行交易(检查交易,处理手续费,调用具体执行器执行交易),获得交易执行结果KV及日志,存储在receipts,并将kv及StateHash写入Store数据库(通过EventStoreMemSet、EventStoreRollback、EventStoreCommit几个消息触发,分为Set-获得stateHash、Rollback-失败回滚、Commit-提交存储几个步骤)。
2.AddTxs将tx信息(KV)保存到本地数据库,其中要保存的KV数据,经过执行器的处理,如果系统配置为支持MVCC,则对相关KV按MVCC的处理方式进行改造,结果存储本地数据库;也包括手续费信息:TotalFeeKey:hash->fee
关于AddMVCC的处理过程描述如下:
1).首先从本地数据库使用prevHash来获得对应的version
本地数据库中的对应关系:.-mvcc-m.hash->version
校验版本号信息是对的(hash对应的version与preHash对应的preVersion相差1)
2).SetVersionKV
按如下对应的key-value关系,加入kvset
.-mvcc-m.hash->version
.-mvcc-m.version.000000000000xx->hash
3).对于原有的kv进行GetSaveKV处理,生成MVCC的对应version的kv数据,并加入kvset
.-mvcc-.d.key.version->value
4).生成对应版本的versionkeylist数据,并加入kvset
.-mvcc-.m.versionkl.000000000000xx->delkeys
这个数据用于回滚删除数据。
###删除区块
1.从本地数据中,通过批量删除tx信息
通过EventDelBlock消息触发执行器执行删除交易,获得要删除的kv的正确格式,如果系统配置为支持MVCC,则相关kv要使用DelMVCC处理改造,才能从本地数据库中正确删除;也包括要删除的手续费信息:TotalFeeKey:hash->fee
关于DelMVCC的处理过程描述如下:
1).获取最大的version,检查与要删除的version相等。(删除区块必须从最高区块开始顺序删除)。
2).DelVersionKV
按如下对应的key-value关系,加入要删除的kvset
.-mvcc-m.hash->version
.-mvcc-m.version.000000000000xx->hash
2.从db中删除block相关的信息
###开启MVCC与关闭MVCC时的数据读写区别
![kvdb-mvcc示意图](./resource/mvcc-diff.png)
# 二、需求 #
针对Store模块,需要建立一种支持MVCC机制的KVDB实现,达到以下目的:
1.历史数据可以保留下来,供查询使用,并能够支持数据回滚。
2.支持MVCC机制,除了保留下来历史版本数据,还可以把多版本数据存储在结构是线性平铺的KV数据库中,不需要使用复杂的树形结构来维护数据,对于系统性能提升有帮助,即使数据量达到一定程度,系统性能不发生明显的下降。
# 三、方案描述 #
##配置文件中和Store相关的如下配置增加取值
[store]
name="kvmvcc"
driver="leveldb"
dbPath="datadir/kvdb"
dbCache=128
当上述配置为kvmvcc时,如下配置项自动失效(值强制设定为false):
[exec]
enableMVCC=true
##当配置为kvmvcc时,Store将按照如下方式进行statedb数据的维护
![kvdb-mvcc示意图](./resource/kvdb-mvcc.png)
###1.增加区块
Store收到EventStoreMemSet,会将收到的kvset数据打包生成hash(N)(假定新生成的块高为N),并和前一区块的StateHash(N-1)一起生成StateHash(N),即StateHash(N)=hash(StateHash(N-1)+hash(N))。Store将StateHash(N)及对应的version(height)关系数据存入statedb,将增加了MVCC版本号信息的KVSet数据存入statedb,将存入的KVSet的KeyVersionList数据存入statedb(用于在回滚区块时删除数据使用)。
###2.删除区块(回滚)
Store需要新增接口EventStoreDel,按照要删除的区块高度height,StateHash信息,删除在statedb中存储的对应version(height)的KVSet数据(先找到KeyVersionList数据,然后根据列表进行删除即可)。
删除区块的mvcc数据时,遵循倒序删除的规则,比如生成区块数据是0->1->2->3,删除区块数据只能从顶部开始删0->1->2->3->3(删除)->3'->4...
###3.查询数据
当Store收到EventStoreGet消息,可以根据携带的StateHash或者height信息,从statedb中查找相应的key对应的value的值,查询时,key要拼接上version信息(height),以便查找到正确的版本数据。
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment