用 Go 語言造了一個全新的 kv 儲存引擎

roseduan發表於2022-03-21

經歷了大概 4 個月的打磨,LotusDB 的第一個 release 版本終於釋出了,我看了下,有 200 多次 commit(接近 rosedb 一年多的 commit 次數了)。

圖片

專案地址:https://github.com/flower-cor...

有了 rosedb 在 bitcask 模型上的實踐之後,以及自己在儲存這方面的一些經驗積累,去年底的時候,在上班路上突然想到的一個 idea,讓我有了做一個新的 kv 儲存引擎的想法。

有了想法之後便是驗證,因為其實心裡還是沒譜,我又在 Github 上翻了翻,並沒有同型別的實現。後來又找一些大佬溝通了下,證明我的想法是可行的。

這期間還發現了 Usenix Fast 上的一篇關於優化 LSM 的論文,發現論文的內容跟我的 idea 非常類似,這算是又多了一個理論依據,於是便決定開幹了。

感興趣的可以參考下論文,叫做 SLM-DB,地址:https://www.usenix.org/confer...

眾所周知,資料儲存引擎,目前最主流的兩種模型是 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 的分裂

如果大家在使用或者學習的過程中,有任何問題都可以微信聯絡我:

圖片

覺得有幫助的話,歡迎給專案點個 star 支援下

專案地址:https://github.com/flower-cor...

相關文章