ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Talent Plan TinyKV Project1 StandaloneKV

2021-12-06 22:34:43  阅读:225  来源: 互联网

标签:engine Talent string kvrpcpb Plan func byte Project1 badger


6.824做完了,代码写的乱糟糟,想着重写一遍,整理下思路,后来发现了tinykv,相比于6.824还多了个事务,就准备把tinykv也做一下。

文档翻译

在本项目中,实现一个单机的、支持Column Family的KV存储服务。Column Family表示Key的命名空间,不同Column Family间可以有相同的Key存在。

服务提供Put/Delete/Get/Scan四种基本操作。

本项目可以拆解为两步去实现:

  1. 实现单机的存储引擎。
  2. 实现原生的服务接口。

tinykvpb.proto和kvrpcpb.proto定义了rpc接口和请求响应消息,kv/main.go中注册了RPC服务。

proto文件由protocol-buffer生成,不需要修改。

Server底层由Storage抽象类支持,需要为StandAloneStorage实现Storage的所有接口。

type Storage interface {
    // Other stuffs
    Write(ctx *kvrpcpb.Context, batch []Modify) error
    Reader(ctx *kvrpcpb.Context) (StorageReader, error)
}
复制代码

Storage底层由badger(类似LevelDB或RocksDB的存储引擎)支持,StandAloneStorage即badger的简单封装。

目前不需要考虑kvrpcpb.Context的涵义。

一些提示。

  1. 使用badger.Txn来实现Reader()函数,即badger提供的事务支持。
  2. badger不支持Column Family,engine_util提供了一系列函数,利用前缀来实现Column Family,使用它们来实现Write()函数。
  3. 使用Connor1996/badger而不是dgraph-io/badger。
  4. 使用Discard()关闭badger.Txn,这之前需要关闭所有迭代器。

最后就是基于Storage实现RawGet/RawScan/RawPut/RawDelete,完成后通过make project1进行测试。

StandAloneStorage

engine_util封装了badger的接口,StandAloneStorage就是要在engine_util的基础上再封装一层。因此StandAloneStorage结构也很简单。

type StandAloneStorage struct {
   engine *engine_util.Engines
}
复制代码

StandAloneStorage为抽象类Storage的具体实现,因此需要实现Write和Reader两个函数,函数签名如下。

func (s *StandAloneStorage) Write(ctx *kvrpcpb.Context, batch []storage.Modify) error
func (s *StandAloneStorage) Reader(ctx *kvrpcpb.Context) (storage.StorageReader, error)
复制代码

Project1中,还用不到kvrpcpb.Context,storage.Modify对应Put或Delete两个写操作,storage.StorageReader同样是一个抽象类。

Reader

type StorageReader interface {
   GetCF(cf string, key []byte) ([]byte, error)
   IterCF(cf string) engine_util.DBIterator
   Close()
}
复制代码

可以看到StorageReader的两个函数,屏蔽了事务,简化了接口。实现StorageReader需要用到engine_util提供的GetCFFromTxn和NewCFIterator两个函数。

func GetCFFromTxn(txn *badger.Txn, cf string, key []byte) (val []byte, err error)
func NewCFIterator(cf string, txn *badger.Txn) *BadgerIterator
复制代码

获取badger.Txn的函数engine_util并未给出,需要直接调用badger.DB.NewTransaction函数。

func (db *DB) NewTransaction(update bool) *Txn
复制代码

update为真表示Put/Delete两个写操作,为假表示Get/Scan两个读操作。

Write

type Modify struct {
   Data interface{}
}

type Put struct {
   Key   []byte
   Value []byte
   Cf    string
}

type Delete struct {
   Key []byte
   Cf  string
}
复制代码

Modify表示一个Put/Delete操作,Write中通过断言确定是Put还是Delete,进而调用engine_util提供的PutCF和DeleteCF两个函数。

func PutCF(engine *badger.DB, cf string, key []byte, val []byte) error
func DeleteCF(engine *badger.DB, cf string, key []byte) error
复制代码

其实这两个函数内部实现依旧是用了事务的,相比于Reader,Write对事务的屏蔽并没有让我们自己实现。

Server

StandAloneStorage是Storage的实现,Server还要在他之上,后续还会有RaftStorage,这样Server底层的存储引擎就是可以更换的,分别对应单机的和分布式的存储服务。

type Server struct {
   storage storage.Storage
}
复制代码

Project1要求我们为Server实现原生的服务接口,这部分在raw_api.go中,需要实现的函数的签名如下。

func (server *Server) RawGet(_ context.Context, req *kvrpcpb.RawGetRequest) (*kvrpcpb.RawGetResponse, error)
func (server *Server) RawPut(_ context.Context, req *kvrpcpb.RawPutRequest) (*kvrpcpb.RawPutResponse, error)
func (server *Server) RawDelete(_ context.Context, req *kvrpcpb.RawDeleteRequest) (*kvrpcpb.RawDeleteResponse, error)
func (server *Server) RawScan(_ context.Context, req *kvrpcpb.RawScanRequest) (*kvrpcpb.RawScanResponse, error)
复制代码

实现这四个接口,需要调用之前实现的Write、Reader.GetCF、Reader.IterCF这三个函数,一个可能不太理解的是Scan函数,因为badgerDB内部是有序存储的,所以可以根据一个Key,向后获取N个Key,RawScanRequest.Limit就是N的涵义。

engine_util封装了DBIterator,提供了Item、Valid、Next、Seek用于实现RawScan函数。

Column Family

可能你还没理解CF是什么,其实本质就是字符串而已,用作Key的前缀,起到命名空间的作用。

const (
   CfDefault string = "default"
   CfWrite   string = "write"
   CfLock    string = "lock"
)

func KeyWithCF(cf string, key []byte) []byte {
   return append([]byte(cf+"_"), key...)
}
复制代码

例如默认的CF为"default",那么该CF下的名为"apple"的Key,实际存储为"default_apple"这个字符串。

标签:engine,Talent,string,kvrpcpb,Plan,func,byte,Project1,badger
来源: https://blog.csdn.net/SharingOfficer/article/details/121757877

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有