【以下大量内容参考自boltdb 1.3.0实现分析】
bolt db 数据库文件磁盘布局
# -------------|------------|--------------|--------------------|--------------------|----------
# meta page 0 | meta page 1| freelist page| leaf/branch page 0 | leaf/branch page 1 | .....
# -------------|------------|--------------|--------------------|--------------------|----------
type pgid uint64
type page struct {
id pgid // 页面 id
flags uint16 // 标志位,区分 metaPageFlag、freelistPageFlag、branchPageFlag、leafPageFlag
count uint16 // 页面中存储的数据数量,仅在页面类型是branch以及leaf的时候起作用
overflow uint32 // 当前页面如果还不够存放数据,就会有后续页面,这个字段表示后续页面的数量
}
# 根据这个结构如何获取 data 的地址 ?, 以 meta 为例:
// meta returns a pointer to the metadata section of the page.
func (p *page) meta() *meta {
return (*meta)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)))
}
# 结构如下
# --------------页表头-------------|----页数据------------|
# | id | flags | count | overflow | data............... |
# --------------------------------|---------------------|
# meta 页面结构
type meta struct {
magic uint32 // boltdb 的magic number
version uint32 // boltdb 的版本号
pageSize uint32 // boltdb 文件的页面大小
flags uint32 // 保留字段
root bucket // 保存 boltdb 的根 bucket 的信息
freelist pgid // 保存freelist页面的页面ID
pgid pgid // 保存当前总的页面数量,即最大页面号加一
txid txid // 上一次写数据库的事务ID,可以看作是当前 boltdb 的修改版本号,每次写数据库时加1,只读时不改变
checksum uint64 // 校验码,用于校验元数据页面是否出错的
}
# 结构如下
# --------------页表头-------------|----页数据----------------------------------------|
# | id | flags | count | overflow |pageSize|flags|root|freelist|pgid|txid| checksum |
# --------------------------------|-------------------------------------------------|
freelist 页面结构
# freelist 页面结构
// txPending holds a list of pgids and corresponding allocation txns
// that are pending to be freed.
type txPending struct {
ids []pgid
alloctx []txid // txids allocating the ids
lastReleaseBegin txid // beginning txid of last matching releaseRange
}
// freelist represents a list of all pages that are available for allocation.
// It also tracks pages that have been freed but are still in use by open transactions.
type freelist struct {
freelistType FreelistType // freelist type
ids []pgid // all free and available free page ids.
allocs map[pgid]txid // mapping of txid that allocated a pgid.
pending map[txid]*txPending // mapping of soon-to-be free page ids by tx.
cache map[pgid]bool // fast lookup of all free and pending page ids.
freemaps map[uint64]pidSet // key is the size of continuous pages(span), value is a set which contains the starting pgids of same size
forwardMap map[pgid]uint64 // key is start pgid, value is its span size
backwardMap map[pgid]uint64 // key is end pgid, value is its span size
allocate func(txid txid, n int) pgid // the freelist allocate func
free_count func() int // the function which gives you free page number
mergeSpans func(ids pgids) // the mergeSpan func
getFreePageIDs func() []pgid // get free pgids func
readIDs func(pgids []pgid) // readIDs func reads list of pages and init the freelist
}
# 结构如下
# --------------页表头-------------|----页数据------------|
# | id | flags | count | overflow | free id 列表........ |
# --------------------------------|---------------------|
branch 和 left 页面结构
# branch 和 left 页面结构
// branchPageElement represents a node on a branch page.
type branchPageElement struct {
pos uint32 // 存储键相对于当前页面数据部分的偏移量
ksize uint32 // 键的大小
pgid pgid // 子节点的页面ID
}
// leafPageElement represents a node on a leaf page.
type leafPageElement struct {
flags uint32 // 标志位,为0的时候表示就是普通的叶子节点,而为1的时候表示是子bucket
pos uint32 // 存储键相对于当前页面数据部分的偏移量
ksize uint32 // 键的大小
vsize uint32 // 存储数据的大小
}
结构见下图 【图片来自 https://youjiali1995.github.io/storage/boltdb/】
mmap,几乎是所有现代的存储系统使用的核心技术之一,比如 mongo, prometheus, rocketmq 等等。这部分将总结和学习 mmap 在各个项目中的使用。
mmap优点共有一下几点:
关于 mmap 的介绍和为什么有性能优势可以参考这篇文章
PROT_READ
,表示只读原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。