作者:金长龙
爱可生测试工程师,负责DMP产品的测试工作
本文起源:原创投稿
*爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
先前在做OB存储引擎这块学习的时候,对 OceanBase 的分层转储和 SSTable 这块有些细节就懵懵的,比方L0层的 mini SSTable 的每次生成是否就计入转储次数,L0层到L1层转储的机会以及和 minor_compact_trigger 之间的关系等。 明天就这部分内容做个更粗疏的探索,试图更深刻的了解 OceanBase 的分层转储。
一、LSM-Tree
首先来看一下 LSM-Tree(全称是Log-Structured Merge Tree),当下许多较新的数据库都会抉择LSM-Tree作为存储构造,比方TiDB、Cassandra、OceanBase等。LSM-Tree的劣势是程序写,晋升了整体写入性能。
LSM-Tree 大抵能够分为两局部:
- Memtable: 常驻内存的 KV 查找树 + 无序的 WAL 文件
- SSTable (Sorted String Table): 一组存储在磁盘的不可变文件,存储有序的键值对
写入流程
1、同步写 Memtable
先将数据写入 WAL 文件,而后批改内存中的 AVL,因而最优状况下,每次写操作只有一次磁盘 I/O。
删除操作并不会间接删除磁盘中的内容,而是将删除标记(tombstone)写入 Memtable。当 Memtable 增大到肯定水平后,则会转换为 Immutable Memtable 并产生一个新的 Memtable 承受写操作。
2、异步写 SSTable
后盾会启动一个合并线程,当 Immutable Memtable 达到肯定数量,合并线程会将其写入磁盘(Flush),生成 Level 0 的 SSTable 文件。
当 Level N 的 SSTable 文件数量达到阈值之后,会进行合并压缩(Compaction)操作,在 Level N+1 生成新的 SSTable 文件。
SSTable 分为多层,单个文件的大小通常是上一层的 10 倍,每层能够同时蕴含多个 sst file,每个文件由多个 block 组成,其大小约为 32K,是磁盘 IO 的根本单位。
第 Level i (i > 0) 层的 SSTable 满足:
- 第 i 层所有文件均由 i - 1 层的 SSTable 合并排序而来,能够通过设定阈值(文件个数...)来管制合并的行为
- 文件之间是有序的,且每个文件的 key 汇合不会与其余文件有交加(Level 0 的 SSTable 除外)
Compaction 策略
罕用的 Compaction 策略有 Classic Leveled、Tiered、Tiered & Leveled 、FIFO 等,简略介绍下前3种。
1、Classic Leveled
Classic Leveled 模式下每一层都是独立的"Sorted Run" ,代表是按Key排序且同层sst file之间的Key值没有重合,数量大小是逐层增大。相邻的两层sst file比称之为fanout(扇出),每次做Compaction的条件是Ln层大小达到了阈值,将Ln层数据与Ln+1层数据进行合并。因为每次做Compaction都将Ln层数据写入到Ln+1中,写放大状况会比较严重, 比方L1 ,L2 两层fanout是10,那么L1层写满后与L2层做排序合并,重写生成新的L2层,那么写放大最坏状况下等于fanout
2、Tiered
Tiered 模式与 Classic Leveled 的区别在于每一层的sst file之间Key有重合的,每层有多个"Sorted Run",每次做Compaction都是同层先做合并生成一个新的sst file写入到下一层中,这里与Leveled最重要区别是写入到下一层后不再须要排序合并、重写,因为Tiered每层存在多个"Sorted Run",那么写放大最坏状况下为1。然而相比于Leveled,会有读放大和空间放大会比较严重。
3、Tiered & Leveled
Tiered & Leveled 模式是指对于层级较小的 Level,数据量比拟小,写入的数据较新,被更新的可能性比拟大,应用 Size-Tiered 模式缩小写放大问题;对于层级较大的 Level,SSTable 的数据量较大,数据比拟旧不太容易被更新,应用 Leveled 模式缩小空间放大问题。
二、OceanBase的分层转储
OceanBase 数据库的存储引擎就是基于 LSM-Tree 架构的设计,也是划分为内存中的MemTable 和磁盘上的SSTable。OceanBase 将磁盘上的 SSTable 划分为三层,应用的是 Tiered & Leveled 的 Compaction 策略,在 L0 层应用 Tiered 模式,在 L1 层、L2 层应用 Leveled 模式。
OceanBase 中的 Compaction 分为三种类型:Mini Compaction、Minor Compaction、Major Compaction。 其中Major Compaction指的是大合并,咱们先不谈,这里只说一下Mini Compaction和Minor Compaction。
Mini Compaction (转储)
Mini Compaction 是一种 Tiered 类型的 Compaction,外围就是开释内存和数据日志,内存中的 Frozen MemTable 通过 Mini Compaction 变成磁盘上的 Mini SSTable。
Mini Compaction 在OceanBase设计里代表的就是一次转储,对应的类型是 MINI_MERGE
Minor Compaction
随着用户数据的写入,Mini SSTable 的数量会逐步增多,在查问时须要拜访的 SSTable 数量会增多,会影响查问的性能。Minor Compaction 就是将多个 Mini SSTable 合成一个,次要目标是缩小 SSTable 的数量,缩小读放大问题。当 Mini SSTable 的数量超过阈值时,后盾会主动触发 Minor Compaction。
Minor Compaction 细分为两类:
1、L0 -> L0
Tiered 类型的 Compaction,将若干个 Mini SSTable 合成一个 Mini SSTable,搁置于 L0 层。 对应的类型是 MINI_MINOR_MERGE
2、L0 - > L1
Leveled 类型的 Compaction,将若干个 Mini SSTable 与 Minor SSTable 合成一个新的 Minor SSTable,搁置于 L1 层。 对应的类型是 MINOR_MERGE
试验(应用社区版OceanBase 4.0.0.0)
测试创立的租户ob_bench,内存2G。几个次要参数设置为
memstore_limit_percentage = 50
freeze_trigger_percentage = 20
minor_compact_trigger = 2
_minor_compaction_amplification_factor = 25
major_compact_trigger = 9999 (咱们本次试验仅是想>摸索L0、L1级的Compaction,不心愿触发大合并,所以该参数设置一个极大值)
试验一:在继续数据流的状况下,观测L0, L1层转储的机会
1、创立测试库sysbench,用sysbench工具创立1张表sbtest1、数据100W。
租户每触发一次转储 memtable dump flush的数据必然是蕴含许多表的,我这里只创立1张业务表,仅是心愿后续测试时业务变更绝对集中
sysbench /usr/share/sysbench/oltp_insert.lua --mysql-host=172.30.134.1 --mysql-db=sysbench --mysql-port=2881 --mysql-user=root@ob_bench --tables=1 --table_size=1000000 --report-interval=10 --db-driver=mysql --skip-trx=on --db-ps-mode=disable --create-secondary=off --mysql-ignore-errors=6002,6004,4012,2013,4016 --threads=10 --time=600 prepare
2、先通过视图DBA_OB_TABLE_LOCATIONS找到sbtest1对应的TABLET_ID,而后通过GV$OB_TABLET_COMPACTION_HISTORY查问到在创立100W数据过程中,曾经触发了4次MINI_MERGE和1次MINI_MINOR_MERGE
3、对sbtest1继续的写数据,观测sbtest1表级的转储状况
sysbench /usr/share/sysbench/oltp_insert.lua --mysql-host=172.30.134.1 --mysql-db=sysbench --mysql-port=2881 --mysql-user=root@ob_bench --tables=1 --table_size=1000000 --report-interval=10 --db-driver=mysql --skip-trx=on --db-ps-mode=disable --create-secondary=off --mysql-ignore-errors=6002,6004,4012,2013,4016 --threads=10 --time=600 run
测试总结:
官网对于参数minor_compact_trigger的解释:“minor_compact_trigger 用于管制分层转储触发向下一层下压的阈值。当该层的 Mini SSTable 总数达到设定的阈值时,所有 SSTable 都会被下压到下一层,组成新的 Minor SSTable。” https://www.oceanbase.com/docs/community-observer-cn-10000000...
如上测试时咱们设置的minor_compact_trigger = 2,按了解在每两次触发MINI_MERGE之后,就会触发一次MINOR_MERGE,把L0层的SSTable下压到L1层。 理论测试下来发现未必如此,当达到minor_compact_trigger的阈值后,必然会触发Minor Compaction,但它可能是L0层上的MINI_MINOR_MERGE(同层数据合并),也可能是L0->L1层的MINOR_MERGE(数据下压到下一层)。 然而具体什么状况下,触发哪种Minor Compaction,在官网文档只是介绍会受暗藏参数_minor_compaction_amplification_factor管制,然而具体如何影响的 也并没有给到相应的观测手法。
附:官网对参数 _minor_compaction_amplification_factor的解释:“_minor_compaction_amplification_factor管制 L0 层外部多个Mini SSTable转储的机会,默认为 25。当所有Mini SSTable的总行数达到 Minor SSTable 的写放大系数比例后,才会触发 L1 层转储,否则触发 L0 层转储。当 L1 层不存在Minor SSTable 时,所有Mini SSTable行数到指定阈值(由 minor_compact_trigger 管制)后才会触发 L1 层转储。”
试验二:alter system minor freeze 是否真的在L1层做一个MINOR_MERGE类型的compaction ?
1、同试验一的参数配置,且 minor_compact_trigger = 2
先对sbtest1表记录做一次update,而后手动执行alter system minor freeze;(因为咱们试验观测的是指定表的merge状况,所以在minor freeze之前要做一次update操作,次要是保障memtable中有对该表操作的记录)
如上咱们看到,alter system minor freeze之后只是做了一次MINI_MERGE,并没有到L1层。
咱们再执行一次alter system minor freeze;
这一次咱们发现在做了一次MINI_MERGE之后,触发了MINI_MINOR_MERGE。
咱们能够持续这样做上来,最终咱们发现 alter system minor freeze实际上做的是MINI_MERGE,在MINI_MERGE之后具体是否会触发MINI_MINOR_MERGE 或 MINOR_MERGE,还是会受试验一外面所提到的参数minor_compact_trigger 和 _minor_compaction_amplification_factor的管制。
2、同试验一的参数配置,但设置minor_compact_trigger = 0
同样是屡次执行alter system minor freeze,每次执行后察看merge状况。
能够看到在minor_compact_trigger = 0时,当内存中的memtable dump flush到L0层后,会立即下压到L1层, 这点同官网文档中的解释是统一的。
测试总结:
通过试验二的测试咱们发现,alter system minor freeze真正做的是造成一个mini sstable (MINI_MERGE),在MINI_MERGE之后是否还会触发其余的merge,同样是受参数minor_compact_trigger 和 _minor_compaction_amplification_factor的管制。 并且指令中的minor freeze实际上并不是特地精确,因为看到minor总会让人想到L1层,如果改成mini freeze会更适合一些。
参考资料
https://www.cnblogs.com/buttercup/p/12991585.html
https://www.modb.pro/db/608302
https://www.oceanbase.com/docs/community-developer-advance-00...
https://www.modb.pro/db/610025
https://ask.oceanbase.com/t/topic/31400011