作者:Derek

简介

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockchain/bytom

本章介绍Derek解读-Bytom源码分析-持久化存储LevelDB

作者使用MacOS操作系统,其他平台也大同小异

Golang Version: 1.8

LevelDB介绍

比原链默认使用leveldb数据库。Leveldb是一个google实现的非常高效的kv数据库。LevelDB是单进程的服务,性能非常之高,在一台4核Q6600的CPU机器上,每秒钟写数据超过40w,而随机读的性能每秒钟超过10w。

由于Leveldb是单进程服务,不能同时有多个进程进行对一个数据库进行读写。同一时间只能有一个进程,或一个进程多并发的方式进行读写。

比原链在数据存储层上存储所有链上地址、资产交易等信息。

LevelDB的增删改查操作

LevelDB是google开发的一个高性能K/V存储,本节我们介绍下LevelDB如何对LevelDB增删改查。

package main

import (
"fmt" dbm "github.com/tendermint/tmlibs/db"
) var (
Key = "TESTKEY"
LevelDBDir = "/tmp/data"
) func main() {
db := dbm.NewDB("test", "leveldb", LevelDBDir)
defer db.Close() db.Set([]byte(Key), []byte("This is a test.")) value := db.Get([]byte(Key))
if value == nil {
return
}
fmt.Printf("key:%v, value:%v\n", Key, string(value)) db.Delete([]byte(Key))
} // Output
// key:TESTKEY, value:This is a test.

以上Output是执行该程序得到的输出结果。

该程序对leveld进行了增删改查操作。dbm.NewDB得到db对象,在/tmp/data目录下会生成一个叫test.db的目录。该目录存放该数据库的所有数据。

db.Set 设置key的value值,key不存在则新建,key存在则修改。

db.Get 得到key中value数据。

db.Delete 删除key及value的数据。

比原链的数据库

默认情况下,数据存储目录在--home参数下的data目录。以Darwin平台为例,默认数据库存储在 $HOME/Library/Bytom/data。

  • accesstoken.db token信息(钱包访问控制权限)

    core.db 核心数据库,存储主链相关数据。包括块信息、交易信息、资产信息等

    discover.db 分布式网络中端到端的节点信息
  • trusthistory.db

    txdb.db 存储交易相关信息

    txfeeds.db 目前比原链代码版本未使用该功能,暂不介绍

    wallet.db 本地钱包数据库。存储用户、资产、交易、utox等信息

以上所有数据库都由database模块管理

比原数据库接口

在比原链中数据持久化存储由database模块管理,但是持久化相关接口在protocol/store.go中

type Store interface {
BlockExist(*bc.Hash) bool GetBlock(*bc.Hash) (*types.Block, error)
GetStoreStatus() *BlockStoreState
GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error)
GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error
GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) LoadBlockIndex() (*state.BlockIndex, error)
SaveBlock(*types.Block, *bc.TransactionStatus) error
SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error
}
  • BlockExist 根据hash判断区块是否存在
  • GetBlock 根据hash获取该区块
  • GetStoreStatus 获取store的存储状态
  • GetTransactionStatus 根据hash获取该块中所有交易的状态
  • GetTransactionsUtxo 缓存与输入txs相关的所有utxo
  • GetUtxo(*bc.Hash) 根据hash获取该块内的所有utxo
  • LoadBlockIndex 加载块索引,从db中读取所有block header信息并缓存在内存中
  • SaveBlock 存储块和交易状态
  • SaveChainStatus 设置主链的状态,当节点第一次启动时,节点会根据key为blockStore的内容判断是否初始化主链。

比原链数据库key前缀

** database/leveldb/store.go **

var (
blockStoreKey = []byte("blockStore")
blockPrefix = []byte("B:")
blockHeaderPrefix = []byte("BH:")
txStatusPrefix = []byte("BTS:")
)
  • blockStoreKey 主链状态前缀
  • blockPrefix 块信息前缀
  • blockHeaderPrefix 块头信息前缀
  • txStatusPrefix 交易状态前缀

GetBlock查询块过程分析

** database/leveldb/store.go **

func (s *Store) GetBlock(hash *bc.Hash) (*types.Block, error) {
return s.cache.lookup(hash)
}

** database/leveldb/cache.go **

func (c *blockCache) lookup(hash *bc.Hash) (*types.Block, error) {
if b, ok := c.get(hash); ok {
return b, nil
} block, err := c.single.Do(hash.String(), func() (interface{}, error) {
b := c.fillFn(hash)
if b == nil {
return nil, fmt.Errorf("There are no block with given hash %s", hash.String())
} c.add(b)
return b, nil
})
if err != nil {
return nil, err
}
return block.(*types.Block), nil
}

GetBlock函数最终会执行lookup函数。lookup函数总共操作有两步:

  • 从缓存中查询hash值,如果查到则返回
  • 如果为从缓存中查询到则回调fillFn回调函数。fillFn回调函数会将从磁盘上获得到块信息存储到缓存中并返回该块的信息。

fillFn回调函数实际上调取的是database/leveldb/store.go下的GetBlock,它会从磁盘中获取block信息并返回。

Derek解读Bytom源码-持久化存储LevelDB的更多相关文章

  1. Derek解读Bytom源码-创世区块

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  2. Derek解读Bytom源码-孤块管理

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  3. Derek解读Bytom源码-Api Server接口服务

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  4. Derek解读Bytom源码-启动与停止

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  5. Derek解读Bytom源码-P2P网络 地址簿

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  6. Derek解读Bytom源码-protobuf生成比原核心代码

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  7. Derek解读Bytom源码-P2P网络 upnp端口映射

    作者:Derek 简介 Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom ...

  8. 鸿蒙OS的系统调用是如何实现的? | 解读鸿蒙源码

    本文将首先带您回顾"系统调用"的概念以及它的作用,然后从经典的Hello World开始,逐行代码层层分析--鸿蒙OS的系统调用是如何实现的. 写在前面 9月10号 华为开发者大会 ...

  9. RxJava系列6(从微观角度解读RxJava源码)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

随机推荐

  1. HTTPS 怎样保证数据传输的安全性

    大家都知道,在客户端与服务器数据传输的过程中,HTTP协议的传输是不安全的,也就是一般情况下HTTP是明文传输的.但HTTPS协议的数据传输是安全的,也就是说HTTPS数据的传输是经过加密的. 在客户 ...

  2. 使用jdk的keytool 生成CA证书的方法

    一.CA证书生成设置总共分为以下5步: 步骤: 1.根据java的keytool生成CA根证书,放在服务器 2.根据服务器CA根证书导出客户端证书 3.tomcat增加SSL配置 4.客户端IE浏览器 ...

  3. li内有span需要右浮的问题

    图一和图二换了一下span的位置,但是其页面展示是一样的,兼容性比较好的是第二种

  4. Oracle 创建表并设置主键自增

    创建数据库 CREATE TABLE STUDENT(ID NUMBER PRIMARY KEY, NAME VARCHAR(200) NOT NULL, SEX VARCHAR(200), CREA ...

  5. redis linux(centos) 安装

    前言 redis 大家都使用过, 可以安装在windows下, 也可以安装在linux下, 一般还是linux下安装比较多. 这里来介绍一下redis在linux下的安装 一. 下载 https:// ...

  6. Maven_2 本地资源库 中央存储库

    CONF window7 本地资源库: 一般默认的地址:C:\Users\Administrator\.m2 也可以修改地址:在路径{M2_HOME}\conf\setting.xml,更新 loca ...

  7. java高级工程师开放面试题集<二>

    临近年关,不少人蠢蠢欲动,有童鞋问我java后端面试会面试什么? 作为一个java后端老鸟,跌打滚爬多次被面试和面试别人,总结了一些经验,希望对大家有所帮助. 特别说明,仅仅针对工作两年以上的java ...

  8. JS判断是否是数组的四种做法

    一.前言 如何判断一个对象或一个值是否是一个数组,在面试或工作中我们常常会遇到这个问题,既然出现频率高,想着还是做个整理,那么本文主要基于几种判断方式,以及方式判断的原理,是否存在问题展开讨论. 二. ...

  9. xshell与xftp使用注意

    1.xshell报ssh服务器拒绝了密码,请再试一次 xshell登录使用的用户名不能是root,要是服务器的用户名,否则连接时会报 ssh服务器拒绝了密码,请再试一次.将root改成服务器用户名即可 ...

  10. 【esayui】扩展验证方法,控件验证

    基础验证 //页面调用方法$.extend($.fn.validatebox.defaults.rules, { 验证电话 IsPhoneRex: {validator: function (valu ...