實(shí)現(xiàn)分布式 Kv-1 Standalone KV
本文轉(zhuǎn)載自微信公眾號(hào)「roseduan寫(xiě)字的地方」,作者roseduan。轉(zhuǎn)載本文請(qǐng)聯(lián)系roseduan寫(xiě)字的地方公眾號(hào)。
旨在實(shí)現(xiàn)一個(gè)簡(jiǎn)易的分布式 kv,其中很多代碼框架它已經(jīng)提供了,我們只需要填充具體的邏輯即可。
這個(gè)課程分為了 4 個(gè) Project:
- Standlone KV
- Raft KV
- Multi Raft KV
- Transaction
分別需要實(shí)現(xiàn)單機(jī)版 kv、基于 raft(和 multi raft) 一致性算法的 kv、具有分布式事務(wù)的 kv,除了第一個(gè) standalone kv 沒(méi)有什么難度之外,其他的幾個(gè) Project 都非常的有挑戰(zhàn),涉及到手寫(xiě) raft 算法以及分布式事務(wù)。
當(dāng)然這個(gè)課程也是入門(mén)和實(shí)踐分布式存儲(chǔ)領(lǐng)域的挺好的學(xué)習(xí)資源,因此記錄一下自己的學(xué)習(xí)歷程。
今天這篇文章先來(lái)看看第一個(gè) Project。
第一個(gè) Project 是集成 Badger,實(shí)現(xiàn)一個(gè)簡(jiǎn)易的單機(jī)版 kv。
Badger 是一個(gè)很優(yōu)秀的開(kāi)源的單機(jī)版 kv 存儲(chǔ)引擎,基于 LSM Tree 實(shí)現(xiàn),讀寫(xiě)性能都很好,因此需要簡(jiǎn)單熟悉下 Badger 的用法,可以參考下官方示例:github.com/dgraph-io/bager。
在 TinyKV 中,存儲(chǔ)層是一個(gè)抽象接口,分別實(shí)現(xiàn)了 raft storage、mem storage、standalone storage,這里我們只需要實(shí)現(xiàn) standalone storage 就行了。
具體的實(shí)現(xiàn),在 kv/storage/standalone_storage/standalone_storage.go 中,需要封裝一下 Badger,然后實(shí)現(xiàn) storage 接口中定義的幾個(gè)方法。
這里貼一下結(jié)構(gòu)體的定義:
- type StandAloneStorage struct {
- // Your Data Here (1).
- badgerDB *badger.DB
- options badger.Options
- }
需要說(shuō)明的是,在 Reader 方法中,需要返回一個(gè) StorageReader 接口,這是一個(gè)抽象接口,具體邏輯需要我們自定義。
- 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
- }
例如我定義了一個(gè) StandaloneReader:
- type StandaloneReader struct {
- txn *badger.Txn
- }
- func NewStandaloneReader(txn *badger.Txn) *StandaloneReader {
- return &StandaloneReader{
- txn: txn,
- }
- }
這里完成之后,還需要在 kv/server/raw_api.go 中完善相應(yīng)的 gRPC 接口,直接解析傳過(guò)來(lái)的參數(shù),然后調(diào)用 Storage 接口中的方法即可。這里展示一個(gè)示例:
- 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
- }
這里的幾個(gè)接口完成之后,一個(gè)完整的 Standalone KV 就完成了。
你可以把 TinyKV 的代碼 clone 下來(lái),然后自己跟著我的節(jié)奏做,一步一步堅(jiān)持下去,相信能夠在分布式存儲(chǔ)領(lǐng)域有個(gè)初步的認(rèn)知。