前言

还是回到传统的 LSM-tree 中,我们key-value 写入时以append形态存放到一个data-block中,多个data-block+metablock 之类的数据组织成一个sst。当我们读数据以及compaction的时候读到key 之后则很方便得读取到对应的value,一次I/O能够将key-value完全从磁盘读上来。但这种存储方式在大value场景下引入了非常多的读写放大,读写性能都会非常差。

所以Wisckey提出了key-value分离,且业界也有了一些不错的实现,包括Tikv/Titan, DGraph/badger等应用在工业界的实现案例。

但是,这一些对于使用rocksdb作为存储生态的用户来说还是不够方便,titan虽然是以rocksdb的插件形态存在的,但是很多rocksdb支持的功能还不够完善(checkpoint/backup, Trasaction 等需求量比较大的场景),所以虽然基本功能实现了,但还是没有办法得到更加广泛的应用。

这个时候rocksdb 社区的BlobDB经过长久的开发和完善,在旧版本的基础上实现了一个全新的BlobDB版本。

支持的特性

文章标题说的是分离存储插件,其实本身并不是插件的形态了, 这个新版本已经完全融入到rocksdb之中,支持的特性:

  1. rocksdb的基本操作接口不需要任何变动,DB::Put,DB::Get 等仍然继续使用(Merge不支持),开启k/v分离,只需要打开enable_blob_files=true 以及设置 min_blob_size就可以了(简直不要太方便,当然,titan没有做成这样也可能是因为这样与rocksdb代码耦合太多了, 不方便跟进社区的版本)。
  2. Recovery 异常重放
  3. 压缩
  4. atomic flush
  5. compaction filter( 支持 用户选择读取value,有一些用户使用compaction filter 只想要key的操作,这个时候不需要将value再回传了 )
  6. Checkpoints
  7. 备份
  8. 事务
  9. 文件级别的checksum
  10. sst-filem-manager(后续支持ingest会比较方便)

当然还有一些特性暂时不支持:

  • Merge 接口写入大value (这个特性的优先级后续会比较高,主要update场景的需求量还是很大)
  • EventListener
  • Secondary Instance (离线读取场景)
  • ingest blob file(这个场景需求也会大一些,高效的离线导入)

GC 实现

这里简单描述一下BlobDB的key-value分离存储实现。

  1. 分离场景其实比较简单,在Flush/Compaction过程中判断是否开启key/value分离, 且判读写入的value是否是超过设置的min_blob_size,超过则通过blob_file_builder 将key-value写入到.blob文件中且对应的key+key-index则仍然存放在sst中,否则key-value都存放在sst中。
  2. 重点是GC的实现,当然可以通过设置enable_blob_garbage_collection控制是否开启关闭GC。GC的调度不同于Titan的传统GC,通过EventLister 在Compaction完成之后触发,而是类似于Titan的level merge GC ,在Compaction过程中如果开启了GC,会将大value读出来,写入到新的blobfile,旧的blobfile 则会后续通过后台清理线程集中清理。

这种方式的GC实现 因为没有办法避免大value的读取,当数据量足够大的时候,compaction调度的GC引入的磁盘大量的读写导致的长尾也是无法接受的,所以社区也只能提供了可开启关闭的GC的参数来交给用户控制。

关于BlobDB中的option都是可以通过SetOptions来运行时动态变更。

性能测试

从测试结果来看,大value下的BlobDB和 TitanDB 读写性能接近,对于Rocksdb生态的用户来说BlobDB 在功能上的优势还是更受欢迎的。

测试bench mark:
测试版本:master分支
测试工具:db_bench
硬件:64core cpu + 512G mem + 3T NVMe-SSD

关闭key/value分离 随机写入性能:

numactl --cpubind=0 --membind=0 ./db_bench \--benchmarks=fillrandom,stats \--num=30000000 \--threads=16 \--writes=1000000 \--db=./db-test \--wal_dir=./db-test \--duration=120 \--key_size=16 \--value_size=8192 \-max_background_compactions=16 \-max_background_flushes=7 \-subcompactions=8 \-compression_type=none \-enable_pipelined_write=true \


下面是随机写入场景中的磁盘I/O情况,其中磁盘I/O达到1G及以上的时间底层都是有compaction调度的,带着大value 进行compaction,整体的读写代价还是很大的,可以看到磁盘偶尔会有超过2G的带宽占用,这对于只有152M的用户写入来说实在是太大的放大了。
(关于磁盘I/O没有读流量,是因为内存比较大,db数据量比较小,大多数的数据还都会被缓存在操作系统page-cache,所以compaction过程中的读基本都会命中page-cache)

作为对比,开始测试BlobDB,使用如下benchmark

numactl --cpubind=0 --membind=0 ./db_bench \--benchmarks=fillrandom,stats \--num=30000000 \--threads=16 \--writes=1000000 \--db=./db-test \--wal_dir=./db-test \--duration=120 \--key_size=16 \--value_size=8192 \-max_background_compactions=16 \-max_background_flushes=7 \-subcompactions=8 \-compression_type=none \-enable_pipelined_write=true \-enable_blob_files=true \-min_blob_size=4096 \-enable_blob_garbage_collection=true

很明显,吞吐相比于使用rocksdb来存放大value 提升了倍。

再看看磁盘I/O情况,因为我们也开启了GC,所以这个过程中会有GC的调度。从磁盘带宽来看,整体的吞吐还是比较均匀的,即使compaction + GC 一起存在,并不会有像未开启key/value分离那样的巨量I/O出现,因为不必要的key/value的value读取并不会被调度起来。

关于读性能的测试,大家可以变更benchmark为--benchmarks=readrandom,指定--use_existing_db=1--use_existing_keys=1来保证key的100%命中就好。当然,blobdb的使用在一批热点key的集中update场景下还是需要注意GC带来的带宽占用(热点update会让GC调度的频率更高,重复写入的key多,blob文件中失效的key也会很多),如果想要保持稳定的latency,软件层的优化就是限速了,或者动态开启关闭GC(业务低峰开启GC,高峰关闭GC)。

Rocksdb 的 BlobDB key-value 分离存储插件相关推荐

  1. ef mysql 读写分离_基于 EntityFramework 的数据库主从读写分离服务插件

    基于 EntityFramework 的数据库主从读写分离服务插件 1. 版本信息和源码 1.1版本信息 v1.01 beta(2015-04-07),基于 EF 6.1 开发,支持 EF 6.1 之 ...

  2. Drill官网文档翻译六:存储插件的注册

    我们可以通过存储插件连接到本地文件系统,Hive,HBase,或是其他的数据源.在Drill的web界面的存储插件配置tab,你可以查看修改这些插件的配置.如果不支持HTTPS(默认就没有),你可以访 ...

  3. ClickHouse 冷热分离存储在得物的实践

    1. 业务背景 得物上一代日志平台的存储主要依赖于 ES.随着公司业务的高速发展,日志场景逐步产生了一些新需求,主要表现在:应用数量逐步增多,研发需要打印更多的日志定位业务问题,安全合规需要保留更长时 ...

  4. 阿里云自建k8s存储插件csi安装使用

    新钛云服已为您服务1213天 前言 k8s在阿里云上使用,推荐还是使用阿里云的ack.无论是从稳定性,以及后期的维护来说,ack 都是最优的方案,自建k8s 阿里云不提供任何帮助,一旦集群出现问题(主 ...

  5. 实战:k8s之存储插件-2022.2.23

    目录 文章目录 目录 实验环境 实验软件 1.存储插件 2.FlexVolume

  6. Drill下配置Hive存储插件

    安装好Drill.Hive.Hadoop,且Hive以MySQL作为元数据库 启动hive metastore 必须先启动hive metastore,否则无法添加存储插件 a@DataServer: ...

  7. KEPServerEX 6 之 数据存储插件Data Logger 中文说明(完整版)

    ​​​​​​      DataLogger是易于配置的应用程序,可将数据从OPC服务器记录到许多ODBC兼容的数据库中.DataLogger与KEPServerEX的无缝集成提供了许多实质性的独特优 ...

  8. Shopee ClickHouse 冷热数据分离存储架构与实践

    本文首发于微信公众号"Shopee技术团队". 摘要 Shopee ClickHouse 是一款基于开源数据库 ClickHouse 做二次开发.架构演进的高可用分布式分析型数据库 ...

  9. PbootCms阿里云OSS插件和七牛云存储插件

    特别注意事项 URL请填写全地址,如下图是阿里云OSS提供的Bucket域名,请填写完整这个域名. 插件介绍 增加图片上传到七牛云和阿里云OSS,可选择启用. 图片上传.编辑器上传图片均已接入云存储. ...

最新文章

  1. TensorFlow四种Cross Entropy算法实现和应用
  2. win7系统中给GVim 配置ctags和taglist插件
  3. 致不可重新来过一次的青春(上)
  4. 摘:常用函数(包括:宽字符函数、普通C函数 )
  5. php怎么把字符转成大写,php怎么把字符串转换为大写
  6. 【C#学习笔记】使用C#中的Dispatcher
  7. linux arm current_thread_info定义,linux 内核 current全局变量
  8. 从Nand Flash启动U-BOOT的基本原理
  9. spring+hibernate+mysql mvc 配置
  10. rabbitmq消息的序列化与反序列化
  11. EasyUI 搜索框
  12. 学习EXT第九日:表单入门
  13. 很久没写了,今天兴致来了,写一下!
  14. php强制时间,php如何强制转成字符串
  15. lol大脚一直卡在读取服务器信息,英雄联盟大脚 - 英雄联盟 - LOL英雄联盟官网 - 英雄联盟攻略 - 英雄联盟专题站...
  16. 14周:设计会员登录页面
  17. 天津全国计算机等级考试考点,2018年下半年全国计算机等级考试报考简章及天津考点安排...
  18. 终极选择---老男孩教育
  19. dedecms织梦后台系统用户管理授权栏目BUG修正
  20. JAVA判断数字是否在指定开闭区间内

热门文章

  1. Usage and Idioms——Categories
  2. JAVA的instanceOf什么时候用
  3. Oracle 12C -- 基于sequence的列的默认值
  4. 2014腾讯校园招聘研发笔试题
  5. Windows Phone开发(39):漫谈关键帧动画上篇 转:http://blog.csdn.net/tcjiaan/article/details/7550506...
  6. 基于libmad库的MP3解码简析
  7. python2.7升3.7_升级python2.7至python3.7
  8. php构造和析构方法,php5构造函数与析构函数实例
  9. php ajax mysql 分页查询_基于PHP_MySql_Ajax的分页技术方案
  10. efishell无法开机shell_电脑出现EFIshellversion解决方法W1048/海尔青春小蓝