golang高性能LSM键值存储引擎插件库moss的使用
golang高性能LSM键值存储引擎插件库moss的使用
moss简介
moss是一个简单、快速、可持久化的有序键值集合实现,100%使用Golang编写。moss代表"memory-oriented sorted segments"(面向内存的排序段)。
主要特性
- 有序键值集合API
- 100% Go实现
- 键范围迭代器
- 快照提供隔离读取
- 通过批处理API进行原子变更
- 合并操作允许对写密集型用例进行读-计算-写优化(例如更新计数器)
- 并发读写不会相互阻塞
- 子集合允许原子性地分组多个相关集合
- 可选的高级API以避免额外的内存拷贝
- 可选的底层存储实现"mossStore",使用追加写入设计和mmap()读取,具有可配置的压缩策略
- mossStore支持以只读方式导航到之前的提交点,并支持回滚到之前的提交点
- 可选持久化钩子,允许高级用户提供底层存储实现的回写缓存
- 事件回调允许监控异步任务
- 单元测试
- 模糊测试
- moss存储诊断工具:mossScope
许可证
Apache 2.0
使用示例
基本用法
import "github.com/couchbase/moss"
// 创建新集合
c, err := moss.NewCollection(moss.CollectionOptions{})
c.Start()
defer c.Close()
// 创建批处理
batch, err := c.NewBatch(0, 0)
defer batch.Close()
// 添加键值对
batch.Set([]byte("car-0"), []byte("tesla"))
batch.Set([]byte("car-1"), []byte("honda"))
// 执行批处理
err = c.ExecuteBatch(batch, moss.WriteOptions{})
// 获取快照
ss, err := c.Snapshot()
defer ss.Close()
ropts := moss.ReadOptions{}
// 从快照读取
val0, err := ss.Get([]byte("car-0"), ropts) // val0 == []byte("tesla").
valX, err := ss.Get([]byte("car-not-there"), ropts) // valX == nil.
// 也可以直接从集合读取
val1, err := c.Get([]byte("car-1"), ropts) // val1 == []byte("honda").
持久化存储
// 打开持久化存储集合
store, collection, err := moss.OpenStoreCollection(directoryPath,
moss.StoreOptions{}, moss.StorePersistOptions{})
设计原理
设计类似于(大大简化的)LSM树,具有一堆已排序的不可变键值数组或"段"。
为了合并下一批键值变更,首先将传入的键值条目排序到一个不可变的"段"中,然后原子性地推送到段堆栈的顶部。
对于读取器,堆栈中较高的段将遮蔽较低段中相同键的条目。
一个异步goroutine(“合并器”)将不断合并N个排序段以保持堆栈高度较低。
在最佳情况下,剩余的一个大的排序段将在内存使用上高效,并且对于二分查找和范围迭代也高效。
当堆栈高度>1时,使用N路堆合并实现迭代。
在此设计中,每当需要"修改"堆栈时,通过写时复制方法将段堆栈视为不可变。因此,多个读取器和写入器不会相互阻塞,获取快照也是类似的廉价操作,只需克隆堆栈。
限制和注意事项
注意:批处理中的键必须是唯一的。也就是说,不支持myBatch.Set(“x”,“foo”); myBatch.Set(“x”,“bar”)。不自然满足此要求的应用程序可以维护自己的map[key]val数据结构以确保此唯一性约束。
最大键长度为2^24(使用24位跟踪键长度)。
最大值长度为2^28(使用28位跟踪值长度)。
每个键值操作的元数据开销为16字节。
读取性能特征大致为O(log N)用于键值检索。
写入性能特征大致为O(M log M),其中M是调用ExecuteBatch()时批处理中的变更数。
错误处理
请注意,moss的后台goroutine可能会遇到错误,例如在可选持久化操作期间。为了收到这些情况的通知,您的应用程序可以提供(强烈推荐)一个可选的CollectionOptions.OnError回调函数,moss将调用该函数。
日志记录
请参阅可选的CollectionOptions.Log回调函数和CollectionOptions.Debug标志。
性能
可以运行go test -bench=.
进行一些基本性能测试。
每个性能测试通常会输出如下内容:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
spec: {numItems:1000000 keySize:20 valSize:100 batchSize:100 randomLoad:false noCopyValue:false accesses:[]}
open || time: 0 (ms) | 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s
load || time: 840 (ms) | 1190476 wop/s | 139508 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 1190476 wop/s | 139508 wkb/s | 0 rop/s | 0 rkb/s
drain || time: 609 (ms) | 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 690131 wop/s | 80874 wkb/s | 0 rop/s | 0 rkb/s
close || time: 0 (ms) | 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 690131 wop/s | 80874 wkb/s | 0 rop/s | 0 rkb/s
reopen || time: 0 (ms) | 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 690131 wop/s | 80874 wkb/s | 0 rop/s | 0 rkb/s
iter || time: 81 (ms) | 0 wop/s | 0 wkb/s | 12344456 rop/s | 1446616 rkb/s || cumulative: 690131 wop/s | 80874 wkb/s | 12344456 rop/s | 1446616 rkb/s
close || time: 2 (ms) | 0 wop/s | 0 wkb/s | 0 rop/s | 0 rkb/s || cumulative: 690131 wop/s | 80874 wkb/s | 12344456 rop/s | 1446616 rkb/s
total time: 1532 (ms)
file size: 135 (MB), amplification: 1.133
BenchmarkStore_numItems1M_keySize20_valSize100_batchSize100-8
测试包含多个阶段:
- open - 打开全新的moss存储实例
- load - 加载N个顺序键的时间
- drain - 加载后持久化完成的额外时间
- close - 关闭moss存储实例的时间
- reopen - 重新打开moss存储实例的时间(OS/文件系统缓存仍然有效)
- iter - 顺序迭代键值项的时间
- access - 执行各种访问模式的时间,如随机或顺序读写
文件大小测量是在最终压缩后进行的,放大率是与原始键值大小的简单比较计算。
更多关于golang高性能LSM键值存储引擎插件库moss的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html