数据库
1.概述
存储模块中的Block DB、State DB、History DB等都是封装后的DB对象,其具体实现要基于特定的数据库引擎,比如LevelDB、BadgerDB、TikvDB、MySQL等数据库引擎。为了实现可插拔的数据库引擎,长安链在数据库引擎之上封装了一层接口,并将LevelDB、BadgerDB、TikvDB、MySQL等数据库封装成DB provider。用户可以根据业务需求选择合适的数据库引擎作为长安链的底层存储组件。
支持的数据库类型
长安链目前支持4种数据库引擎可供选择,分别是LevelDB、BadgerDB、TikvDB、MySQL。
LevelDB,默认采用的数据库引擎,LevelDB作为一款嵌入式KV数据库,默认集成在长安链节点中,无需部署,性能也相对关系型数据要更好。
BadgerDB,作为另一种形式的KV单机数据库的实现,也是嵌入式KV数据库,性能在写入value比较大时比LevelDB更高,但是读性能可能差于LevelDB
TikvDB,作为KVDB的横向扩容版本,需要单独启动tikv服务,底层使用rocksdb,性能更高。tikv部署流程
MySQL,关系型数据库,支持schema和富查询,性能较KV数据库低,目前关系型数据库与区块链的状态数据并不能很好的结合,导致很少有区块链采用关系型数据库作为状态数据库。原因主要有两点:1.区块链需要对智能合约所读写的状态数据做严格的控制和校验,而SQL语句相对区块链来说过于灵活,难以控制;2.需要提前创建库表和索引,需要针对不同的智能合约创建不同的数据库表结构,不够灵活。目前长安链支持MySQL存储引擎,在系统数据如Block DB上支持区块元信息、交易信息的关系型语义,状态数据库支持kv的方式和智能合约编写SQL语句方式读写状态数据(world state)。
2.配置说明
节点本地配置文件chainmaker.yml中存储部分的配置说明
注:
若需使用Mysql存储,特殊配置:max_allowed_packet属性需比bc.yml中的block_size要大
临时修改:set global max_allowed_packet=210241024*10
永久修改:
vim/etc/my.cnf[mysqld]max_allowed_packet=20M
storage:store_path:../data/ledgerData#账本的存储路径,包括LevelDB、BadgerDB的数据目录,Block binary log的数据目录write_buffer_size:4#LevelDB的write_buffer_size,单位为MB,默认为4M bloom_filter_bits:10#LevelDB的布隆过滤器参数,为每个key分配的额外bit空间,默认为10,如果少于或等于0,则不开启布隆过滤。disable_historydb:false#是否禁用历史读写集的存储功能,默认为false,也就是保存历史读写集。
disable_block_file_db:false#是否禁用区块文件存储功能,默认为true,也就是未启用,新节点建议此处设置为false。logdb_segment_async:false#区块文件异步落盘与否,默认为false,也就是默认同步落盘,异步落盘时存在断电后数据损坏风险。logdb_segment_size:128#区块文件大小,单位MB,默认20MB。
#encrypt_key:"1234567890123456"#Symmetric encryption key:16 bytes key。如果pkcs11设置有值,代表打开encryption write_block_type:0#0 common write,1 quick write#bigfilter config enable_bigfilter:false#default false是否使用bigfilter,如果使用需要安装redis bigfilter_config:redis_hosts_port:"127.0.0.1:6300,127.0.0.1:6301"#redis host:port redis_password:abcpass#redis password tx_capacity:1000000000#support max transaction capacity fp_rate:0.000000001#false postive rate#RWC config enable_rwc:true#default false,是否开启滑动窗口缓存rolling_window_cache_capacity:55000#greater than max_txpool_size*1.1 disable_state_cache:false#default false,是否关闭statedb缓存,模式是打开的.state_cache_config:#statedb cache life_window:3000000000000#key/value ttl time,ns clean_window:1000000000
#间隔一定时间后清理expired keys and values(clean up),ns max_entry_size:500#每个entry的最大大小,单位byte。hard_max_cache_size:1024#最大缓存大小,单位MB。blockdb_config:#BlockDB数据库配置provider:leveldb#数据库类型,支持LevelDB,BadgerDB,TikvDB,Mysql,这里示例为LevelDB leveldb_config:#LevelDB的详细配置store_path:../data/org1/blocks write_buffer_size:4#LevelDB的write_buffer_size,单位为MB,默认为4M
bloom_filter_bits:10#LevelDB的布隆过滤器参数,为每个key分配的额外bit空间,默认为10,如果少于或等于0,则不开启布隆过滤。block_write_buffer_size:statedb_config:#StateDB数据库配置provider:sqlkv#数据库类型,支持LevelDB,BadgerDB,TikvDB,Mysql,这里示例为Mysql#或者provider:sql sqldb_config:#SQL数据库的详细配置sqldb_type:mysql#具体的RDBMS为mysql,也可以是sqlite、mssql等dsn:root:password tcp(127.0.0.1:3306)/#MySQL的数据库连接字符串max_idle_conns:10#连接池中维持的最大的空闲连接数,默认为10
max_open_conns:10#最大的可用连接数,默认为10 conn_max_lifetime:60#连接维持的最长时间,单位秒,默认为60 historydb_config:#HistoryDB数据库配置provider:badgerdb#数据库类型,支持LevelDB,BadgerDB,TikvDB,Mysql,这里示例为BadgerDB badgerdb_config:store_path:../data/org1/history compression:0#value为0不压缩,1 Snappy压缩,2 ZSTD压缩,默认为0 value_threshold:10240#单位为bytes,默认为10240 bytes resultdb_config:#ResultDB数据库配置provider:tikvdb#支持LevelDB,BadgerDB,TikvDB,Mysql tikvdb_config:
endpoints:"127.0.0.1:2379"#tikv pd server url,支持多个url,如:"192.168.1.2:2379,192.168.1.3:2379"max_batch_count:128#每次kv batch最大大小默认128 grpc_connection_count:4#chainmaker连接tikv的连接数,默认4 grpc_keep_alive_time:10#保持连接的连接数,默认10 grpc_keep_alive_timeout:3#保持连接的超时时间默认3 write_batch_size:128#每次提交tikv批次最大大小,默认128 disable_contract_eventdb:true#是否禁止合约事件存储功能,默认为true,
如果设置为false,需要配置mysql contract_eventdb_config:provider:sql#如果开启contract event db功能,需要指定provider为sql sqldb_config:sqldb_type:mysql#contract event db只支持mysql dsn:root:password tcp(127.0.0.1:3306)/#mysql的连接信息,包括用户名、密码、ip、port等
注:区块文件存储从v2.2.x(包含)以后开始支持,需注意一下几点:
区块文件存储默认未开启(>=v2.2.x),但是可以开启(设置disable_block_file_db:false),使用chainmaker-go的配置生成工具生成配置时,此处的值为false
区块文件存储是适合区块数据库大于400GB以后的场景,采用与之前方案不同的区块存储方式,以解决日益增长的区块数据导致节点速度变慢的问题(推荐优先使用),故暂时与旧版本的节点数据不兼容
区块文件存储暂时不支持归档
区块文件存储未开启时,兼容旧版本的数据
建议配置disable_block_file_db:false&logdb_segment_async:false
文件存储实现原理:
区块在到达存储模块后会进行序列化操作,为下一步区块数据落盘做准备,此时我们将区块对象中的子对象单独序列化,同时记录序列化产生字节流的长度,然后再拼接起来,就是一个序列化之后的完整区块的字节流
在序列化和拼接的时候记录子对象在区块字节流的偏移量和长度,即:某子对象在整个区块字节流的起始位置和长度,在反序列化字节流成对象的时候直接截取区块指定位置特定长度的片段,再反序列化,即可得到原始对象
区块字节流主要由区块元数据、交易、读写集、事件日志,由于区块文件存储不再删除存入的区块,同时也能具有原来WAL的效果,因此KV数据库中不再需要存储原始的区块信息,只需要存储区块原始数据在文件存储中的(区块元数据、交易、读写集、事件日志)索引即可
长安链在文件存储中定义了区块存储的文件.fdb文件,用于存放每次产生的区块文件,如下图:
在读取区块时,从KV数据库中获取区块所在在fdb文件名和在该文件中的起始和长度,然后再反序列化即可
在读取区块中的数据如交易时,同样获取该交易所在fdb文件名和在该文件中的起始和长度,然后再反序列化即可
文件存储可以将区块存储对于磁盘的KV数据库随机写,变成对于磁盘的顺序写,可以降低磁盘的读写压力,同时降低KV数据库的压力