Boltdb学习笔记之〇--概述
更多精彩内容,请关注微信公众号:后端技术小屋
看了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, 而后者不行。
安装
go get github.com/boltdb/bolt/...
操作DB
操作DB包括创建(打开)、关闭。
代码如下:在执行bolt.Open
时,如果指定文件路径不存在,则根据路径创建一个数据库文件;否则加载该路径下的文件。使用db.Close
便可关闭DB.
package main
import (
"log"
"github.com/boltdb/bolt"
)
func main() {
// Open the my.db data file in your current directory.
// It will be created if it doesn't exist.
db, err := bolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
...
}
操作事务
Boltdb中按照是否只读将事务分为读事务和写事务。
用户使用db.View
创建读事务时需传入一个回调函数,表示读事务执行操作。如果回调函数返回的err != nil
,db.View
则会回滚该事务,并将err
透传给db.View
err := db.View(func(tx *bolt.Tx) error {
...
return nil
})
使用db.Update
可创建写事务。db.Update
如何处理错误同db.View
err := db.Batch(func(tx *bolt.Tx) error {
...
return nil
})
操作Bucket
操作Bucket包括创建Bucket、删除Bucket
创建Bucket属于写事务。这里db.Update
会创建一个写事务,写事务执行的操作是CreateBucket
,即创建一个新的Bucket
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucket([]byte("MyBucket"))
if err != nil {
return fmt.Errorf("create bucket: %s", err)
}
return nil
})
删除Bucket也属于写事务。使用上同理
db.Update(func(tx *bolt.Tx) error {
b, err := tx.DeleteBucket([]byte("MyBucket"))
if err != nil {
return fmt.Errorf("create bucket: %s", err)
}
return nil
})
操作key/value
操作key/value包括:新建/更新/删除/查询。所有的key/value对都必须属于某个具体的Bucket. 因此操作key/value之前必须找到Bucket对象。
新建/更新代码必须用写事务封装,代码如下,这里在名为MyBucket
的Bucket下新增了一对("answer", "42")
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
err := b.Put([]byte("answer"), []byte("42"))
return err
})
删除代码如下:
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
err := b.Delete([]byte("answer")
return err
})
查询代码如下:
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
v := b.Get([]byte("answer"))
fmt.Printf("The answer is: %s\n", v)
return nil
})
如何分析Boltdb
代码导读
首先是读代码,从微观到宏观的层面了解这座房屋如何建成的。代码阅读顺序是
page.go: 磁盘上的page layout,包括meta page, freelist page, branch page, leaf page。
node.go: 磁盘上的page反序列化到内存之后的数据结构,也作为B+树节点。
freelist.go: page管理, 支持page申请、释放、回滚等操作。
cursor.go: 用于访问B+树的迭代器
bucket.go: Bucket数据结构,支持创建/删除子Bucket、新建/更新/删除kv数据。
db.go.go: 用于访问DB, 支持打开/关闭DB、创建读/写事务、db file自动扩容。
更详细的代码细节将在该系列的后续内容中给出.
分析工具
Boltdb提供了一个好用的工具,可用于查看db file中每个page的内容
安装:
git clone https://github.com/boltdb/bolt
cd cmd/bolt
go build
ls ./bolt
查看所有pages状态
$ ./bolt pages /tmp/bolt.db | head
ID TYPE ITEMS OVRFLW
======== ========== ====== ======
0 meta 0
1 meta 0
2 freelist 4
3 leaf 141
4 leaf 86
5 leaf 85
6 branch 117
7 leaf 85
其中ID表示page id, TYPE为page类型,ITEMS表示其中的数据条数,OVRFLW表示该page是否溢出。
查看某个page的内容
$ ./bolt page /tmp/bolt-624750664 3 | head
Page ID: 3
Page Type: leaf
Total Size: 4096 bytes
Item Count: 141
"9874": "9874"
"9875": "9875"
"9876": "9876"
"9877": "9877"
"9878": "9878"
以上为某个leaf page的内容,底部为该page中存储的key/value对。
推荐阅读
- 一文读懂clickhouse集群监控
- redis实现分布式锁
- C/C++关键字之restrict
- 现代C++之右值语义
- 30分钟入门Vim
- 30分钟入门GDB
- STL源码分析--vector
- zookeeper client原理总结
- 推荐几个好用的效率神器
- Python乱码九问
- Linux Shell脚本攻略读书笔记
更多精彩内容,请扫码关注微信公众号:后端技术小屋。如果觉得文章对你有帮助的话,请多多分享、转发、在看。
Boltdb学习笔记之〇--概述的更多相关文章
- OGG学习笔记01-基础概述
OGG学习笔记01-基础概述 OGG(Oracle Golden Gate),最近几年在数据同步.容灾领域特别火,甚至比Oracle自己的原生产品DataGuard还要风光,主要是因为其跨平台.跨数据 ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- Flink学习笔记:Connectors概述
本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...
- JDBC学习笔记(1)——JDBC概述
JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数 ...
- Python学习笔记 :01概述
Python基础 首先推荐学习Python基础的教程和书籍 视频教程推荐南京大学张莉老师在cousera上的教程用Python玩转数据 入门教程<Python基础教程> 数据挖掘教程< ...
- Spring学习笔记之Spring概述
概述 Spring是一个java应用最广的开源框架,它是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Deve ...
- ASP.NET MVC4学习笔记之总体概述
断断续续使用ASP.NET MVC框架也有一年多了,也算积累了一些经验,唉,一直想写一些笔记好好总结一下,人太懒不想动笔,今天终于决定开始.希望自己能坚持下去. 这篇文章大体介绍ASP.NET MVC ...
- XML学习笔记(1)--XML概述
XML基本概念 XML—extensible Markup Language(可扩展标记语言) XML最基本的三个概念 1)XML语言---描述事物本身(可扩展) 2)XSL语言---展现事物表现形式 ...
- java核心技术学习笔记之一程序设计概述
Java 核心技术之一程序设计概述 一. Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...
随机推荐
- 2020ICPC·小米 网络选拔赛第一场 A.Intelligent Warehouse (DP)
题意:给你一组数,选一些数出来组成一个排列,使得每个数都能被前一个数整除,求排列的最大元素. 题解:我们先用欧拉筛筛出\(1e7\)的质数,设\(dp[i]\)表示当前选的数都是\(i\)的约数且合法 ...
- C#(winform)button去掉各种边框
仔细读完,主要在FlatAppearance属性里 1.既然是添加背景图片 所以这里应该使用 Button.BackgroudImage = "" ;来设置图片 而不应该使用 B ...
- Hexo准备---Node.js、Vue
Hexo准备---Node.js.Vue 安装node.js 1.下载node 配置node.js环境官网下载,一直next就好,非常方便. 下载官网: http://nodejs.cn/downlo ...
- Redis 集合统计(HyperLogLog)
统计功能是一类极为常见的需求,比如下面这个场景: 为了决定某个功能是否在下个迭代版本中保留,产品会要求统计页面在上新前后的 UV 作为决策依据. 简单来说就是统计一天内,某个页面的访问用户量,如果相同 ...
- vue 的 computed 属性在什么时间执行
vue 的 computed 属性在什么时间执行
- React useEffect in depth
React useEffect in depth useEffect class DogInfo extends React.Component { controller = null state = ...
- 如何在 macOS 上进行滚动截屏
如何在 macOS 上进行滚动截屏 Shift-Command-5 https://support.apple.com/zh-cn/guide/mac-help/mh26782/mac demo Xn ...
- ES Next & Arrow function & Promise & Iterator & Generator yield & Async Await
ES Next & Arrow function & Promise & Iterator & Generator yield & Async Await co ...
- NGK公链DeFi发力,Baccarat项目引爆流动性挖矿热潮
DeFi市值屡创新高,在这条康庄大道上,人们摩拳擦掌,就像90年代美国西部淘金热一般.DeFi带来的流动性挖矿构成了今年加密货币一道靓丽的风景线,而人们手握的不再是当年的锄头铲子,而是一串代码. 随着 ...
- Fast-RTPS简介
RTPS即DDS中的主要核心通信部分.它提供实时高效的去中心化publish/subscribe通信机制.是ROS-2的核心底层通信组件,也是未来机器人/无人驾驶领域一个必然的方向. 资料参考: ht ...