Rocksdb 的 BlobDB key-value 分离存储插件
前言
还是回到传统的 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之中,支持的特性:
- rocksdb的基本操作接口不需要任何变动,
DB::Put
,DB::Get
等仍然继续使用(Merge不支持),开启k/v分离,只需要打开enable_blob_files=true
以及设置min_blob_size
就可以了(简直不要太方便,当然,titan没有做成这样也可能是因为这样与rocksdb代码耦合太多了, 不方便跟进社区的版本)。 - Recovery 异常重放
- 压缩
- atomic flush
- compaction filter( 支持 用户选择读取value,有一些用户使用compaction filter 只想要key的操作,这个时候不需要将value再回传了 )
- Checkpoints
- 备份
- 事务
- 文件级别的checksum
- sst-filem-manager(后续支持ingest会比较方便)
当然还有一些特性暂时不支持:
- Merge 接口写入大value (这个特性的优先级后续会比较高,主要update场景的需求量还是很大)
- EventListener
- Secondary Instance (离线读取场景)
- ingest blob file(这个场景需求也会大一些,高效的离线导入)
GC 实现
这里简单描述一下BlobDB的key-value分离存储实现。
- 分离场景其实比较简单,在Flush/Compaction过程中判断是否开启key/value分离, 且判读写入的value是否是超过设置的
min_blob_size
,超过则通过blob_file_builder 将key-value写入到.blob文件中且对应的key+key-index则仍然存放在sst中,否则key-value都存放在sst中。 - 重点是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 分离存储插件相关推荐
- ef mysql 读写分离_基于 EntityFramework 的数据库主从读写分离服务插件
基于 EntityFramework 的数据库主从读写分离服务插件 1. 版本信息和源码 1.1版本信息 v1.01 beta(2015-04-07),基于 EF 6.1 开发,支持 EF 6.1 之 ...
- Drill官网文档翻译六:存储插件的注册
我们可以通过存储插件连接到本地文件系统,Hive,HBase,或是其他的数据源.在Drill的web界面的存储插件配置tab,你可以查看修改这些插件的配置.如果不支持HTTPS(默认就没有),你可以访 ...
- ClickHouse 冷热分离存储在得物的实践
1. 业务背景 得物上一代日志平台的存储主要依赖于 ES.随着公司业务的高速发展,日志场景逐步产生了一些新需求,主要表现在:应用数量逐步增多,研发需要打印更多的日志定位业务问题,安全合规需要保留更长时 ...
- 阿里云自建k8s存储插件csi安装使用
新钛云服已为您服务1213天 前言 k8s在阿里云上使用,推荐还是使用阿里云的ack.无论是从稳定性,以及后期的维护来说,ack 都是最优的方案,自建k8s 阿里云不提供任何帮助,一旦集群出现问题(主 ...
- 实战:k8s之存储插件-2022.2.23
目录 文章目录 目录 实验环境 实验软件 1.存储插件 2.FlexVolume
- Drill下配置Hive存储插件
安装好Drill.Hive.Hadoop,且Hive以MySQL作为元数据库 启动hive metastore 必须先启动hive metastore,否则无法添加存储插件 a@DataServer: ...
- KEPServerEX 6 之 数据存储插件Data Logger 中文说明(完整版)
DataLogger是易于配置的应用程序,可将数据从OPC服务器记录到许多ODBC兼容的数据库中.DataLogger与KEPServerEX的无缝集成提供了许多实质性的独特优 ...
- Shopee ClickHouse 冷热数据分离存储架构与实践
本文首发于微信公众号"Shopee技术团队". 摘要 Shopee ClickHouse 是一款基于开源数据库 ClickHouse 做二次开发.架构演进的高可用分布式分析型数据库 ...
- PbootCms阿里云OSS插件和七牛云存储插件
特别注意事项 URL请填写全地址,如下图是阿里云OSS提供的Bucket域名,请填写完整这个域名. 插件介绍 增加图片上传到七牛云和阿里云OSS,可选择启用. 图片上传.编辑器上传图片均已接入云存储. ...
最新文章
- TensorFlow四种Cross Entropy算法实现和应用
- win7系统中给GVim 配置ctags和taglist插件
- 致不可重新来过一次的青春(上)
- 摘:常用函数(包括:宽字符函数、普通C函数 )
- php怎么把字符转成大写,php怎么把字符串转换为大写
- 【C#学习笔记】使用C#中的Dispatcher
- linux arm current_thread_info定义,linux 内核 current全局变量
- 从Nand Flash启动U-BOOT的基本原理
- spring+hibernate+mysql mvc 配置
- rabbitmq消息的序列化与反序列化
- EasyUI 搜索框
- 学习EXT第九日:表单入门
- 很久没写了,今天兴致来了,写一下!
- php强制时间,php如何强制转成字符串
- lol大脚一直卡在读取服务器信息,英雄联盟大脚 - 英雄联盟 - LOL英雄联盟官网 - 英雄联盟攻略 - 英雄联盟专题站...
- 14周:设计会员登录页面
- 天津全国计算机等级考试考点,2018年下半年全国计算机等级考试报考简章及天津考点安排...
- 终极选择---老男孩教育
- dedecms织梦后台系统用户管理授权栏目BUG修正
- JAVA判断数字是否在指定开闭区间内
热门文章
- Usage and Idioms——Categories
- JAVA的instanceOf什么时候用
- Oracle 12C -- 基于sequence的列的默认值
- 2014腾讯校园招聘研发笔试题
- Windows Phone开发(39):漫谈关键帧动画上篇 转:http://blog.csdn.net/tcjiaan/article/details/7550506...
- 基于libmad库的MP3解码简析
- python2.7升3.7_升级python2.7至python3.7
- php构造和析构方法,php5构造函数与析构函数实例
- php ajax mysql 分页查询_基于PHP_MySql_Ajax的分页技术方案
- efishell无法开机shell_电脑出现EFIshellversion解决方法W1048/海尔青春小蓝