说明
BoltDB是一个嵌入式key/value的数据库,即只需要将其链接到你的应用程序代码中即可使用BoltDB提供的API来高效的存取数据。而且BoltDB支持完全可序列化的ACID事务,让应用程序可以更简单的处理复杂操作。
BoltDB设计源于LMDB,具有以下特点:
- 直接使用API存取数据,没有查询语句;
- 支持完全可序列化的ACID事务,这个特性比LevelDB强;
- 数据保存在内存映射的文件里。没有wal、线程压缩和垃圾回收;
- 通过COW技术,可实现无锁的读写并发,但是无法实现无锁的写写并发,这就注定了读性能超高,但写性能一般,适合与读多写少的场景。
最后,BoltDB使用Golang开发,而且被应用于influxDB项目作为底层存储。
使用
安装BoltDB
go get github.com/boltdb/bolt/...
打开数据库
package main
import (
"log"
"github.com/boltdb/bolt"
)
func main() {
db, err := bolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
...
}
更新事务
err := db.Update(func(tx *bolt.Tx) error {
...
return nil
})
说明:
- 通过该接口可以实现数据更新操作
- 该操作会被当做一个事务来处理,如果Update()内的操作返回nil,则事务会被提交,否则事务会回滚
只读事务
err := db.View(func(tx *bolt.Tx) error {
...
return nil
})
说明:
- 通过该接口可以且只能进行数据查询操作
批量更新事务
err := db.Batch(func(tx *bolt.Tx) error {
...
return nil
})
说明:
- 通过该接口可以实现多次数据更新操作
- 所有的更新会被当做一个事务来处理,如果Update()内的操作返回nil,则事务会被提交,否则事务会回滚
手动事务管理
// Start a writable transaction.
tx, err := db.Begin(true)
if err != nil {
return err
}
defer tx.Rollback()
// Use the transaction...
_, err := tx.CreateBucket([]byte("MyBucket"))
if err != nil {
return err
}
// Commit the transaction and check for error.
if err := tx.Commit(); err != nil {
return err
}
说明:
- 自己创建事务,并管理事务的提交和回滚,没有利用BoltDB提供的封装式写法
更多
更多更好玩的用法请参考 boltdb/bolt
性能测试
为了让大家对BoltDB有一个直观的了解,我对它做了一些基本的性能测试,结果如下:
环境准备
单线程创建1000个bucket,并且每个bucket插入10w条数据,因此,总数据量约为1亿。
并发写测试
测试原理:
- 测试过程中调整写入并发数
- 保持并发数不变,调整写入次数
并发读测试
每轮测试预先创建1000个bucket,每个Bucket创建100条记录,共10w条记录,读取过程中随机选择bucket。