LSM 优化系列(二)-- dCompaction: Speeding up Compaction of the LSM-Tree via Delayed Compaction
文章目录
- 背景描述
- dCompaction设计
- 触发条件 VCT
- 触发VT 合并的条件 VSMT
- 测试数据
优化的重心集中在减少写放大上,同时将读性能维持在和rocksdb 原生读性能接近,优化思想是中国科学院的2位博士 提出的。
论文原地址:
dCompaction: Speeding up Compaction of the LSM-Tree via Delayed Compaction
背景描述
关于LSM的问题,这里不多介绍,有兴趣的同学可以看看之前 总结的相关优化论文的描述:
1. PebblesDB Building Key-Value Stores using FLSM-Tree(Fragmented) SOSP‘17
2. X-Engine: An Optimized Storage Engine for
Large-scale E-commerce Transaction Processing SIGMOD’19
论文中 通过YSCB 构造的workload 来统计 三种类型的操作造成的IO:Compaction, Get, Put.
如下图:
其中IO操作主要是由compaction 造成的,而读IO仅仅会由读的比例的增加而增加,且最大不会超过 总的IO的20%,也就是大部分IO操作都是由Compaction造成的。
再通过分析Compaction的实现 如下图:
可以发现实际compaction过程中针对同一个key可能会写入多次,比如C2–>C3 compaction,会将选择的C3的文件经过合并再次写入到C3之中,这就是写放大的源头。
dCompaction设计
为了减少写放大,dCompaction核心设计了 virtual compaction 和 virtual SSTables,如下图:
compaction过程中 内存里维护virtual sstables ,之间以树状结构来管理实际的real stabiles。virtual sstables 包含如下几种类型的元数据:
- smallest key
- largest key
- file number
- file size
- Parent SStables
相比于实际的real sstables 多了一个parent SStables,用来管理实际的sst文件
dCompaction 实际的过程如下图
原本的Compaction实现:
T22@L2 + T32,T33@L3 --> T34,T35,T36@L3
T34,T35,T36@L3 + T42,T43@L4 --> T44,T45,T46,T47,T48@L4
也就是T34,T35,T36中的key-value会被多读、多写一次
dCompaction实现:
T22@L2 + T32,T33@L3 --> VT34,VT35,VT36@L3
这一步仅仅将实际的sstable中的元数据读上来,在内存中构造 virtual table,合并real table的元数据,从而完成virtual compaction。不需要对T34,T35,T36中的数据多读写一次。
VT34,VT35,VT36@L3 + VT42,VT43@L4 --> T44,T45,T46,T47,T48@L4
这一步通过L3的virtual table + L4的virtual table 完成一次real compaction。
通过dCompaction,将实际T22@L2 + T32,T33@L3 + T22@L2 + T32,T33@L3 + T42,T43@L4 --> T44,T45,T46,T47,T48@L4
降低为T22@L2 + T32,T33@L3 + T42,T43@L4 --> T44,T45,T46,T47,T48@L4
所有的key-value仅仅只需要产生一次IO操作即可,能够有效得降低读写放大,提升写性能。
但是这个过程 对读性能有影响。dCompaction 下的读 和 原生rocksdb的读 流程对比如下图:
实际的读在有virtual table的情况下会有如下几步:
- 读memtable
- 读block cache
- 读virtual table
- 确认key是在VT smallest – largest key之间
- 读Parent sstables
- 从实际的T 中读取key-value
相比于从实际的T中直接读取 多了两步。
触发条件 VCT
VCT定义了一个阈值用来控制当前compaction是virtual compaction还是real compaction,触发算法如下:
compaction开始
选择需要被合并的 sst files
sst files 计数
Count = sst files 计数
如果 Count < VCT
触发virtual compaction
否则
触发real compaction
如果VCT 被设置为0,那么默认就是real compaction;
随着VCT被设置的数值不断增加,virtual compaction会触发得越来越频繁,compaction产生的IO会降低,但是VCT 越大,并不代表系统性能越好。
- 这其实也是变相的compaction delay,virtual compaction进行的越多,单次real compaction的量会越大,这一次的 real compaction会将系统的性能拖到低谷。
- Virtual compaction越多,real ssttables 也会越多,这其实会增加读延时,从而降低读性能。
所以VCT的值需要做一个实际的测试来平衡real compaction 和 sst files 计数 compaction
触发VT 合并的条件 VSMT
这个阈值主要是用来控制一个virtual sstables 能够包含多少real sstables,如果读的过程中发现virtual sstables的real sstables 超过了这个阈值,就对当前virtual sstables进行合并。
这个参数主要是为了 降低 的读请求命中VT 的时 对读性能的影响。
比如读请求命中 VT34,发现其中的real sstables 的个数超过VSMT,那么触发VT的合并。
将VT34 管理的三个real sstables T22,T32,T33都读到内存中,合并为T34,T35,T36。
同理 其他的VT35,VT36 也需要合并到T35,T36。这个过程其实是对IO带宽的一种浪费,但是VT merge 能够减少查找时的IO,提升读性能。
实际的合并算法:
如果 sstable.type == virtaul sstable
2. 计算VT中有多少个real sstables
3. Count = the number of real sstables
4. 如果 Count >= VSMT
合并virtual sstable 到real sstables
实际VSMT 也不能随意设置,否则同样会对性能有很大的影响。
如果VSMT设置的过小,VT merge会很频繁,将增加合并过程中的IO消耗(需要读到内存,合并 并写入)。为了降低一部分读延时,缺增加了dCompaction对读写放大的优化效果。
而如果VSMT设置的过大,VT 得不到合并,同样无法达到提升读性能的效果。
测试数据
硬件如下:
CPU: Intel Xeon E5645 (6core,2.4GHz, 12MB L3 cache)
DRAM:2GB
2 * 1TB SATA hdd( 平局寻道时间/旋转延时 : 8.5 ms/4.2 ms, 传输带宽:150M/s)
1 * 480GB SATA intel ssd (平均读/写延时:80 μs/85 μs, 平均读/写带宽:550/520 MB/s)
rocksdb 配置 都是默认的配置,dCompaction的VCT 是12, VSMT 是5。
使用YCSB 按照读写比,生成的workload。
和开头提到的 dCompaction的目标集中在减少写放大,保证读性能。
如下图为四种workload下的测试情况:
D1: (2.4×10^7, 1, 0, 256 B, 6 GB),
D2: (2.4×10^7, 0.8, 0.2, 256 B, 5 GB),
D3: (2.4×10^7, 0.2, 0.8, 256 B, 2 GB),
D4: (2.4×10^7, 0, 1, 256 B, 6 GB)
其中 D(O, W, R, V, S) 为数据集的描述,O表示操作次数,W 表示写占的比例,R 表示读占的比例,V 表示value siz,S 表示总的数据集大小。
如上图可以看到 dCompaction的实现对整体的写性能有很大的提高,同时也有不弱于rocksdb的读性能。
后续还有更加详细的性能数据,相同数据量下两种compaction产生的IO量对比,读写延时对比,不同数据集对性能的影响 以及 VCT和VSMT 指标对性能的影响。
相关文章:

Android应用系列:完美运行GIF格式的ImageView(附源码)
前言 我们都知道ImageView是不能完美加载Gif格式的图片,如果我们在ImageView中src指定的资源是gif格式的话,我们将会惊喜的发觉画面永远停留在第一帧,也就是不会有动画效果。当然,经过略加改造,我们是可以让gif在Image…

wordpress怎么修改html,WordPress后台编辑器HTML模式界面中添加修改删除按钮
在WordPress编辑器HTML模式界面中添加按钮一文中,我大致介绍了怎么在后台添加一些自定义的按钮,本文则更为详细全面的对wordpress后台编辑器HTML模式下的按钮自定义进行详解,以让开发者肆意的修改按钮及其布局。自定义按钮起效的两种途径 ↑首…

OCA读书笔记(9) - 管理数据同步
9.Managing Data Concurrency 描述锁机制以及oracle如何管理数据一致性监控和解决锁冲突 管理数据的并发--管理锁数据的不一致:脏读更改丢失幻影读 脏读:数据是指事务T2修改某一数据,并将其写回磁盘,事务T1读取同一数据后,T2由于某…

Java EE学习笔记(四)
Spring的数据库开发 1、Spring JDBC 1)、Spring JDBC模块的作用:Spring的JDBC模块负责数据库资源管理和错误处理,大大简化了开发人员对数据库的操作,使得开发人员可以从繁琐的数据库操作中解脱出来,从而将更多的精力投入到编写业务…

SpringBoot 中实现订单30分钟自动取消的策略
在电商和其他涉及到在线支付的应用中,通常需要实现一个功能:如果用户在生成订单后的一定时间内未完成支付,系统将自动取消该订单。本文将详细介绍基于Spring Boot框架实现订单30分钟内未支付自动取消的几种方案,并提供实例代码。

一键部署 SpringCloud 微服务,这套流程值得学习一波儿!
一键部署 springcloud 微服务,需要用到 Jenkins K8S Docker等工具。本文使用jenkins部署,流程如下图开发者将代码push到git运维人员通过jenkins部署,自动到git上pull代码通过maven构建代码将maven构建后的jar打包成docker镜像 并 push docker镜像到docker registry通过k8s发起 发布/更新 服务 操作其中 2~5步骤都会在jenkins中进行操作。

Rocksdb 的 rate_limiter实现 -- compaction限速
文章目录前言1. Compaction为什么会影响Client qps1.1 基本LSM介绍1.2 LSM internal ops1.3 长尾延时的原因2. Rate limiter 基本限速接口3. Rate Limiter 限速原理实现3.1 Rate Limiter的传入3.2 Rate Limiter 控制 sync datablock的速率3.3 Rate Limiter控制写入速率4. rocks…

Oracle --获取绑定变量的值.
SELECT * FROM DBA_HIST_SQLBIND WHERE SNAP_ID>67073 AND SNAP_ID<67079 AND SQL_ID3DR3410F086P4;SELECT * FROM v$sql_bind_capture where sql_id http://blog.itpub.net/22034023/viewspace-689802/ 通过v$sql_bind_capture视图,可以查看绑定变量…

计算机网络TCP/IP协议-从双绞线到TCP
消息响应也是同理,这种带端口的消息发送方式,其实就是UDP协议,UDP简单粗暴,但是UDP存在很多问题,所以我们需要设计一个稳定可靠的协议,TCP协议,首先,网络是不稳定的,我们发送的消息很有可能会在中途丢失,所以需要设置重试机制,当消息发送失败时重新发送,为了判断是否成功,还需要要求接收方收到消息后,必须发送确认消息,这样就可以保证消息必达,另外大段的内容发送,很容易造成部分丢失,导致全部内容都要重新发送,于是我们可以将数据分包,分成多个包发送。到这,也行你会发现了,演示中的IP地址是怎么设置的呢?

使用HTML CSS完成初步的页面,任务九:使用HTML/CSS实现一个复杂页面(示例代码)
任务目的通过实现一个较为复杂的页面,加深对于HTML,CSS的实战能力实践代码的复用、优化任务描述整个页面内容宽度固定,但头部的蓝色导航和浏览器宽度保持一致任务注意事项只需要完成HTML,CSS代码编写,不需要写JavaScri…

Yii-yiic使用
原文在:http://blog.sina.com.cn/s/blog_862b12fb0101n00v.htmlyii提供了强大的命令行工具来快速的创建相关组件和应用。下面就来讲解用yiic工具快速创建yii应用我的web目录在d:\ EasyPHP-DevServer\data\localweb下;yiiframework在D:\EasyPHP-DevServer…

nginx语法
一、 1. 配置文件由指令与指令块构成; 2. 每条指令以;分号结尾,指令与参数间以空格符号分隔; 3. 指令块以{} 大括号将多条指令组在一起; 4. include语句允许组合多个配置文件以提升可维护性; 5. 使用#符号添…

如何对 Rocksdb以及类似存储引擎社区 提出 有效的性能问题?
性能 是rocksdb的优点,活跃的社区十分欢迎大家对各自使用rocksdb 过程中性能相关的疑惑点进行提问。提问的时候如果能够提供更多,更详细的信息 是可以增加快速得到恢复回复的概率。当然,性能是一个非常广泛且有巨量影响因素的话题,…

我已经喜欢上了Python
早就听说了Python语言,今天试了试,挺喜欢她了。 Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32Type "copyright", "credits" or "license()" for more information.&g…

layui跳转html如何带参数,Layui跳转页面代码(可携带复杂参数)
今天用了Layui的“数据表格 - 数据操作”示例代码,结果发现点击“编辑”按钮出出来一个弹出消息框,效果如下:虽然说也可以用“弹出层”做编辑页面,但是,由于我编辑的东西很多,用“弹出层”不太理想。我就想…

java获取日期
/* * 获取昨天日期 方法一,这个方法好像有点慢 */Date dt new Date(); Calendar cal Calendar.getInstance();cal.add(Calendar.DATE, -1);time new SimpleDateFormat( "yyyy-MM-dd").format(cal.getTime()); /* * 获取昨天日期 方法二 */Date as ne…

DRF (Django REST framework) 中的视图类
视图说明 1. 两个基类 1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类。 APIView与View的不同之处在于: 传入到视图方法中的是REST framework的Request对象,而不是…

Go:分布式学习利器(1) -- 开发环境搭建 + 运行第一个go程序
文章目录为什么要学习 go开发环境搭建 -- MAC运行第一个go程序go 函数的返回值设置go 函数的命令行参数为什么要学习 go 在如下几个应用场景的需求下产生了go: 超大规模分布式计算集群多核硬件的架构web模式下的大规模开发和频繁的进度更新 所以go 语言有如下几个特点&#…

html生成的超级链接预览功能,超链接特效
功能说明超链接特效功能是基于报表特殊效果功能的一种扩展实现。报表特殊效果功能的作用是为单元格添加一些特殊的显示效果。超链接特效可以给超链接添加特殊显示效果,实现超链接功能的扩展增强。当产品默认生成的超链接显示效果不能满足用户的个性化需求时…

ROOT android 原理。 基于(zergRush)
出自: http://bbs.gfan.com/android-2996211-1-1.html 须要ROOT的同学请去上面的地址下载。 a.控制手机创建个暂时目录,然后把zergRush脚本写入此目录,并改动此文件权限使之能够运行(这一步无需ROOT权限); adb shell rm -r /data/local/tmpadb shell mkdir /data/lo…

Oracle数据库日常维护知识总结
DBA要定时对数据库的连接情况进行检查,看与数据库建立的会话数目是不是正常,如果建立了过多的连接,会消耗数据库的资源。同时,对一些“挂死”的连接,可能会需要DBA手工进行清理。首先要说的是,不同版本数据…

JAVA 第五周学习总结
20175304 2018-2019-2 《Java程序设计》第五周学习总结 教材学习内容总结 Java为什么要定义接口:接口的作用是实现多重继承,因为一个子类只能继承一个父类,但是可以实现一个或多个接口。使用关键字interface来定义一个接口,定义方…

Go: 分布式学习利器(2)-- Go中的变量,常量 以及与其他语言变量之间的差异
文章目录1. Go 语言编写测试代码2. Go 的变量3. Go 常量定义1. Go 语言编写测试代码 源码文件以 _test结尾: xxx_test.go测试方法名需以Test开头: func TESTXXX(t *testing.T) {..} ,且参数列表直接用go 默认的test参数即可 如下first_test…

Scala:Functions and Closures
1 object Functions {2 def main(args: Array[String]) {3 // 本地函数4 def localFun(msg: String) println(msg)5 localFun("Hi")6 7 // 函数对象8 var list List(1, 2, 3)9 list.foreach((x: Int) > println(x)) 10 list.fore…

云计算机机房怎么样,如何知道云电脑配置多少?怎么选择云电脑机房?
一般在玩一款游戏时,需要考虑玩游戏的配置,云电脑帮助我们实现配置的需求,那如何才能知道云电脑配置是多少,该怎么选择云电脑机房。在使用云电脑时,我们不用考虑自己的手机、平板和电脑的硬件,只要设备能正…

eclipse中新建android项目,不自动生成R.java
http://huyuantai000.iteye.com/blog/1681582转载于:https://www.cnblogs.com/wmm3416/p/3386698.html

获取子iframe的属性
第一种方法: <iframe name"iframeName" src"http://www.test.com"></iframe> // name"iframeName" 取值 window.frames[iframeName] 第二种方法: <iframe id"iframeId" src"http://www.t…

Go: 分布式学习利器(3) -- Go的数据类型和运算符
文章目录1. Go的数据类型1.1 类型转化1.2 类型的预定义1.3 指针类型2. Go 的运算符1. Go的数据类型 GO的基本数据类型如下: bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // 基本和uint8 类型一样 rune // 代表unicode …

云职教课堂计算机文化基础,2020智慧职教云课堂计算机文化基础答案最新最全单元测试答案...
参考答案如下智慧职教最新最全【判断题】两种气体在相同温度下放入同一个容器中,测得的压强分别为 和 ,则把它们同时放入容器中后的总压强为 .云课【单选题】根据物质的导电能力,将物质分为哪些类别?A. 导体 B. 半导体 C. 绝缘体 D. 以上都对堂计【单选题】按照数的进位制概念…
测试用例挑选策略
在软件开发过程中,无论是在feature testing还是在final regression testing中,测试策略的好坏在整个质量保证过程中起着至关重要的作用,尤其是在测试资源有限的情况下,影响更为突出。好的测试策略能够更快速的发现软件最有value的…