實現分布式 Kv-1 Standalone KV
本文轉載自微信公眾號「roseduan寫字的地方」,作者roseduan。轉載本文請聯系roseduan寫字的地方公眾號。
旨在實現一個簡易的分布式 kv,其中很多代碼框架它已經提供了,我們只需要填充具體的邏輯即可。
這個課程分為了 4 個 Project:
- Standlone KV
- Raft KV
- Multi Raft KV
- Transaction
分別需要實現單機版 kv、基于 raft(和 multi raft) 一致性算法的 kv、具有分布式事務的 kv,除了第一個 standalone kv 沒有什么難度之外,其他的幾個 Project 都非常的有挑戰,涉及到手寫 raft 算法以及分布式事務。
當然這個課程也是入門和實踐分布式存儲領域的挺好的學習資源,因此記錄一下自己的學習歷程。
今天這篇文章先來看看第一個 Project。
第一個 Project 是集成 Badger,實現一個簡易的單機版 kv。
Badger 是一個很優秀的開源的單機版 kv 存儲引擎,基于 LSM Tree 實現,讀寫性能都很好,因此需要簡單熟悉下 Badger 的用法,可以參考下官方示例:github.com/dgraph-io/bager。
在 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 就完成了。
你可以把 TinyKV 的代碼 clone 下來,然后自己跟著我的節奏做,一步一步堅持下去,相信能夠在分布式存儲領域有個初步的認知。