TinyKV 是 PingCAP 的一個開源課程:https://github.com/tidb-incubator/tinykv,旨在實現一個簡易的分散式 kv,其中很多程式碼框架它已經提供了,我們只需要填充具體的邏輯即可。
這個課程分為了 4 個 Project:
- Standlone KV
- Raft KV
- Multi Raft KV
- Transaction
分別需要實現單機版 kv、基於 raft 一致性演算法的 kv、具有分散式事務的 kv,除了第一個 standalone kv 沒有什麼難度之外,其他的幾個 Project 都非常的有挑戰,涉及到手寫 raft 演算法以及分散式事務。
當然這個課程也是入門分散式儲存領域是挺好的學習資源,因此記錄一下自己的學習歷程。
第一個 Project 是整合 Badger,實現一個簡易的單機版 kv。
Badger 是一個很優秀的開源的單機版 kv 儲存引擎,基於 LSM Tree 實現,讀寫效能都很好,需要簡單熟悉下 Badger 的用法,可以參考下官方示例:https://github.com/dgraph-io/badger。
在 TinyKV 中,儲存層是一個抽象介面,分別實現了 raft storage、mem storage、standalone storage,這裡我們只需要實現 standalone storage 就行了。
具體的實現,在 kv/storage/standalone_storage/standalone_storage.go 中,需要封裝一下 Badger,然後實現 storage 介面中定義的幾個方法。
這裡貼一下結構體的定義:
type StandAloneStorage struct {
// Your Data Here (1).
badgerDB *badger.DB
options badger.Options
}
需要說明的是,在 Reader 方法中,需要返回一個 StorageReader 介面,這是一個抽象介面,具體邏輯需要我們自定義。
func (s *StandAloneStorage) Reader(ctx *kvrpcpb.Context) (storage.StorageReader, error) {
// Your Code Here (1).
txn := s.badgerDB.NewTransaction(false)
reader := NewStandaloneReader(txn)
return reader, nil
}
例如我定義了一個 StandaloneReader:
type StandaloneReader struct {
txn *badger.Txn
}
func NewStandaloneReader(txn *badger.Txn) *StandaloneReader {
return &StandaloneReader{
txn: txn,
}
}
這裡完成之後,還需要在 kv/server/raw_api.go 中完善相應的 gRPC 介面,直接解析傳過來的引數,然後呼叫 Storage 介面中的方法即可。這裡展示一個示例:
func (server *Server) RawGet(_ context.Context, req *kvrpcpb.RawGetRequest) (resp *kvrpcpb.RawGetResponse, err error) {
// Your Code Here (1).
resp = &kvrpcpb.RawGetResponse{}
// get storage reader.
var reader storage.StorageReader
reader, err = server.storage.Reader(req.Context)
if err != nil {
return
}
defer reader.Close()
val, err := reader.GetCF(req.Cf, req.Key)
if len(val) == 0 {
resp.NotFound = true
}
resp.Value = val
return
}
這裡的幾個介面完成之後,一個完整的 Standalone KV 就完成了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結