Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究
引言
通過本項(xiàng)目可以學(xué)到什么?
WAL預(yù)寫日志的實(shí)現(xiàn)
LSM Tree(Log-Structed-Merge Tree)
如何構(gòu)架一個(gè)企業(yè)級(jí)的項(xiàng)目
KV數(shù)據(jù)的序列化和反序列化存儲(chǔ)
- Golang的基本語法
整個(gè)代碼量1000多行,基本的大框架也好理解,容易出現(xiàn)錯(cuò)誤的點(diǎn)在于代碼細(xì)節(jié)的處理(特別是wal文件的讀寫部分)

簡(jiǎn)介
內(nèi)存數(shù)據(jù)采用SkipList 存儲(chǔ)
通過WAL (Write Ahead Log)保證內(nèi)存數(shù)據(jù)durability和crash-safe能力

代碼邏輯結(jié)構(gòu)

- 先通過
easydb.Open打開數(shù)據(jù)庫(kù)*DB對(duì)象;*DB內(nèi)部基于WAL恢復(fù)內(nèi)存數(shù)據(jù)openAllMemtables【就是讀取segment文件,解析出一個(gè)個(gè)LogRecord保存到skiplist中】,同時(shí)將內(nèi)存數(shù)據(jù)分成活躍內(nèi)存和不可變內(nèi)存【參考 LSM Tree結(jié)構(gòu)】。每個(gè)內(nèi)存對(duì)象*memtable內(nèi)部除了定義skiplist記錄內(nèi)存數(shù)據(jù),同時(shí)定義*wal對(duì)象記錄磁盤,*wal對(duì)象中的磁盤文件按照指定的大小分段保存(這里類似kafka中日志數(shù)據(jù)文件分段原理) - 然后調(diào)用
db.Put方法,內(nèi)部通過batch開啟寫事物(對(duì)db上鎖),將數(shù)據(jù)批量保存batch的pendingWrites中,然后在batch.Commit一次性全部保存到內(nèi)存和預(yù)寫日志中同時(shí)關(guān)閉寫事物(對(duì)db解鎖) - 調(diào)用
db.Get方法,內(nèi)部通過batch開啟讀事物(對(duì)db上鎖),讀取所有的內(nèi)存對(duì)象中的數(shù)據(jù)(倒序)方式,也就是從最近的內(nèi)存對(duì)象*memtable開始讀,讀取結(jié)束,提交事物(關(guān)閉讀事物,對(duì)db解鎖)
建議從下面 Open Get Put這幾個(gè)函數(shù)開始看起
package main
import (
"fmt"
"github.com/gofish2020/easydb"
"github.com/gofish2020/easydb/utils"
)
// this file shows how to use the basic operations of EasyDB
func main() {
// specify the options
options := easydb.DefaultOptions
options.DirPath = utils.ExecDir() + "/data"
// open a database
db, err := easydb.Open(options)
if err != nil {
panic(err)
}
deferfunc() {
_ = db.Close()
}()
// put a key
err = db.Put([]byte("name"), []byte("easydb"), nil)
if err != nil {
panic(err)
}
// get a key
val, err := db.Get([]byte("name"))
if err != nil {
panic(err)
}
println(string(val))
// delete a key
err = db.Delete([]byte("name"), nil)
if err != nil {
panic(err)
}
// get a key
val, err = db.Get([]byte("name"))
if err != nil {
if err == easydb.ErrKeyNotFound {
fmt.Println("key not exist")
return
}
panic(err)
}
println(string(val))
}WAL日志格式

WAL日志文件按照SegmentSize分成一個(gè)個(gè)的段文件;
每個(gè)段文件,按照32KB為一塊存儲(chǔ)區(qū)域,存儲(chǔ) 多個(gè) chunk實(shí)際數(shù)據(jù)
每個(gè)chunk由 7 字節(jié)header + 數(shù)據(jù)payload 組成;header頭包括 4字節(jié)校驗(yàn)碼,2字節(jié)數(shù)據(jù)長(zhǎng)度 1字節(jié)數(shù)據(jù)類型;校驗(yàn)碼校驗(yàn)的范圍為:【length + type + payload】確保數(shù)據(jù)沒有損壞
一個(gè)數(shù)據(jù)可能由多個(gè)chunk組成

當(dāng)在block中保存了多個(gè)chunk后,block剩余的空間不夠保存數(shù)據(jù),多余的空間浪費(fèi)掉,填充一些無效字節(jié)即可

Ps:本項(xiàng)目主要參考 LotusDB 實(shí)現(xiàn)
以上就是Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究的詳細(xì)內(nèi)容,更多關(guān)于Golang KV存儲(chǔ)引擎的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語言用Gin實(shí)現(xiàn)圖書管理接口的實(shí)現(xiàn)示例
本文主要介紹了Go語言用Gin實(shí)現(xiàn)圖書管理接口的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-08-08
Go調(diào)用C++動(dòng)態(tài)庫(kù)實(shí)現(xiàn)車牌識(shí)別的示例代碼
本文主要介紹了如何利用C++中Opencv、TensorRT等庫(kù)編譯出動(dòng)態(tài)庫(kù)供Go調(diào)用,再寫個(gè)簡(jiǎn)單的api對(duì)上傳的車輛圖片進(jìn)行車牌識(shí)別,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
go+redis實(shí)現(xiàn)消息隊(duì)列發(fā)布與訂閱的詳細(xì)過程
這篇文章主要介紹了go+redis實(shí)現(xiàn)消息隊(duì)列發(fā)布與訂閱,redis做消息隊(duì)列的缺點(diǎn):沒有持久化,一旦消息沒有人消費(fèi),積累到一定程度后就會(huì)丟失,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
Go 超時(shí)控制:context 與 timeout從實(shí)戰(zhàn)到原理解析
本文主要講解了Go語言中使用context進(jìn)行超時(shí)控制的核心概念、使用方法、常見錯(cuò)誤與坑以及底層實(shí)現(xiàn)原理,context用于管理生命周期,通過控制信號(hào)傳播機(jī)制優(yōu)雅地終止任務(wù),示例展示了其在HTTP請(qǐng)求、goroutine控制、多層調(diào)用鏈中的應(yīng)用,總結(jié)了常見錯(cuò)誤并提供了最佳實(shí)踐2026-05-05
VSCode Golang dlv調(diào)試數(shù)據(jù)截?cái)鄦栴}及處理方法
這篇文章主要介紹了VSCode Golang dlv調(diào)試數(shù)據(jù)截?cái)鄦栴},本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
golang?MySQL實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表存儲(chǔ)獲取操作示例
這篇文章主要為大家介紹了golang?MySQL實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表存儲(chǔ)獲取操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
在 Golang 中實(shí)現(xiàn) Cache::remember 方法詳解
這篇文章主要介紹了在 Golang 中實(shí)現(xiàn) Cache::remember 方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

