Golang實現(xiàn)KV存儲引擎實例探究
引言
通過本項目可以學(xué)到什么?
WAL
預(yù)寫日志的實現(xiàn)
LSM Tree(Log-Structed-Merge Tree)
如何構(gòu)架一個企業(yè)級的項目
KV數(shù)據(jù)的序列化和反序列化存儲
- Golang的基本語法
整個代碼量1000多行,基本的大框架也好理解,容易出現(xiàn)錯誤的點在于代碼細(xì)節(jié)的處理(特別是wal文件的讀寫部分)
簡介
內(nèi)存數(shù)據(jù)采用SkipList
存儲
通過WAL (Write Ahead Log)
保證內(nèi)存數(shù)據(jù)durability
和crash-safe
能力
代碼邏輯結(jié)構(gòu)
- 先通過
easydb.Open
打開數(shù)據(jù)庫*DB
對象;*DB
內(nèi)部基于WAL
恢復(fù)內(nèi)存數(shù)據(jù)openAllMemtables
【就是讀取segment
文件,解析出一個個LogRecord
保存到skiplist
中】,同時將內(nèi)存數(shù)據(jù)分成活躍內(nèi)存和不可變內(nèi)存【參考 LSM Tree結(jié)構(gòu)】。每個內(nèi)存對象*memtable
內(nèi)部除了定義skiplist
記錄內(nèi)存數(shù)據(jù),同時定義*wal
對象記錄磁盤,*wal
對象中的磁盤文件按照指定的大小分段保存(這里類似kafka中日志數(shù)據(jù)文件分段原理) - 然后調(diào)用
db.Put
方法,內(nèi)部通過batch
開啟寫事物(對db上鎖),將數(shù)據(jù)批量保存batch
的pendingWrites
中,然后在batch.Commit
一次性全部保存到內(nèi)存和預(yù)寫日志中同時關(guān)閉寫事物(對db解鎖) - 調(diào)用
db.Get
方法,內(nèi)部通過batch
開啟讀事物(對db上鎖),讀取所有的內(nèi)存對象中的數(shù)據(jù)(倒序)方式,也就是從最近的內(nèi)存對象*memtable
開始讀,讀取結(jié)束,提交事物(關(guān)閉讀事物,對db解鎖)
建議從下面 Open Get Put
這幾個函數(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
分成一個個的段文件;
每個段文件,按照32KB
為一塊存儲區(qū)域,存儲 多個 chunk
實際數(shù)據(jù)
每個chunk
由 7 字節(jié)header
+ 數(shù)據(jù)payload
組成;header
頭包括 4字節(jié)校驗碼,2字節(jié)數(shù)據(jù)長度 1字節(jié)數(shù)據(jù)類型;校驗碼校驗的范圍為:【length + type + payload】確保數(shù)據(jù)沒有損壞
一個數(shù)據(jù)可能由多個chunk
組成
當(dāng)在block中保存了多個chunk后,block剩余的空間不夠保存數(shù)據(jù),多余的空間浪費掉,填充一些無效字節(jié)即可
Ps:本項目主要參考 LotusDB 實現(xiàn)
以上就是Golang實現(xiàn)KV存儲引擎實例探究的詳細(xì)內(nèi)容,更多關(guān)于Golang KV存儲引擎的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang?gorm的Callbacks事務(wù)回滾對象操作示例
這篇文章主要為大家介紹了golang?gorm的Callbacks事務(wù)回滾對象操作示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04更換GORM默認(rèn)SQLite驅(qū)動出現(xiàn)的問題解決分析
這篇文章主要為大家介紹了更換GORM默認(rèn)SQLite驅(qū)動出現(xiàn)的問題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01golang 數(shù)組去重,利用map的實現(xiàn)
這篇文章主要介紹了golang 數(shù)組去重,利用map的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04Golang實現(xiàn)smtp郵件發(fā)送的示例代碼
這篇文章主要為大家詳細(xì)介紹了Golang實現(xiàn)smtp郵件發(fā)送的相關(guān)知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03