【许晓笛】EOS 数据库与持久化 API —— 架构
EOS 数据库结构详解
在 EOS 中,智能合约执行完毕后,所占用的内存会释放。程序中的所有变量都会丢失。如果智能合约里要持久地记录信息,比如游戏智能合约要记录每位用户游戏记录,本次合约执行完毕后数据不能丢失,就需要将数据存储到 EOS 数据库中。与数据库交互的 API 被官方称为 Persistence API,中文可以叫做持久化 API。下图说明了 EOS 智能合约在执行 Action 时,与数据库的交互过程。
为了方便智能合约与 EOS 数据库的交互,EOS 仿造了 Boost 库中的 Multi-Index Containers
,开发了 C++ 类:eosio::multi_index(以下简称
multi_index`),中文可以叫做多索引列表类。
multi_index
头文件地址:
https://github.com/EOSIO/eos/blob/master/contracts/eosiolib/multi_index.hpp
在 EOS 见证人硬盘中,为每个账户都预留了数据库空间(大小与代币持有量有关),每个账户名下可以建立多个数据表。智能合约无法直接操作存储在见证人硬盘中的数据表,需要使用multi_index
作为中间工具(或者叫容器),每个multi_index
实例都与一个特定账户的特定数据表进行交互(取决于实例化时的参数)。EOS智能合约与EOS数据库的数据交互如下图所示。
数据表
multi_index
是一个非常方便的数据库交互容器,可以存储任何 C++ 数据类型。每一个multi_index
都相当于传统数据库的一个数据表(table),但将传统数据库的行与列的形式改为了单纯的列。也就是说multi_index
是一个线性排列的表,只有一列,每一行都只存储一个对象。但是一般来说multi_index
存储的对象都是结构体或者类,里面含有多个成员变量,所以multi_index
存储数据的灵活性也是不亚于传统数据库的。
我们使用官方的“汽车维修店”示例,我们建立一个数据表,储存每个汽车维修店客户的账户名、保养时间、车辆里程。那么multi_index
数据表储存的项目中,每个都是如下的结构体:
struct service_rec { uint64_t pkey; // 主键 account_name customer; // 车主用户名 uint32_t service_date; // 维修保养时间 uint32_t odometer; // 车辆里程 };
在传统数据库中,需要建立一个 4 列的数据表,用来储存每个用户的这个 4 个数据,而multi_index
的每个数据表只有一列,只存储每个用户的 service_rec
整个结构体即可。下图为multi_index
数据结构。
多索引
首先,每个数据表要有一组主键,主键必须是无符号 64 位整数类型(64-bit integer),这就是上面的service_rec
结构体中第一个变量为uint64_t
类型的原因。在数据表中,所有的对象就是按照主键升序排列的,小的在前,大的在后。主键可以是有意义的,也可以是没有意义的,让系统产生一个在这个数据表中没有被使用的主键即可。为了设置主键,我们需要在之前的service_rec
结构体添加一个叫做primary_key()
的成员函数函数的返回值为主键。
auto primary_key()const { return pkey; }
这样就将pkey
这个变量设置成了主键。
multi_index
从字面上看就是能使用多个索引的数据表。EOS 中,每个multi_index
或者说每个数据表都可以设置最多16个索引。索引相当于使用特定的方式给数据表中的对象重新排序。比如在我们经常使用的 windows 文件管理器中,可以按照文件名排序、按照文件修改时间排序、按照文件大小排序,这就有了3个索引。EOS 数据库索引更加灵活,可以单独按照结构体中的某个变量索引,也可以将变量之间的运算结果(函数输出)进行索引。如果我们想使用车主用户名
进行索引,需要在结构体中添加一个get_customer()
成员函数,函数的返回值为索引变量。
account_name get_customer()const { return customer; }
这样就将customer
这个变量设置成了数据表的一个索引,下图右侧为customer
索引。
迭代器
multi_index
是如何操作数据表中的每个对象的呢?答案是 Iterators(迭代器)。大家可以搜索 “C++ 迭代器”或者设计模式中的“迭代器模式”来了解迭代器的设计思路。在 EOS 数据库中,我更愿意将迭代器比喻为一个“电梯”,在整个数据表中上下穿梭。所有对数据的操作必须通过迭代器完成。典型的数据修改过程是这样的:首先使用迭代器的find()
方法,在特定的索引中寻找需要的数据,比如在车主用户名索引中寻找某个用户。迭代器会移动到需要的数据对象上。然后就可以使用迭代器的modify()
方法修改当前迭代器对应的数据。下图为迭代器指向用户 Sue 的情况。
本篇文章介绍了 EOS 数据库的基本结构,以后的文章会详细介绍 EOS 数据库使用实战,敬请期待。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android 自定义 View 之卷尺
如果你的项目是健康类的 APP,卷尺功能必不可少,今天推荐三个卷尺库,供大家借鉴和学习。 1、RulerView 简介 一系列卷尺控件,包含:基本卷尺控件(体重尺,或其它)、金额卷尺控件、时间卷尺控件。Demo 中,分别用三个控件,高仿了薄荷健康的体重尺、团贷网的金额尺、海康威视下萤石云视频的时间尺。 效果预览 源码地址 https://github.com/zjun615/RulerView 2、RulerView 简介 一个可以滑动选择的尺子 View,可以选择体重身高等信息,通过刷新当前屏幕模拟滑动效果,达到暂用内存最小的目的。 效果预览 源码地址 https://github.com/superSp/RulerView 3、Android-ruler-picker 简介 Android 自定义视图,使用标尺从给定范围中选取数字。高度可定制,更改指针之间的宽度,高度,颜色,距离。以 XML 格式更改标尺中文本的颜色和 size,或者从 Java 或 Kotlin 代码中动态更改。 效果预览 源码地址 https://github.com/kevalpatel2106/andro...
- 下一篇
【许晓笛】EOS 系统架构图解
其实没有那么复杂 相信关心 EOS 系统的同学肯定见过下面这张蓝图。对,目前只是一个蓝图,而且以 BM 的尿性,肯定在心理已经把这张图改的面目全非了(比如图中的 eosd 早就改名了)。所以这张图只能作为未来 EOS 发展方向的参考而已,目前的 EOS 还远没有这么复杂和完善。 了解系统架构之前我们先看看目前 EOS 系统的主要组成部分: nodeos: EOS 系统的核心进程,也就是所谓的“节点”。运行时可以配置插件: producer_plugin(见证人插件):见证人必须使用这个插件,普通节点不需要。 wallet_plugin(钱包插件):使用这个插件就可以省去 keosd 钱包工具。 wallet_api_plugin(钱包接口插件):给钱包插件提供接口。 chain_api_plugin(区块链接口插件):提供区块链数据接口。 http_plugin(http 插件):提供 http 接口。 account_history_api_plugin(账户历史接口):提供账户历史查询接口。 cleos:本地的命令行工具,通过命令行与真人用户交互,并与节点(nodeos)的 RES...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果