用 Go 语言写了一个全新的存储引擎

简介: 经历了大概 4 个月的打磨,LotusDB 的第一个 release 版本终于发布了,我看了下,有 200 多次 commit(接近 rosedb 一年多的 commit 次数了)。

经历了大概 4 个月的打磨,LotusDB 的第一个 release 版本终于发布了,我看了下,有 200 多次 commit(接近 rosedb 一年多的 commit 次数了)。

项目地址:https://github.com/flower-corp/lotusdb


有了 rosedb 在 bitcask 模型上的实践之后,以及自己在存储这方面的一些经验积累,去年底的时候,在上班路上突然想到的一个 idea,让我有了做一个新的 kv 存储引擎的想法。

有了想法之后便是验证,因为其实心里还是没谱,我又在 Github 上翻了翻,并没有同类型的实现。后来又找一些大佬沟通了下,证明我的想法是可行的。

这期间还发现了 Usenix Fast 上的一篇关于优化 LSM 的论文,发现论文的内容跟我的 idea 非常类似,这算是又多了一个理论依据,于是便决定开干了。

感兴趣的可以参考下论文,叫做 SLM-DB,地址: https://www.usenix.org/conference/fast19/presentation/kaiyrakhmet


众所周知,数据存储引擎,目前最主流的两种模型是 B+ 树和 LSM 树,B+ 树在关系型数据库例如 Mysql 中应用比较广泛,而 LSM 的典型代表 rocksdb 也是大多数分布式系统数据落盘的首选。


B+ 树读性能稳定,而 LSM 写吞吐高,LotusDB 在这基础上做了一个巨大的改动,就是完全舍弃掉 LSM 中的 SST 文件,改由 B+ 树来存储索引,而 value 存放则参考了 Wisckey 和 bitcask 模型的设计,存储到单独的 value log 文件中。

LotusDB 是对 LSM 和 B+ 树的优势结合,目前并没有同类型的实现,我们应该是第一个吃螃蟹的人。

LotusDB 的架构图如下:

前台的写入和 LSM 完全一致,先写 wal 再写 memtable。


而读取则会从 memtable 开始,如果 memtable 找到了,直接返回;没找到的话则从 B+ 树中查询索引,然后根据索引信息到 value log 中获取 value。

大家可以先了解个大概,后续我会出一个完整的《LotusDB 设计与实现》系列文章,全面解析 LotusDB 的架构细节以及代码实现,目前已经写了几篇待发布,欢迎关注我的知乎后续更新:



再来看看 LotusDB 提供的一些基本接口,目前实现了基础的 Put、Get、Delete 接口,并且支持 Column Family(借鉴于 rocksdb),以及 value log 的自动 GC 回收。

简单的使用方法如下:

package main
import (
  "github.com/flower-corp/lotusdb"
  "io/ioutil"
  "time"
)
// basic operations for LotusDB:
// put
// put with options
// get
// delete
// delete with options
func main() {
  path, _ := ioutil.TempDir("", "lotusdb")
  opts := lotusdb.DefaultOptions(path)
  db, err := lotusdb.Open(opts)
  if err != nil {
    panic(err)
  }
  defer db.Close()
  // 1.----put----
  key1 := []byte("name")
  err = db.Put(key1, []byte("lotusdb"))
  if err != nil {
    // ...
  }
  key2 := []byte("feature")
  // 2.----put with options----
  writeOpts := &lotusdb.WriteOptions{
    Sync: true,
    ExpiredAt: time.Now().Add(time.Second * 100).Unix(),
  }
  err = db.PutWithOptions(key2, []byte("store data"), writeOpts)
  if err != nil {
    // ...
  }
  // 3.----get----
  val, err := db.Get(key1)
  if err != nil {
    // ...
  }
  if len(val) > 0 {
    // ...
  }
  // 4.----delete----
  err = db.Delete(key1)
  if err != nil {
    // ...
  }
  // 5.----delete with options----
  deleteOpts := &lotusdb.WriteOptions{
    Sync: false,
    DisableWal: true,
  }
  err = db.DeleteWithOptions([]byte("dummy key"), deleteOpts)
  if err != nil {
    // ...
  }
}


目前自认为 LotusDB 的代码质量比之前的 RoseDB 好多了,单元测试更加完备,注释清晰,代码也更加简洁规范,如果你是 Go 新手,或者准备学习 Go,也能够把项目当做练习素材,自己对照着来学习。


当然我们的愿景还是打造一个能够在生产环境中实际落地的存储引擎,目前的版本只是一个开始,后续还会有非常多的工作,包括但不限于:

  • batch 操作,保证原子性
  • 多个 Column Family 保证原子性
  • 基于 SSI 的事务
  • Iterator 迭代器
  • 数据压缩
  • 数据备份
  • index 的分裂


相关文章
|
17天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
61 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
1月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
42 7
|
1月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
1月前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
105 71
|
1月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
109 67
|
2天前
|
监控 安全 算法
深度剖析核心科技:Go 语言赋能局域网管理监控软件进阶之旅
在局域网管理监控中,跳表作为一种高效的数据结构,能显著提升流量索引和查询效率。基于Go语言的跳表实现,通过随机化索引层生成、插入和搜索功能,在高并发场景下展现卓越性能。跳表将查询时间复杂度优化至O(log n),助力实时监控异常流量,保障网络安全与稳定。示例代码展示了其在实际应用中的精妙之处。
24 9
|
11天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
46 12
|
1月前
|
存储 Go
go语言中映射
go语言中映射
42 11
|
14天前
|
监控 算法 安全
解锁企业计算机监控的关键:基于 Go 语言的精准洞察算法
企业计算机监控在数字化浪潮下至关重要,旨在保障信息资产安全与高效运营。利用Go语言的并发编程和系统交互能力,通过进程监控、网络行为分析及应用程序使用记录等手段,实时掌握计算机运行状态。具体实现包括获取进程信息、解析网络数据包、记录应用使用时长等,确保企业信息安全合规,提升工作效率。本文转载自:[VIPShare](https://www.vipshare.com)。
22 0
|
28天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数