更多精彩内容,请关注微信公众号:后端技术小屋

看了boltdb也有一阵子了,看完之后总想写点什么,因为感觉到这可能是个不小的坑,所以迟迟没有动笔(没错我的拖延症又犯了..)。最近有一种流行的说法:如果一个东西不能把它讲清楚,便不能说你学会了它。因为看起来会和真的会之间有一个巨大的鸿沟,想跨越这个鸿沟便需要不断的提问、思考与输出,这是个相对枯燥但绝对值得的过程,因此趁着周末两天的完整时间正式开始挖坑。

什么是boltdb

Boltdb是一个go语言开发的嵌入式kv数据库。其实现相对简单:

  • 不支持网络请求和SQL查询,因此也就没有了网络交互、词法分析、语法分析、查询优化等成熟数据库中必不可少的功能。
  • 使用了比较少见的shadow page技术,只支持一个writer和多个reader,在这种约束下,事务的隔离级别为可串行话,并发控制也比较简单
  • 使用mmap将内存与磁盘建立映射,由OS管理磁盘page load到内存的过程,大大减少了boltdb手动管理的复杂度。

Boltdb所有代码加起来才1W行,但是麻雀虽小五脏俱全,非常适合用来学习数据库中的一些基本原理和概念,例如page、transanction、cursor等。

值得一提的是,Boltdb还是etcd底层的kv存储,目前Boltdb原仓库(https://github.com/boltdb/bolt)已经是read-only状态。而etcd维护了一个fork(https://github.com/etcd-io/bbolt), 主要是为了继续增强可靠性、稳定性和性能。

如何使用boltdb

数据模型

在使用boltdb之前,我们需要对其数据模型有个直观的了解。以下是boltdb与关系型数据库的数据模型简单类比:

boltdb中的概念 关系型数据库中的概念
DB database
Bucket table
key value pair Tuple

Boltdb中的Bucket虽然可简单类比成关系型数据中table,有一点却不相同:前者可嵌套创建Bucket, 即一个Bucket下还可创建子Bucket, 而后者不行。

安装

  1. go get github.com/boltdb/bolt/...

操作DB

操作DB包括创建(打开)、关闭。

代码如下:在执行bolt.Open时,如果指定文件路径不存在,则根据路径创建一个数据库文件;否则加载该路径下的文件。使用db.Close便可关闭DB.

  1. package main
  2. import (
  3. "log"
  4. "github.com/boltdb/bolt"
  5. )
  6. func main() {
  7. // Open the my.db data file in your current directory.
  8. // It will be created if it doesn't exist.
  9. db, err := bolt.Open("my.db", 0600, nil)
  10. if err != nil {
  11. log.Fatal(err)
  12. }
  13. defer db.Close()
  14. ...
  15. }

操作事务

Boltdb中按照是否只读将事务分为读事务和写事务。

用户使用db.View创建读事务时需传入一个回调函数,表示读事务执行操作。如果回调函数返回的err != nildb.View则会回滚该事务,并将err透传给db.View

  1. err := db.View(func(tx *bolt.Tx) error {
  2. ...
  3. return nil
  4. })

使用db.Update可创建写事务。db.Update如何处理错误同db.View

  1. err := db.Batch(func(tx *bolt.Tx) error {
  2. ...
  3. return nil
  4. })

操作Bucket

操作Bucket包括创建Bucket、删除Bucket

创建Bucket属于写事务。这里db.Update会创建一个写事务,写事务执行的操作是CreateBucket,即创建一个新的Bucket

  1. db.Update(func(tx *bolt.Tx) error {
  2. b, err := tx.CreateBucket([]byte("MyBucket"))
  3. if err != nil {
  4. return fmt.Errorf("create bucket: %s", err)
  5. }
  6. return nil
  7. })

删除Bucket也属于写事务。使用上同理

  1. db.Update(func(tx *bolt.Tx) error {
  2. b, err := tx.DeleteBucket([]byte("MyBucket"))
  3. if err != nil {
  4. return fmt.Errorf("create bucket: %s", err)
  5. }
  6. return nil
  7. })

操作key/value

操作key/value包括:新建/更新/删除/查询。所有的key/value对都必须属于某个具体的Bucket. 因此操作key/value之前必须找到Bucket对象。

新建/更新代码必须用写事务封装,代码如下,这里在名为MyBucket的Bucket下新增了一对("answer", "42")

  1. db.Update(func(tx *bolt.Tx) error {
  2. b := tx.Bucket([]byte("MyBucket"))
  3. err := b.Put([]byte("answer"), []byte("42"))
  4. return err
  5. })

删除代码如下:

  1. db.Update(func(tx *bolt.Tx) error {
  2. b := tx.Bucket([]byte("MyBucket"))
  3. err := b.Delete([]byte("answer")
  4. return err
  5. })

查询代码如下:

  1. db.View(func(tx *bolt.Tx) error {
  2. b := tx.Bucket([]byte("MyBucket"))
  3. v := b.Get([]byte("answer"))
  4. fmt.Printf("The answer is: %s\n", v)
  5. return nil
  6. })

如何分析Boltdb

代码导读

首先是读代码,从微观到宏观的层面了解这座房屋如何建成的。代码阅读顺序是

  1. page.go: 磁盘上的page layout,包括meta page, freelist page, branch page, leaf page
  2. node.go: 磁盘上的page反序列化到内存之后的数据结构,也作为B+树节点。
  3. freelist.go: page管理, 支持page申请、释放、回滚等操作。
  4. cursor.go: 用于访问B+树的迭代器
  5. bucket.go: Bucket数据结构,支持创建/删除子Bucket、新建/更新/删除kv数据。
  6. db.go.go: 用于访问DB, 支持打开/关闭DB、创建读/写事务、db file自动扩容。

更详细的代码细节将在该系列的后续内容中给出.

分析工具

Boltdb提供了一个好用的工具,可用于查看db file中每个page的内容

安装:

  1. git clone https://github.com/boltdb/bolt
  2. cd cmd/bolt
  3. go build
  4. ls ./bolt

查看所有pages状态

  1. $ ./bolt pages /tmp/bolt.db | head
  2. ID TYPE ITEMS OVRFLW
  3. ======== ========== ====== ======
  4. 0 meta 0
  5. 1 meta 0
  6. 2 freelist 4
  7. 3 leaf 141
  8. 4 leaf 86
  9. 5 leaf 85
  10. 6 branch 117
  11. 7 leaf 85

其中ID表示page id, TYPE为page类型,ITEMS表示其中的数据条数,OVRFLW表示该page是否溢出。

查看某个page的内容

  1. $ ./bolt page /tmp/bolt-624750664 3 | head
  2. Page ID: 3
  3. Page Type: leaf
  4. Total Size: 4096 bytes
  5. Item Count: 141
  6. "9874": "9874"
  7. "9875": "9875"
  8. "9876": "9876"
  9. "9877": "9877"
  10. "9878": "9878"

以上为某个leaf page的内容,底部为该page中存储的key/value对。

推荐阅读

更多精彩内容,请扫码关注微信公众号:后端技术小屋。如果觉得文章对你有帮助的话,请多多分享、转发、在看。

Boltdb学习笔记之〇--概述的更多相关文章

  1. OGG学习笔记01-基础概述

    OGG学习笔记01-基础概述 OGG(Oracle Golden Gate),最近几年在数据同步.容灾领域特别火,甚至比Oracle自己的原生产品DataGuard还要风光,主要是因为其跨平台.跨数据 ...

  2. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  3. Flink学习笔记:Connectors概述

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  4. JDBC学习笔记(1)——JDBC概述

    JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数 ...

  5. Python学习笔记 :01概述

    Python基础 首先推荐学习Python基础的教程和书籍 视频教程推荐南京大学张莉老师在cousera上的教程用Python玩转数据 入门教程<Python基础教程> 数据挖掘教程< ...

  6. Spring学习笔记之Spring概述

    概述   Spring是一个java应用最广的开源框架,它是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Deve ...

  7. ASP.NET MVC4学习笔记之总体概述

    断断续续使用ASP.NET MVC框架也有一年多了,也算积累了一些经验,唉,一直想写一些笔记好好总结一下,人太懒不想动笔,今天终于决定开始.希望自己能坚持下去. 这篇文章大体介绍ASP.NET MVC ...

  8. XML学习笔记(1)--XML概述

    XML基本概念 XML—extensible Markup Language(可扩展标记语言) XML最基本的三个概念 1)XML语言---描述事物本身(可扩展) 2)XSL语言---展现事物表现形式 ...

  9. java核心技术学习笔记之一程序设计概述

    Java 核心技术之一程序设计概述 一.   Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...

随机推荐

  1. Databricks 第11篇:Spark SQL 查询(行转列、列转行、Lateral View、排序)

    本文分享在Azure Databricks中如何实现行转列和列转行. 一,行转列 在分组中,把每个分组中的某一列的数据连接在一起: collect_list:把一个分组中的列合成为数组,数据不去重,格 ...

  2. MySQL 启动流程及配置管理

    目录 MySQL 启动关闭流程 启动数据库 关闭数据库 MySQL 配置管理 预编译阶段 配置文件 命令行 MySQL 配置文件 配置文件的位置和优先级 配置文件的优先级测试 配置文件的生效顺序 配置 ...

  3. Python——Django框架——django-simple-captcha(验证码)

    一.引用 包 pip install django-simple-captcha 二.将captcha加入setting的 INSTALLED_APPS 三.运行python manager.py m ...

  4. Keepalived+LVS实现LNMP网站的高可用部署

    Keepalived+LVS实现LNMP网站的高可用部署   项目需求   当我们访问某个网站的时候可以在浏览器中输入IP或者域名链接到Web Server进行访问,如果这个Web Server挂了, ...

  5. kubernetes进阶(四)服务暴露-ingress控制器之traefik

    上一章我们测试了在集群内部解析service名称, 下面我们测试在集群外部解析: 根本解析不到,因为我们外部用的dns是10.4.7.11,也就是我们的自建bind dns,这个DNS服务器上也没有响 ...

  6. 鸟哥的linux私房菜——第十二章学习(Shell Scripts)

    第十二章  Shell Scripts 1.0).什么是shell scripts? script 是"脚本.剧本"的意思.整句话是说, shell script 是针对 shel ...

  7. hardsource bug

    hardsource bug webpack crashed bug memory stackoverflow [hardsource:32210703] Could not freeze refs ...

  8. how to use brew install gpg

    how to use brew install gpg https://formulae.brew.sh/formula/gnupg $ brew install gnupg https://gith ...

  9. macOS 需要更新软件才能连接到 iOS 设备

    macOS 需要更新软件才能连接到 iOS 设备 更新 Mac 上的软件 如果您在 iPhone.iPad 或 iPod touch 上看到"需要更新软件才能连接到 iOS 设备" ...

  10. js swap array

    js swap array ES6 swap array 就地交换 no need let , const [ b, a, ] = [ a, b, ]; // ES6 swap const arr = ...