达达兔 谢晖停职后南通首战遭血... 达达兔 从零实现一个 K... 达达兔 想象世界 | 艺术与序言论... 达达兔 智通港股公告精选︱(5.1... 达达兔 曼联7800万欧报价桑乔被拒...
栏目分类
热点资讯
>> 你的位置:桃花视频在线观看免费高清完整版 > 达达兔 > 达达兔 从零实现一个 K

达达兔 从零实现一个 K

发布日期:2021-09-02 16:45    点击次数:187

  

本文转载自微信公多号「roseduan写字的地方」,作者roseduan。转载本文请有关roseduan写字的地方公多号。好男人资源社区

写这篇文章的主意,是为了协助更多的人理解 rosedb,吾会从零最先实现一个浅易的包含 PUT、GET、DELETE 操作的 k-v 存储引擎。

你能够将其望做是一个浅易版本的 rosedb,就叫它 minidb 吧(mini 版本的 rosedb)。

不论你是 Go 说话初学者,照样想进阶 Go 说话,或者是对 k-v 存储感有趣,都能够尝试本身脱手实现一下,吾笃信必定会对你协助很大的。

说到存储,其实解决的一个中央题目就是,怎么存放数据,怎么掏出数据。在计算机的世界里,这个题目会更添的多样化。

计算机当中有内存和磁盘,内存是易失性的,失踪电之后存储的数据通盘丢失,于是,倘若想要体系休业再重启之后照样平常行使,就不得不将数据存储在非易失性介质当中,最常见的便是磁盘。

于是,针对一个单机版的 k-v,吾们必要设计数据在内存中答该怎么存放,在磁盘中答该怎么存放。

自然,已经有许多特出的进步们往探究过了,并且已经有了经典的总结,主要将数据存储的模型分为了两类:B+ 树和 LSM 树。

本文的重点不是讲这两栽模型,于是只做浅易介绍。

B+ 树

B+ 树由二叉查找树演化而来,经由过程增补每层节点的数目,来降矮树的高度,适配磁盘的页,尽量缩短磁盘 IO 操作。

B+ 树查询性能比较安详,在写入或更新时,会查找并定位到磁盘中的位置并进走原地操作,仔细这边是随机 IO,并且大量的插入或删除还有能够触发页破碎和相符并,写入性能清淡,因此 B+ 树正当读多写少的场景。

LSM 树

LSM Tree(Log Structured Merge Tree,日志组织相符并树)其实并不是一栽详细的树类型的数据组织,而只是一栽数据存储的模型,它的中央理维基于一个原形:挨次 IO 远快于随机 IO。

和 B+ 树分歧,在 LSM 中,数据的插入、更新、删除都会被记录成一条日志,然后追添写入到磁盘文件当中,如许一切的操作都是挨次 IO,因此 LSM 比较适用于写多读少的场景。

望了前线的两栽基础存储模型,笃信你已经对如何存取数占有了基本的晓畅,而 minidb 基于一栽更添浅易的存储组织,总体上它和 LSM 比较相通。

吾先不直接干巴巴的讲这个模型的概念,而是经由过程一个浅易的例子来望一下 minidb 当中数据 PUT、GET、DELETE 的流程,借此让你理解这个浅易的存储模型。

PUT

吾们必要存储一条数据,别离是 key 和 value,最先,为预防数据丢失,吾们会将这个 key 和 value 封装成一条记录(这边把这条记录叫做 Entry),追添到磁盘文件当中。Entry 的内里的内容,大致是 key、value、key 的大幼、value 的大幼、写入的时间。

于是磁盘文件的组织专门浅易,就是多个 Entry 的荟萃。

磁盘更新完了,再更新内存,内存当中能够选择一个浅易的数据组织,比如哈希外。哈希外的 key 对答存放的是 Entry 在磁盘中的位置,便于查找时进走获取。

如许,在 minidb 当中,一次数据存储的流程就完了,只有两个步骤:一次磁盘记录的追添,一次内存当中的索引更新。

GET

再来望 GET 获取数据,最先在内存当中的哈希外查找到 key 对答的索引新闻,这其中包含了 value 存储在磁盘文件当中的位置,然后直接按照这个位置,到磁盘当中往掏出 value 就能够了。

DEL

然后是删除操作,这边并不会定位到原记录进走删除,而照样将删除的操作封装成 Entry,追添到磁盘文件当中,只是这边必要标识一下 Entry 的类型是删除。

然后在内存当中的哈希外删除对答的 key 的索引新闻,如许删除操作便完善了。

能够望到,不管是插入、查询、删除,都只有两个步骤:一次内存中的索引更新,一次磁盘文件的记录追添。于是不论数据周围如何, minidb 的写入性能相等安详。

Merge

末了再来望一个比较主要的操作,前线说到,磁盘文件的记录是不息在追添写入的,如许会导致文件容量也不息在增补。并且对于联相符个 key,能够会在文件中存在多条 Entry(回想一下,更新或删除 key 内容也会追添记录),那么在数据文件当中,其实存在冗余的 Entry 数据。

举一个浅易的例子,比如针对 key A,达达兔 先后竖立其 value 为 10、20、30,那么磁盘文件中就有三条记录:

此时 A 的最新值是 30,那么其实前两条记录已经是无效的了。

针对这栽情况,吾们必要按期相符并数据文件,修整无效的 Entry 数据,这个过程清淡叫做 merge。

merge 的思路也很浅易,必要掏出原数据文件的一切 Entry,将有效的 Entry 重新写入到一个新建的一时文件中,末了将原数据文件删除,一时文件就是新的数据文件了。

这就是 minidb 底层的数据存储模型,它的名字叫做 bitcask,自然 rosedb 采用的也是这栽模型。它内心上属于类 LSM 的模型,中央理维是行使挨次 IO 来升迁写性能,只不过在实现上,比 LSM 浅易多了。

介绍完了底层的存储模型,就能够最先代码实现了,吾将完善的代码实现放到了吾的 Github 上面,地址:

https://github.com/roseduan/minidb

文章当中就截取片面关键的代码。

最先是掀开数据库,必要先添载数据文件,然后掏出文件中的 Entry 数据,还原索引状态,关键片面代码如下:

func Open(dirPath string) (*MiniDB, error) {    // 倘若数据库现在录不存在,则新建一个    if _, err := os.Stat(dirPath); os.IsNotExist(err) {       if err := os.MkdirAll(dirPath, os.ModePerm); err != nil {          return nil, err       }    }     // 添载数据文件    dbFile, err := NewDBFile(dirPath)    if err != nil {       return nil, err    }     db := &MiniDB{       dbFile: dbFile,       indexes: make(map[string]int64),       dirPath: dirPath,    }     // 添载索引    db.loadIndexesFromFile(dbFile)    return db, nil } 

再来望望 PUT 手段,流程和上面的描述相通,先更新磁盘,写入一条记录,再更新内存:

func (db *MiniDB) Put(key []byte, value []byte) (err error) {       offset := db.dbFile.Offset    // 封装成 Entry    entry := NewEntry(key, value, PUT)    // 追添到数据文件当中    err = db.dbFile.Write(entry)     // 写到内存    db.indexes[string(key)] = offset    return } 

GET 手段必要先从内存中掏出索引新闻,判定是否存在,不存在直接返回,存在的话从磁盘当中掏出数据。

func (db *MiniDB) Get(key []byte) (val []byte, err error) {    // 从内存当中掏出索引新闻    offset, ok := db.indexes[string(key)]    // key 不存在    if !ok {       return    }     // 从磁盘中读取数据    var e *Entry    e, err = db.dbFile.Read(offset)    if err != nil && err != io.EOF {       return    }    if e != nil {       val = e.Value    }    return } 

DEL 手段和 PUT 手段相通,只是 Entry 被标识为了 DEL ,然后封装成 Entry 写到文件当中:

func (db *MiniDB) Del(key []byte) (err error) {    // 从内存当中掏出索引新闻    _, ok := db.indexes[string(key)]    // key 不存在,无视    if !ok {       return    }     // 封装成 Entry 并写入    e := NewEntry(key, nil, DEL)    err = db.dbFile.Write(e)    if err != nil {       return    }     // 删除内存中的 key    delete(db.indexes, string(key))    return } 

末了是主要的相符并数据文件操作,流程和上面的描述相通,关键代码如下:

func (db *MiniDB) Merge() error {    // 读取原数据文件中的 Entry    for {       e, err := db.dbFile.Read(offset)       if err != nil {          if err == io.EOF {             break          }          return err       }       // 内存中的索引状态是最新的,直接对比过滤出有效的 Entry       if off, ok := db.indexes[string(e.Key)]; ok && off == offset {          validEntries = append(validEntries, e)       }       offset += e.GetSize()    }     if len(validEntries) > 0 {       // 新建一时文件       mergeDBFile, err := NewMergeDBFile(db.dirPath)       if err != nil {          return err       }       defer os.Remove(mergeDBFile.File.Name())        // 重新写入有效的 entry       for _, entry := range validEntries {          writeOff := mergeDBFile.Offset          err := mergeDBFile.Write(entry)          if err != nil {             return err          }           // 更新索引          db.indexes[string(entry.Key)] = writeOff       }        // 删除旧的数据文件       os.Remove(db.dbFile.File.Name())       // 一时文件变更为新的数据文件       os.Rename(mergeDBFile.File.Name(), db.dirPath+string(os.PathSeparator)+FileName)        db.dbFile = mergeDBFile    }    return nil } 

除往测试文件,minidb 的中央代码只有 300 走,麻雀虽幼,五脏俱全,它已经包含了 bitcask 这个存储模型的主要思维,并且也是 rosedb 的底层基础。

理解了 minidb 之后,基本上就能够十足掌握 bitcask 这栽存储模型,多花点时间,笃信对 rosedb 也能够如鱼得水了。

进一步,倘若你对 k-v 存储这方面感有趣,能够更添深入的往钻研更多有关的知识,bitcask 固然简洁易懂,但是题目也不少,rosedb 在实践的过程当中,对其进走了一些优化,但现在照样有不少的题目存在。

有的人能够比较疑心,bitcask 这栽模型浅易,是否只是一个玩具,在实际的生产环境中有行使吗?答案是肯定的。

bitcask 最初源于 Riak 这个项主意底层存储模型,而 Riak 是一个分布式 k-v 存储,在 NoSQL 的排名中也名列前茅:

豆瓣所行使的的分布式 k-v 存储,其实也是基于 bitcask 模型,并对其进走了许多优化。现在纯粹基于 bitcask 模型的 k-v 并不是许多,于是你能够多往望望 rosedb 的代码,能够挑出本身的偏见提出,一首完善这个项现在。

末了,附上有关项现在地址:

minidb:https://github.com/roseduan/minidb rosedb:https://github.com/roseduan/rosedb

参考原料:

https://riak.com/assets/bitcask-intro.pdf

https://medium.com/@arpitbhayani/bitcask-a-log-structured-fast-kv-store-c6c728a9536b

题图:from wallheaven.cc

【编辑选举】达达兔

揭露网络坦然的7个实际:打破子虚的“坦然感” 30 位大佬,勾勒出一个中国网络坦然江湖 人造智能在网络坦然中的四大上风和挑衅 智能网络坦然必要的不光仅是智能技术 新冠疫情对全球经济以及网络坦然的影响你晓畅哪些? ,

上一篇:高并发服务优化篇:详解一次由读写锁引首的内存泄露

下一篇:达达兔 数据中央需求如何将投资者推向新市场

Powered by 桃花视频在线观看免费高清完整版 @2013-2021 RSS地图 HTML地图