`

eos chainbase状态库

    博客分类:
  • EOS
 
阅读更多
chainbase:是一个快速包含版本控制的事务数据库.chainbase最大的特点是,它可以维护一个无限层级的undo历史,从而可以方便地回滚一个事务.chainbase是为了满足区块链对事务的需求而设计的,但它也适合需要对application状态持久化以及需要undo能力的程序.

特性
1.支持多表多索引,基于boost::multi_index_container
2.状态数据可以持久化,也可在多进程之间共享
3.嵌套的事务性的写入,具备undo更改的能力

区块链application依赖一个高性能数据库,该数据库可能要在每秒发生数百万次的读写操作,而区块链的操作追求的是最终一致性,这意味着任何区块链的更改都可能被回滚,也就是说,在共识协议发挥作用之前的任何时间内,它们都是可逆的.
现有的libbitcoin数据库,拥有高性能,也是通过内存映射文件的技术,但它是高度专业化的,无法实现必要的多索引逻辑或者undo回滚历史的操作.LevelDB提供了一种简单的键值数据库,但性能表现不如内存映射文件的技术手段.

并发访问
1.在默认情况下,chainbase不提供同步操作以及那些有相同并发限制的boost::multi_index_container,这意味着两个或者以上的线程可能同时读取数据库,但所有写操作必须有互斥锁保护.多线程同时访问数据库的情况,chainbase引用boost::interprocess库作为进程间通信工具进行处理

2.boost::interprocess库(简称BIP库)提供了一套完整的进程间同步机制,是Boost并发编程常用的库,BIP库包含很多强大的功能,chainbase使用到了以下几个方面
a.内存映射文件
b.BIP库重新实现了一套数据结构容器,包括map,set,flat_map,deque,string.
c.同步机制,包括进程间共享锁,同步共享锁,文件锁

3.读锁采用的是BIP库的sharable_lock,用于执行可共享锁的任务,任务被锁定后,其他线程仍旧可以执行任务,通常用于读操作.而针对写入的事务性操作,需要采用同步机制进行处理,因此仍旧是互斥锁,但使用的是unique_lock唯一锁,任务上锁以后,这段代码无法被其他线程执行.需要注意的是,写锁时,shared_lock代码也不可被访问,这是为了防止读到处理中的数据引发前端混乱

undo操作:undo_state
1.撤回操作的对象是multi_index_container的对象,该对象是基于多表多索引的容器,可以存储各种数据结构,一般用于存储程序的状态数据.撤回的操作包括增,删,改,需要监控这些操作,转储历史版本,那么版本号reversion就是必要的.对象的历史版本内容包含reversion字段是由一个类undo_state进行描述的.

2.其次,想要监控增,删,改动作,那么每个动作变更的历史状态都要保存下来,用于保存的变量是generic_index的私有属性_indices及_stack
a.emplace:向_indices插入数据,内容是传入的multi_index_container对象构造器.同时向_stack的头元素对象的new_ids字段插入对象的id作为索引
b.modify:先检查_stack的长度,如果长度为0,则说明该队列不可用,直接中断返回.先在_stack的头元素中查询该对象,如果未查询,则操作头元素的字段old_values插入对象.然后操作_indices更改对象内容,根据结果打印异常日志
c.remove:先检查_stack长度,然后获取_stack头元素,判断传入对象id是否在new_ids.如果存在,则擦除掉.接着在头元素的old_values字段查询传入的对象id,如果能查到,则在removed_values字段新增一条数据,同时擦除old_values中的对象.在头元素的removed_values字段中确认该对象id存在,如果仍未插入成功,则手动为头元素的removed_values插入一个包含id_type和传入对象的元组对象.最后回到_indices,将该对象擦除

3.此处_indices充当的角色是真实存储最新状态数据的容器,而_stack则是用于缓存历史对象状态的容器

session:专门支持undo操作的类
//将状态恢复到当前会话之前的状态,丢弃上次修订和当前修订之间的所有更改
 void undo() {
     if( !enabled() ) return;//校验_stack长度,是否有历史数据
     
     const auto& head = _stack.back();
     
     for( auto id : head.new_ids )
     {
         _indices.erase( _indices.find( id ) );
     }
     _next_id = head.old_next_id;
     
     for( auto& item : head.old_values ) {
         //核心动作:将当前状态库_indices回退至上一个历史版本
         auto ok = _indices.modify( _indices.find( item.second.id ), [&]( value_type& v ) {
                 v = std::move( item.second );
     });
         if( !ok ) std::abort(); // uniqueness violation
     }
     
     for( auto& item : head.removed_values ) {
         //逐一恢复已删除对象至当前状态库_indices
         bool ok = _indices.emplace( std::move( item.second ) ).second;
         if( !ok ) std::abort(); // uniqueness violation
     }
     
     //_stack历史数据队列去掉一个头元素(已恢复)
     _stack.pop_back();
     --_revision;//版本号减1
 }

1.squash():合并最近两个历史版本,与git squash的操作类似
2.commit():提前当前状态的版本,会删除_stack所有之前的版本
3.undo_all():回退所有的历史操作,内部循环调用undo,直到_stack为空
4.set_version():设置版本号,要求_stack为空,且设置值不超过int64最大值

持久化处理:通过database类实现,默认情况下,数据会通过请求或当程序退出时被写入磁盘,这是通过boost::interprocess::managed_mapped_file内存映射文件技术实现的,chainbase的I/O高性能是由于这些动作是在内存中执行的,因此chainbase的容量完全取决于机器内存容量

数据库的内容可以保持在一个稳定状态,只要程序不在调用db.modify()或db.create()时中途崩溃,就意味着create及modify操作的表达式lambda的复杂性应该被降到最低.如果操作系统崩溃或者电脑断电,那么数据库将处于一个未定义(undefined)的状态,这个状态取决于操作系统能否将内存中的数据同步到磁盘上,只要可以写入磁盘chainbase就可以让数据起死回生.
class database
{
  public:
     enum open_flags {
        read_only     = 0,
        read_write    = 1
     };

     using database_index_row_count_multiset = std::multiset<std::pair<unsigned, std::string>>;

     database(const bfs::path& dir, open_flags write = read_only, uint64_t shared_file_size = 0, bool allow_dirty = false,
              pinnable_mapped_file::map_mode = pinnable_mapped_file::map_mode::mapped,
              std::vector<std::string> hugepage_paths = std::vector<std::string>());
     ~database();
     database(database&&) = default;
     database& operator=(database&&) = default;
     bool is_read_only() const { return _read_only; }
     void flush();
     void set_require_locking( bool enable_require_locking );


  private:
     pinnable_mapped_file                                        _db_file;
     bool                                                        _read_only = false;//只读标志位

     /**
      * This is a sparse list of known indices kept to accelerate creation of undo sessions
      */
     vector<abstract_index*>                                     _index_list;//已知索引列表,用于加速undo会话的创建

     /**
      * This is a full map (size 2^16) of all possible index designed for constant time lookup
      */
     vector<unique_ptr<abstract_index>>                          _index_map;//完全的索引map,用于快速查找

#ifdef CHAINBASE_CHECK_LOCKING
     int32_t                                                     _read_lock_count = 0;//读锁数量
     int32_t                                                     _write_lock_count = 0;//写锁数量
     bool                                                        _enable_require_locking = false;//是否需要上锁标志位
#endif
};


创建存储的实际数据文件是shared_memory.bin,以及存储元数据文件shared_memory.meta


EOS区块链的两种数据持久化方式分别是blocks.log日志文件和基于chainnbase的shared_memory文件
1.blocks
a.blocks.log:日志文件,区块链数据,不可逆,不可修改,只能追加
b.blocks.index:日志索引文件,加快区块查询速度,可重播blocks.log重新构建

2.state:状态数据库,基于chainbase,可程序化结构,用于缓存程序过程中的变量
reversible:可逆区块目录,基于chainbase数据库,存储未确权区块
*shared_memory.bin:内存映射文件,存储可逆区块全数据,使用talbe存储
*shared_memory.meta:对应区块元数据,不包含区块实际数据
分享到:
评论

相关推荐

    05 EOS基础构件库参考手册.chm

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    EOS6 基础构件库参考手册,介绍EOS6的相关文档,欢迎下载!

    **EOS6 基础构件库参考手册** EOS6 是一个先进的分布式操作系统平台,它为开发者提供了一套高效、安全且可扩展的基础构件库。这个基础构件库是EOS6生态系统的核心部分,允许开发者构建高性能的去中心化应用程序...

    09 EOS Report管理员手册.chm

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    普元EOS操作文档.pdf

    普元EOS操作文档.pdf 普元EOS操作文档.pdf是 Primeton EOS 开发环境的详细使用手册,该文档涵盖了 EOS 开发环境的配置、开发、调试等各个方面的知识点。 EOS初级程序员教程 Primeton EOS 是一个功能强大且灵活的...

    06 EOS管理员手册.chm

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    17 EOS6_报表教程.rar

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    15 EOS6.0三个例子包含SQL.rar

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    EOS.rar_EOS_普元_普元EOS_普元EOS教程

    7. **性能监控**:展示如何利用EOS的监控工具分析服务性能和系统状态。 8. **案例实践**:提供实际场景的案例分析,帮助理解EOS在企业实际项目中的应用。 通过学习"EOS概览",开发者不仅能深入了解普元EOS的功能...

    普元eos帮助文档

    其丰富的UI控件库使得开发者能够快速地搭建起高性能、低内存占用的应用程序。此外,NUI前端框架支持主流的浏览器,如IE6+、Firefox、Chrome等,这为项目的广泛部署提供了坚实的基础。NUI的稳定性和扩展性都非常出色...

    EOS 实现完整代码 eos-master.zip

    2. `libraries/`:这里包含了EOS的底层库,如区块链数据库接口、网络通信模块、加密算法等。 3. `plugins/`:EOS的插件系统允许开发者自定义节点行为,如添加新的API接口或者改变共识机制等。 4. `programs/`:包含...

    EOS Platform 8私服搭建指南

    - EOS仓库的部署是在Nexus服务器上进行的,其目的是为了搭建EOS Platform 8开发环境所需的私库。 - 部署EOS仓库的步骤包括登录到Nexus界面,新建Snapshot仓库和Release仓库。 -Snapshot仓库通常用于存放开发过程...

    eos.js(eos通用js库)

    EOS区块链的 通用js库 版本:15.0.2 发行说明: eosjs@15.0.2与eosio v1.0.5 - v1.0.7兼容 将格式模块中的某些类型从unsigned转换为signed:UDecimalPad - &gt; DecimalPad例如(15.0.1) 所有金额asset和extended_...

    EOS工作流(EOS Workflow)

    - **监控与审计**:EOS具备完善的流程监控功能,能够实时跟踪流程的状态,并记录下流程执行的历史信息,便于后续的分析和审计。 #### EOS工作流的实际应用 EOS工作流广泛应用于企业的各种业务场景中,例如: - **...

    20 EOS故障处理指南.rar

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    18 EOS6程序员教程.rar

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm EOS全部资料合集(包括例子) ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

    EOS NUIDemo源码_nui-demo4eos-src.zip

    5. 应用生命周期管理:理解EOS平台上应用的启动、运行、暂停、恢复和关闭等生命周期阶段,并学习如何妥善处理这些状态转换。 总的来说,通过深入分析这个源码包,开发者不仅可以掌握EOS平台上的NUI开发技术,还能...

    08 EOS Report参考手册.chm

    文档 00 EOS文档使用指南.chm :00 EOS文档使用指南.chm 01 EOS系统概述.chm :01 EOS系统概述.chm ...05 EOS基础构件库参考手册.chm :05 EOS基础构件库参考手册.chm ...........等等 EOS全部资料合集(包括例子)

Global site tag (gtag.js) - Google Analytics