聊聊RocksDB Compact
导语 对于 LevelCompact 策略,RocksDB会根据每一层不同的策略计算出CompactScore,根据CompactScore大小来决定那一层将会优先进行Compact,然后选择Level-N 和Level-(N+1)的文件进行Compact。如何计算CompactScore? 如何选择文件进行Compact?Compact有哪些参数?如何知道RocksDB当前的一个状态?
RocksDB是基于LSM结构的K-V存储引擎,由于数据文件采用Append Only方式写入,而对于过期的数据、重复的数据必然会存在有多份副本,这部分数据通过Compact的方式进行逐步的清理。
那么这里好奇的提出几个问题,由这几个问题引出下文:
- RocksDB是如何进行Compact 的?
- Compact的时候这些文件是如何进行选择的?
- Compact在什么时候、或者什么条件下触发?
- 对于Compact我们能知道哪些信息?通过TRedis怎么查看这部分信息?
- 有哪些参数可以控制或者影响到Compact
由于我们的TRedis底层采用RocksDB存储引擎进行持久化,底层数据文件采用分层的方式管理,故这里讨论的Compact 基于Level Compact 。
数据怎么来?我们调用TRedis接口进行写数据时,数据会先写入到内存中的Memtable里边,当Memtable写满后会写入下一个Memtable,Memtable采用Skiplist结构以此保证数据按照Key的字典序进行排序,同时这个Memtable会被后台线程刷到磁盘文件–Level-0,当Level-0文件个数达到一定数量,Compact线程可能会进行Compact,由此产生Level-1,当Level-1文件总大小达到一定大小后, Compact线程可能会进行Compact,由此产生Level-2,…….
RocksDB对每一层的处理规则不太一样,由于Level-0层的数据直接由Memtable dump得到,从而不能保证Level-0层的每个文件Key的范围不能有交集,故对Level-0层的会进行特殊处理,而对于Level-1+层处理规则一样。
Level-0 层的文件在不停的从Memtable 中dump出来,那么何时才会把这些Level-0层的文件合并到Level-1 ?
RocksDB对对每一层进行打分,分数从0~1000000,这个分数的大小决定了进行Compact 的优先级,分数越大,越先进行Compact。
那么这个分数如何计算出来?
- 如果是Level-0层,会先算出当前有多少个没有进行Compact 的文件个数numfiles, 然后根据这个文件的个数进行判断,
当numfiles<20 时,Score = numfiles/4;当24>numfiles>=20时,Score = 10000;当 numfiles>=24时,Score = 1000000
:
相关参数 | 值 | 说明 |
---|---|---|
level0_file_num_compaction_trigger | 4 | 当有4个未进行Compact的文件时,达到触发Compact的条件 |
level0_slowdown_writes_trigger | 20 | 当有20个未进行Compact的文件时,触发RocksDB,减慢写入速度 |
level0_stop_writes_trigger | 24 | 当有24个未进行Compact的文件时,触发RocksDB停止写入文件,此时会尽快的Compact Level-0层文件 |
- 如果是Level-1+层,会去计算每一层未进行Compact文件的总Size,然后再和这一层的”容量值”做对比,得到一个比值,这个值就是该层的 CompactScore ,也就是说对于Level-1+层,Compact 触发条件是看这一层文件的大小而不是个数。
Score = level_bytes / MaxBytesForLevel(level)
对于Level-1+层,每一层的最大Bytes 是如何计算出来的?
Level-1 层 文件总大小由 max_bytes_for_level_base 参数控制,而 Level-2 层的大小通过: Level_max_bytes[N] = Level_max_bytes[N-1] * max_bytes_for_level_multiplier^(N-1)*max_bytes_for_level_multiplier_additional[N-1] 计算得出:
参数 | 值 | 说明 |
---|---|---|
max_bytes_for_level_base | 10485760 | 用于指定Level-1 层总大小,超过这个值满足触发Compact条件 |
max_bytes_for_level_multiplier | 10 | 每一层最大Bytes 乘法因子 |
max_bytes_for_level_multiplier_addtl[2] | 1 | Level-2 层总大小调整参数 |
max_bytes_for_level_multiplier_addtl[3] | 1 | Level-3 层总大小调整参数 |
max_bytes_for_level_multiplier_addtl[4] | 1 | Level-4 层总大小调整参数 |
max_bytes_for_level_multiplier_addtl[5] | 1 | Level-5 层总大小调整参数 |
max_bytes_for_level_multiplier_addtl[6] | 1 | Level-6 层总大小调整参数 |
if (i > 1) {level_max_bytes[i] = MultiplyCheckOverflow(MultiplyCheckOverflow(level_max_bytes[i - 1],max_bytes_for_level_multiplier),max_bytes_for_level_multiplier_additional[i - 1]);} else {level_max_bytes[i] = max_bytes_for_level_base;}
在进行Compact的时候,会选择哪些文件进行Compact操作呢?
对于Level-0层文件,RocksDB总是选择所有的文件进行Compact操作,因为Level-0层的文件之间,可能会有key范围的重叠。
对于Level-N (N>1)层的文件,会先按照文件大小排序(冒泡排序),选出最大的文件,并计算这个文件Key 的起止范围,通过这个范围查找Level-N+1层文件,把选出的Level-N 文件和Level-N+1 文件做为输入,并且在Level-N+1新建一个或多个SST文件作为输出。
可以通过设置max_background_compactions 大于1 来使用并行Compact,不过这个并行Compact 不能作用到Level-0层。
// Find the compactions by size on all levels.
for (int i = 0; i < NumberLevels() - 1; i++) {double score = vstorage->CompactionScore(i);level = vstorage->CompactionScoreLevel(i);
assert(i == 0 || score <= vstorage->CompactionScore(i - 1));
if ((score >= 1)) {
c = PickCompactionBySize(mutable_cf_options, vstorage, level, score);
if (c == nullptr ||
ExpandWhileOverlapping(cf_name, vstorage, c) == false) {delete c;
c = nullptr;} else {
break;}}}
如何查看RocksDB内部状态?
一般情况下内部状态会定时dump出来存放到LOG文件里,这个时间可以通过:stats_dump_period_sec 来控制这个dump内部状态的频率,如果是TRedis V1.2.9 版本以上可以通过 rocksprop rocksdb.cfstats 得到这些信息:
聊聊RocksDB Compact相关推荐
- 关于数据存储引擎结构,没有比这篇更详细的
摘要:常见存储算法结构涵盖:哈希存储,B .B+.B*树存储,LSM树存储引擎,R树,倒排索引,矩阵存储,对象与块,图结构存储等等. 介绍 在存储系统的设计中,存储引擎属于底层数据结构,直接决定了存储 ...
- 带你全面了解compaction 的13个问题
作者: h5n1 原文来源: https://tidb.net/blog/eedf77ff 1 概述 TiKV 底层存储引擎使用 RocksDB ,RocksDB 是一个基于 LSM tree 的单机 ...
- 【图文详解】一文全面彻底搞懂HBase、LevelDB、RocksDB等NoSQL背后的存储原理:LSM-tree 日志结构合并树...
LSM 树广泛用于数据存储,例如 RocksDB.Apache AsterixDB.Bigtable.HBase.LevelDB.Apache Accumulo.SQLite4.Tarantool.W ...
- rocksdb原理_RocksDB解析
0. 存储引擎基础 存储引擎的基本功能和数据结构 一个存储引擎需要实现三个基本的功能: write(key, value) ...
- LSM-Tree 与 RocksDB
冥冥之中,接触到了不同于关系数据库的NoSQL Key-Value存储引擎RocksDB,懵懵懂懂.充满好奇,google一点,满眼皆是LSM-Tree,头晕眼花.若即若离,便有了这篇文章,一起与大家 ...
- Rocksdb 写流程,读流程,WAL文件,MANIFEST文件,ColumnFamily,Memtable,SST文件原理详解
文章目录 前言 Rocksdb写流程图 WAL 原理分析 概述 文件格式 查看WAL的工具 创建WAL 清理WAL MANIFEST原理分析 概述 查看MANIFEST的工具 创建 及 清除 MANI ...
- rocksdb学习笔记
rocksdb是在leveldb的基础上优化而得,解决了leveldb的一些问题. 主要的优化点 1.增加了column family,这样有利于多个不相关的数据集存储在同一个db中,因为不同colu ...
- 聊聊JVM(八)说说GC标记阶段的一些事
这篇说说GC标记阶段的一些事情,尝试把一些概念说清楚.本人不是研究JVM实现的,如果表述有问题请查看参考资料进一步学习,推荐高级语言虚拟机圈子 ,里面有很多好的文章值得一看. GC最简单的理解就是先把 ...
- rocksdb原理_[转]Rocksdb Compaction原理
概述 compaction主要包括两类:将内存中imutable 转储到磁盘上sst的过程称之为flush或者minor compaction:磁盘上的sst文件从低层向高层转储的过程称之为compa ...
最新文章
- mysql册_Mysql手册
- 负载过高之外网抓数据
- 开发日记-20190328 关键词 利用eolinker一键快速生成API接口文档
- 【Spring Boot 实战开发】第2讲 Kotlin类型系统与空安全
- 一个对象,数组去重的方法
- Debian7 apt源设置
- P4619 [SDOI2018]旧试题
- sqlite换成mysql_从SQLITE的数据转到MYSQL
- HttpServletRequestWrapper使用技巧(自定义session和缓存InputStream)
- “用户、组或角色'XXX'在当前数据库中已存在”问题
- 一键安装lnmp脚本(包括软件版本)
- Flutter AnimatedSwitcher 动画切换组件的基本使用
- T计算机硬件系统是指,计算机硬件系统试题 有答案
- Eclipse主题设置方法(系统主题设置、自行下载主题设置)
- VB2010(3)整型运算
- tomcat 加载js 中文乱码
- 【LTE】Qualcomm LTE Packets log 分析(二)LTE Access Stratum Log Analysis 3_SRB1 4_UL_DATA_Tran
- 基于Femu搭建ZNS
- 西瓜书研读——第三章 线性模型: 线性判别分析 LDA
- DQL:数据库查询语句
热门文章
- RHEL 5服务篇—常用网络配置命令
- @查看MySQL版本的方法
- 软件工程形式化技术简介
- 计算机机房安全风险防控规范,中心机房安全风险分析一览表
- mysql group concat_MySQL 的 GROUP_CONCAT 函数详解
- 线性判别结合源码分析LDA原理
- Python 生成requirement 使用requirements.txt
- Storm的通信机制
- sklearn中常用的数据预处理方法
- css标签resolution,html/css to fit all screen resolution