Notes on BoltDB

2022-03-10 00:00:00 事务 的是 内存 写入 递归

BoltDB 实现了一个 COW BTree, 本身功能比较简单, 代码也比较简洁。我们进入代码之前,可以先讲讲它的大致流程。

这篇文章写的时候,已经有一篇很好的博客了:youjiali1995.github.io/

我不打算讲的那么细,就介绍一下大致的流程。

API

在讨论实现之前,先要理解 boltdb api, 庆幸的是,这部分逻辑比较简单,可以看看这里:zupzup.org/boltdb-examp

磁盘读写

BoltDB 用 pwrite(3) 来写盘,用 mmap(2) 来读盘。它会先 mmap 映射一块比较大的空间,然后每次写的时候,调用 pwrite(3) 来写。

这里要说到 Buffer 管理了。成熟的存储引擎大部分自己实现了一份 Buffer Pool Manager 来管理内存。BoltDB 比较小巧,利用了 mmap(2) 的文件映射,在只读模式下打开数据库文件,然后读取对应的内容。

Golang 的 syscall.Mmap 有 mmap 的功能,但是 CGo 和 syscall.Mmap 申请的内存都不由 Go runtime 管,应该是直接由 OS 管的你需要手动的去负责它们,比如下面的 case:

mmap 可以映射大于本文件的空间,pwrite 写大于文件的空间的时候,行为类似 lseek,会把文件撑大。db 的元信息会记录文件分配的 size, 那么,BoltDB 会重新调用 DB.mmap,来重新映射。这个时候 BoltDB 会对内存的内容走一次 dereference,这个调用会把 mmap 的内容拷贝一份,然后解除对 mmap 的 []byte 的引用。

磁盘结构

别的文章应该已经介绍过磁盘结构详细的 align 了,我就讲讲大致流程。

bolt 的磁盘结构以 page 为组织单位,page 的大小是

page 有下面几种:

const (
	branchPageFlag   = 0x01
	leafPageFlag     = 0x02
	metaPageFlag     = 0x04
	freelistPageFlag = 0x10
)

相关文章