bitcask是一个使用Erlang写的key-value存储引擎。Bitcask的起源和一个分布式key-value数据库 Riak有很密切的关系。在Riak的集群里,每个node使用插件式的存储引擎,几乎所有key-value类型的存储引擎都可以作为单个node节点的存储引擎。关于Riak的详细介绍,有机会后面再讲。

设计理念

在MySQL和postgresql中,除了保存在disk上的真正的数据库数据外,还有额外的日志文件,MySQL中是binlog,pg中是wal 文件。这些日志文件在备份、还原、建立从库的时候非常有用。

在bitcask中的设计中,相对就比较简单,日志文件本身就是数据库。备份起来也相当简单,只要把数据目录的所有文件拷贝一份,在另一个服务器上重建索引就行了。简要说起来有下面几点:

  • 使用RAM(内存)存储一个哈希表,哈希表上的value指向文件系统上的文件,以及该key对应的值在该文件中的具体位置。
  • 无论是插入、更新还是删除,都是append一条记录到一个特殊格式的文件。
  • 每次append记录之后,更新内存里的那个哈希表
  • 每个文件有最大空间限制,这个文件写满之后,写下一个,写过的之后永远不会再改变。
  • 有一个merge进程,用来合并老数据,防止文件大小无限积累。
  • 读缓存:其他的数据库系统,比如MySQL,PostgreSql有相当复杂的设计,bitcask没有相关设计,而是依赖于操作系统内核的文件系统缓存。

优势

  • 写操作:由于所有的操作都是append,所以速度是极快的,因为不会涉及到seek(不知道如何用中文表述,手动捂脸)。
  • 读操作:O(1)复杂度的disk查询,因为内存里的哈希表已经明确表名这个值所在的位置了。
  • 设计简单,很容易理解,这也是一个优势

详细解释

以下内容几乎全部来自bitcask的paper,很易读,地址为:basho.com/wp-content/…

一个bitcask实例就是一个目录,在设计上强制在任意时刻,只有一个操作系统进程可以打开bitcask进行写操作,这个进程就可以看作是bitcask服务。在任意时刻,这个目录中只有一个文件是active的,只有这个文件是可以被写入的。当这个active的文件大小达到一个临界值的时候,bitcask就会创建一个新的文件,用来取代当前的active文件。被取代的文件被称为老文件,之后永远都是不可变的,不会再有任何进程往里面写入数据。

Active文件写操作全是append,意味着顺序写入操作不需要disk seeking。每一个记录的格式如下图:

  • crc:一个检验值,在这里可以忽略
  • tstamp:时间戳
  • ksz: key的大小
  • value_sz : value的大小。

需要注意的是,删除操作,不过是插入一条value为某个特殊值的记录。

这些记录组合起来,就构成了一个bitcask文件:

当append操作完成时,内存里的一个叫做keydir的数据结构就会被更新。一个keydir就是一个简单的哈希表,key就是插入数据的key,value指向了插入数据value在文件系统中的具体位置。

  • file_id : 前面说过,bitcask有active文件,也有老数据文件,这个file_id就是指向了一个其中的文件。
  • value_pos : value在该文件的起始位置。
  • value_sz : value大小

写入发生时,原来的老数据依然还是保存在磁盘上,但是新的读取这个key的请求都会使用keydir上最新的数据。后面会说到,有一个合并进程,最终会删除不会再使用到的老数据。

读取操作是很简单的,根本不需要操作一次的disk seek。从内存中的keydir查询key,从这里知道了value所在的file_id,位置,大小,然后只要调用系统的读取接口就行了。一般操作系统都还会有自己独立的disk读缓存,所以这个操作实际上可以更快。

现在来说说前面提到的合并操作。其实很简单,**合并进程遍历所有的老文件,产生一个只包含当前最新版本数据的文件。**这部分完成的时候,还会产生一个hint file,这个文件本质上和data 文件一样,只不过他们保存的是value所在文件上的位置,而不是value本身。这个文件可以加速从目录文件重建keydir的过程。

当bitcask被一个Erlang进程打开时,它会检查同一个VM里,是不是有另一个Erlang进程在使用这个bitcask,如果是的话,就会和那个进程共享同一个keydir。如果没有的话,它就会扫描所有的数据文件,构建一个新的keydir,对于那些有hint file的文件,这个构建过程会有显著提高。

总结

我接触的第一个key-value存储引擎是redis。redis的所有数据都是装在内存的(每隔一段时间会把数据持久化保存到磁盘),这意味着redis的读写速度都非常快。但是这有一个限制,那就是单机redis存储的数据不能大于内存本身。而bitcask的最大限制是内存必须装得下所有的key,因为bitcask的value是存在磁盘上的。所以相比redis,bitcask的存在意义不是和redis比速度,而是当你的数据用redis存不下的时候,可以考虑稍微损失一丢丢速度,试试bitcask。

关注我的微信公众号

bitcask存储引擎相关推荐

  1. BitCask 持久化hash存储引擎 原理介绍

    文章目录 前言 引擎背景 引擎原理 1. 磁盘数据结构 2. 内存数据结构 3. 读流程 4. 数据合并 总结 前言 最近工作中部分项目中,对存储引擎的需求希望高性能的写.点查,并不需要Range.这 ...

  2. 存储引擎 K/V 分离下的index回写问题

    前言 近期在做on nvme hash引擎相关的事情,对于非全序的数据集的存储需求,相比于我们传统的LSM或者B-tree的数据结构来说 能够减少很多维护全序上的计算/存储资源.当然我们要保证hash ...

  3. plsql存储过程修改后怎么保存_分布式基础-存储引擎

    题目和文章内容有点不太符合,这里存储引擎是指单机存储引擎.对于分布式存储系统来说,存储引擎是必须的.存储引擎决定了数据在内存和磁盘中具体如何存储的,如何方便地拿出来的问题.可以说直接决定了存储系统的性 ...

  4. 评估数据库存储引擎的黄金三角

    存储引擎的特点千差万别,各具特色.但总体上我们可以通过三个变量来描述它们的行为:缓存的使用方式,数据是可变的还是不可变的,存储的数据是有顺序的还是没有顺序的. 缓存形式 缓存是说存储引擎在数据写入的时 ...

  5. 字节跳动在 RocksDB 存储引擎上的改进实践

    本文选自"字节跳动基础架构实践"系列文章. "字节跳动基础架构实践"系列文章是由字节跳动基础架构部门各技术团队及专家倾力打造的技术干货内容,和大家分享团队在基础 ...

  6. 关于数据存储引擎结构,没有比这篇更详细的

    摘要:常见存储算法结构涵盖:哈希存储,B .B+.B*树存储,LSM树存储引擎,R树,倒排索引,矩阵存储,对象与块,图结构存储等等. 介绍 在存储系统的设计中,存储引擎属于底层数据结构,直接决定了存储 ...

  7. 从零实现一个 k-v 存储引擎

    写这篇文章的目的,是为了帮助更多的人理解 rosedb,我会从零开始实现一个简单的包含 PUT.GET.DELETE 操作的 k-v 存储引擎. 你可以将其看做是一个简易版本的 rosedb,就叫它 ...

  8. 浅谈MySQL存储引擎-InnoDBMyISAM

    浅谈MySQL存储引擎-InnoDB&MyISAM 存储引擎在MySQL的逻辑架构中位于第三层,负责MySQL中的数据的存储和提取.MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式 ...

  9. 3种mysql的储存机制_MySQL三种InnoDB、MyISAM和MEMORY存储引擎对比

    三种引擎的区别: 事务:InnoDB支持事务,MyISAM和MEMORY两个不支持. 存储限制:InnoDB有64TB的存储限制,MyISAM和MEMORY要跟具体情况而定. 空间使用:InnoDB对 ...

最新文章

  1. Alamofire源码解读系列(五)之结果封装(Result)
  2. golang中的strings.ContainsRune
  3. test2 3-16 2021 模拟赛two
  4. 基本农田卫星地图查询_如何基于西安80坐标查询定位
  5. tensorflow学习笔记1
  6. synchronized的使用和底层原理、锁状态的膨胀升级过程
  7. Python的DoS拒绝服务之TCP/SYN洪水攻击
  8. hdu 4006 The kth great number 很复杂的线段树,至少对于我来说,但也学会了很多!!!!!!!!!!
  9. ArcView GIS 应用与开发技术(10)-影像操作
  10. 网络安全--通过握手包破解WiFi(详细教程)
  11. 如何免费在本地播放flv格式的视频
  12. 解决 Ubuntu-MATE 系统中出现 System policy prevents Wi-Fi scans 的问题
  13. quoted string not properly terminated错误提示
  14. 【2004-3】【平分核桃】
  15. eNSP解决OSPF不规则区域几个方法和vlink-peer
  16. 归并排序(C语言实现)
  17. spring报MySQLSyntaxErrorException: Unknown error 1146
  18. tf计算矩阵维度_tensorflow tf.matmul() (多维)矩阵相乘(多维矩阵乘法)
  19. .wine/drive_c/users/Public/Application Data/Source Insight/4.0
  20. ReFusion: 3D Reconstruction in Dynamic Environments for RGB-D Cameras Exploiting Residuals 论文阅读

热门文章

  1. Python 爬取图片链接并且解析
  2. qt android 开发之wifi开发篇
  3. app.listen(3000)与app是不一样的
  4. JS BOM之location.hash详解
  5. bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】
  6. 刘宇凡:群生?群死?群P?
  7. forward declaration of class 错误
  8. 【配置映射】—Entity Framework实例详解
  9. 用word2007发布blog
  10. 有道云笔记Windows桌面版v6.5.0.0去左下角广告方法