OceanBase存储引擎高级技术——内存数据落盘策略-合并和转储

简介: OceanBase存储引擎高级技术——内存数据落盘策略-合并和转储

LSM Tree技术简介

LSM Tree(The Log-Structured Merge-Tree)核心特点是利用顺序写来提高写性能

将某个对象(Partition)中的数据按照“key-value” 形式在磁盘上有序存储(SSTable)

数据更新先记录在MemStore中的MemTable里,然后 再合并(Merge)到底层的SSTable里

SSTable和MemTable之间可以有多级中间数据,同样以 key-value形式保存在磁盘上

memtable内存结构

OceanBase MemTable采用双索引结构(B+树索引以及哈希索引)

特点:

B+树索引能够更好地支持范围查找

哈希索引是针对单行查找的一种优化

每次事务执行时,MemTable会自动维护 B+树索引与哈希索引之间的一致性

Undo流程:

如果要读取更老的历史快照,只需要顺着内存中的反向指针往前回溯即可,相当于在内存中执行数据库Undo操作

OceanBase中最简单的LSM Tree只有C0层(MemTable)和C1层(SSTable)。两层数据的合并过程如下:


将所有observer上的MemTable数据做大版本冻结(Major Freeze),其余内存作为新的MemTable继续使用

将冻结后的MemTable数据合并(Merge)到SSTable中,形成新的SSTable,并覆盖旧的SSTable

合并完成后,冻结的MemTable内存才可以被清空并重新使用。


合并的细化

合并按照合并的宏块不同,分为全量合并,增量合并,渐进合并三种:

全量合并:合并时间长,耗费IO和CPU,把所有的静态数据都读取出来,和动态数据归并,再写到磁盘中。

增量合并:只会读取被修改过的宏块数据,和动态数据归并,并写入磁盘,对于未修改过的宏块,则直接重用

渐近合并:每次全量合并一部分,若干轮次后整体数据被重写一遍。

思考:合并存在的问题有集群性,高消耗,时间长

避免这些问题办法就是转储

分层转储:

为了优化转储越来越慢的问题,引入了“分层转储”机制:

多层compaction策略:新增L0层:被冻结MemTable会直接flush为Mini SSTable。

架构变化:3层VS4层

3层架构:memtable + minor sstable(L1) + major sstable (L2)

4层架构:memtable + mini sstable(L0) + minor sstable(L1) + major sstable (L2)

参数 minor_compact_trigger 控制L0层Mini SSTable 总数

参数 major_compact_trigger 控制memtable dump flush次数达到时触发major  

转储相关参数

minor_freeze_times


控制两次合并之间的转储次数,达到此次数则自动触发合并(Major Freeze)


设置为 0表示关闭转储,即每次租户MemStore使用率达到冻结阈值(freeze_trigger_percentage)都直接触发集群合并。


minor_merge_concurrency


并发做转储的分区个数;单个分区暂时不支持拆分转储,分区表可加快速度


并发转储的分区过少,会影响转储的性能和效果(比如MemStore内存释放不够快)


并发转储的分区过多,同样会消耗过多资源,影响在线交易的性能

转储适用的场景

转储功能比较适用于以下场景

批处理、大量数据导入等场景,写MemStore的速度很快,需要MemStore内存尽快释放

业务峰值交易量大,写入MemStore的数据很多,但又不想在峰值时段触发合并(Major Freeze),希望能将合并延后

转储场景的常用配置方法


减小freeze_trigger_percentage的值(比如40),使MemStore尽早释放,进一步降低MemStore写满的概率

增大minor_freeze_times的值,尽量避免峰值交易时段触发合并(Major Freeze),将合并的时机延后到交易低谷时段的每日合并(major_freeze_duty_time)

转储对数据库的影响

转储的优势

每个租户的转储不影响observer上其它的租户,也不会触发集群级转储,避免关联影响。

资源消耗小,对在线业务性能影响较低

耗时相对较短,MemStore更快释放,降低发生MemStore写满的概率

转储的副作用

数据层级增多,查询链路变长,查询性能下降

冗余数据增多,占用更多磁盘空间

手动触发转储

ALTER SYSTEM MINOR FREEZE [{TENANT[=](‘tt1'[, 'tt2'...])|PARTITION_ID [=]'partid

可选的控制参数

tenant:指定要执行minor freeze的租户

partition_id:指定要执行minor freeze的partition

server:指定要执行minor freeze的observer

当什么选项都不指定时,默认对所有observer上的所有租户执行转储

手动触发的转储次数不受参数minor_freeze_times的限制,即手动触发的转储次数即使超过设置的次数,也不会触发合并(Major Freeze)

查看转储记录

MemStore使用率达到freeze_trigger_percentage而 触发的租户级转储,在__all_server_event_history表中查询:


手动转储,在__all_rootservice_event_history表中 可以查到具体的选项

OB合并触发方式-定时合并

由major_freeze_duty_time参数控制定时合并时间,可以修改参数控制合并时间: alter system set major_freeze_duty_time='02:00';

OB合并触发方式-MemStore使用率达到阈值自动合并

当租户的 MemStore内存使用率达到freeze_trigger_percentage参数的值, 并且转储的次数已经达到了 minor_freeze_times参数的值,会自动触发合并。


通过查询(g)v$memstore视图来查看各租户的memstore内存使用情况


查转储次数:gv$memstore, __all_virtual_tenant_memstore_info 中 freeze_cnt 列


OB合并触发方式-手动合并

可以在"root@sys"用户下,通过以下命令发起手动合并(忽略当前MemStore的使用率):

alter system major freeze;


合并发起以后,可以在"oceanbase"数据库里用以下命令查看合并状态:

select * from __all_zone;或者select * from __all_zone where name = 'merge_status';

查看 OB 集群合并和冻结状态 __all_zone

image.pngimage.png

轮转合并

借助自身天然具备的多副本分布式架构,OceanBase引入了轮转合并机制    


一般情况下,OceanBase会有3份(或更多)数据副本;可以轮流为每份副本单独做合并


当一个副本在合并时,这个副本上的业务流量可以暂时切到其它没有合并的副本上


某个副本合并完成后,将流量切回这个副本,然后以类似的方式为下一个副本做合并,直至所有副本完成合并

关于轮转合并的更多说明

通过参数enable_merge_by_turn开启或者关闭轮转合并


以ZONE为单位轮转合并,只有一个ZONE合并完成后才开始下一个ZONE的合并;合并整体时间变长


某一个ZONE的合并开始之前,会将这个ZONE上的Leader服务切换到其它ZONE;切换动作对长事务有影响


由于正在合并的ZONE上没有Leader,避免了合并对在线服务带来的性能影响

OceanBase每日合并策略

可通过以下几项控制每日合并的策略:

enable_manual_merge: OB的配置项,指示是否开启手动合并

enable_merge_by_turn: OB的配置项,指示是否开启自动轮转合并

zone_merge_order: 指定自动轮转合并的合并顺序




设置轮转合并顺序

合并开始前,通过参数zone_merge_order设置合并顺序;只对轮转合并有效。


假设集群中有三个zone,分别是z1,z2,z3,想设置轮转合并的顺序为"z1 -> z2 -> z3",步骤如下:

alter system set enable_manual_merge = false; -- 关闭手动合并
alter system set enable_merge_by_turn = true;--开启轮转合并
alter system set zone_merge_order = 'z1,z2,z3'; --设置合并顺序

取消自定义的合并顺序

alter system set zone_merge_order = ''; --取消自定义合并顺序

OB轮转合并示例

假设集群中的设置是zone_merge_order = 'z1,z2,z3,z4,z5',zone_merge_concurrency = 3,一次轮转合并的大概过程如下:

事件 调度 并发合并的ZONE 合并完成的ZONE

1.开始合并 z1,z2,z3发起合并 z1,z2,z3

2.一段时间后,z2完成合并 z4发起合并 z1,z3,z4 z2

3.一段时间后,z3完成合并 z5发起合并 z1,z4,z5 z2,z3

4.一段时间后,全部ZONE完成合并   z1,z2,z3,z4,z5

合并策略总结对比

合并策略

调度策略

如何开启

使用场景

注释

手动合并

用户通过sql命令指定zone 开始合并,需要用户自己 控制并发度

1.开启手动合并alter system set enable_manual_merge = true; 2.用户自主决定合并顺序和并发度,通过 SQL命令调度zone合并,比如调度z1开始 合并:alter system start merge zone = 'z1';

纯手工操作,一般在业务每日合并出 现问题、需要人工介入的情况下使用

一旦开启,每一次合 并都需要用户主动调 度,除非关掉手动合 并,开启自动合并

自动非轮转合并

所有zone一起开始合并, 没有并发度控制

1.关闭手动合并alter system set enable_manual_merge = false; 2.关闭轮转合并alter system set enable_merge_by_turn = false;

当业务量比较小的情况下,合并中的 zone也能支持业务流量时,则可以开 启自动非轮转合并,这样做能够避免 用户跨表join请求变成分布式跨机查询

每日合并会对业务请 求产生一定的性能影 响,需要业务进行确认

自动指定顺序的轮转合并

用户直接指定轮转的顺序, RS只负责并发度控制

各个版本实现有不同,具体看相关版本介绍

一种特殊的轮转合并策略,一般不会 使用,只有当智能轮转合并不满足业务需求的情况下,才需要为集群定制特殊的合并调度策略

在zone成员发生变更 的情况下,自动指定顺序的轮转合并会失 效,退化成智能轮转合并

智能轮转合并

RS根据一定策略依次调度 zone合并,并进行并发度控 制

1.关闭手动合并alter system set enable_manual_merge = false; 2.开启轮转合并alter system set enable_merge_by_turn = true

线上部署最常用的合并调度方案,轮转合并的过程中,RS会保证尽量不影 响业务的请求,通过切leader的方式, 将用户读写路由到不在合并的zone中;


合并注意事项

合并超时时间

由参数zone_merge_timeout定义超时阈值;默认值为'3h'(3个小时)

如果某个ZONE的合并执行超过阈值,合并状态被设置为TIMEOUT

空间警告水位

参数data_disk_usage_limit_percentage定义数据文件最大可以写入的百分比(超出阈值后禁止数据迁入),默认值90。


当数据盘空间使用量超过阈值后,合并任务打印ERROR警告日志,合并任务失败;需要尽快扩大数据盘物理空间,并调大data_disk_usage_limit_percentage参数的值


当数据盘空间使用量超过阈值后,禁止数据迁入


参数datafile_disk_percentage定义数据盘空间使用阈值(占用data_dir所在磁盘总空间百分比),默认值90


参数datafile_size用于设置数据文件的大小,该配置项与 datafile_disk_percentage 同时配置时,以该配置项设置的值为准,默认值为0



合并控制

合并线程数,由参数merge_thread_count控制


控制可以同时执行合并的分区个数;单分区暂不支持拆分合并,分区表可以加快合并速度。


控制可以同时执行合并的分区个数;单分区暂不支持拆分合并,分区表可以加快合并速度。


默认值为0:表示自适应,实际取值为min(10,cpu_cnt * 0.3)。


最大取值不要超过48:值太大会占用太多CPU和IO资源,对observer的性能影响较大;而且容易触发系统报警,比如CPU使用率超过90%可能会触发主机报警。


如对合并速度没有特殊要求,建议使用默认值0。

合并版本

设置SSTable中保留的数据合并版本个数


由参数max_kept_major_version_number控制,默认值为2。


调大参数值可以保留更多历史数据,但同时占用更多的存储空间。


在hint中利用frozen_version(<major_version>)指定历史版本。



转储&合并对比

合并(Major freeze)


转储(Minor freeze)


集群级行为,产生一个全局快照,所有observer上所有租户的MemStore统一冻结。


以“租户+observer”为维度,只是MemTable的物化,每个MemStore独立触发冻结;也可以通过手工命令,为特定的分区单独执行。


MemTable数据和转储数据全部合并到SSTable中,完成后数据只剩一层,产生新的全量数据。


转储只与相同大版本的Minor SSTable合并,产生新的Minor SSTable,所以只包含增量数据,最终被删除的行需要特殊标记,不涉及SSTable数据,完成后有转储和SSTable两层数据 。


更新的数据量大(全部租户、全部observer、含SSTable), 消耗较多的CPU和IO资源,MemStore内存释放较慢。


更新的数据量小(单独租户、单独observer、不含SSTable) ,消耗的资源更少,可加快MemStore内存的释放。


触发条件:单个租户的MemStore使用率达到 freeze_trigger_precentage,并且转储已经达到指定次数;手工触发;定时触发。


触发条件:单个租户的MemStore使用率达到 freeze_trigger_precentage;手工触发。

1.OB的LSMTree可以分为C0层(MemTable)、C1层(Minor SSTable)、C2层(Major SSTable)


2.OB内存通过双索引结构和数据压缩,提高数据的查询性能


3.合并和转储之前,都需要做一次冻结,然后根据参数设置决定冻结之后是转储还是合并


4.合并可以细分为全量合并、渐进合并、增量合并三种方式,同一个数据库,这三种方式对资源的消耗程度递减


5.为了优化转储越来越慢的问题,引入了“分层转储”机制,为了提高转储速度,加快内存释放速度,被冻结的MemTable 会直接 flush 为 Mini SSTable


6.轮转合并可以轮流为每份副本单独做合并,减少业务影响,但同时也存在合并时间变长、切主过程中影响长连接等问题


7.合并和转储特点的比较,两者互补共同组成了OB数据完整的落盘策略


相关文章
|
4月前
|
存储 机器学习/深度学习 PyTorch
119_LLM训练的高效内存管理与优化技术:从ZeRO到Flash Attention
大型语言模型(LLM)的训练面临着前所未有的计算和内存挑战。随着模型规模达到数百亿甚至数千亿参数,高效的内存管理成为训练成功的关键因素之一。2025年,LLM训练的内存优化技术已经取得了显著进展,从ZeRO优化器到Flash Attention等创新技术,为训练超大规模模型提供了可能。
|
5月前
|
存储 缓存 NoSQL
工作 10 年!Redis 内存淘汰策略 LRU 和传统 LRU 差异,还傻傻分不清
小富带你深入解析Redis内存淘汰机制:LRU与LFU算法原理、实现方式及核心区别。揭秘Redis为何采用“近似LRU”,LFU如何解决频率老化问题,并结合实际场景教你如何选择合适策略,提升缓存命中率。
631 3
|
11月前
|
存储 分布式计算 监控
阿里云服务器实例经济型e、通用算力型u1、计算型c8i、通用型g8i、内存型r8i详解与选择策略
在阿里云现在的活动中,可选的云服务器实例规格主要有经济型e、通用算力型u1、计算型c8i、通用型g8i、内存型r8i实例,虽然阿里云在活动中提供了多种不同规格的云服务器实例,以满足不同用户和应用场景的需求。但是有的用户并不清楚他们的性能如何,应该如何选择。本文将详细介绍阿里云服务器中的经济型e、通用算力型u1、计算型c8i、通用型g8i、内存型r8i实例的性能、适用场景及选择参考,帮助用户根据自身需求做出更加精准的选择。
|
7月前
|
存储 人工智能 自然语言处理
AI代理内存消耗过大?9种优化策略对比分析
在AI代理系统中,多代理协作虽能提升整体准确性,但真正决定性能的关键因素之一是**内存管理**。随着对话深度和长度的增加,内存消耗呈指数级增长,主要源于历史上下文、工具调用记录、数据库查询结果等组件的持续积累。本文深入探讨了从基础到高级的九种内存优化技术,涵盖顺序存储、滑动窗口、摘要型内存、基于检索的系统、内存增强变换器、分层优化、图形化记忆网络、压缩整合策略以及类操作系统内存管理。通过统一框架下的代码实现与性能评估,分析了每种技术的适用场景与局限性,为构建高效、可扩展的AI代理系统提供了系统性的优化路径和技术参考。
437 4
AI代理内存消耗过大?9种优化策略对比分析
|
6月前
|
机器学习/深度学习 监控 安全
解密虚拟化弹性内存:五大核心技术与实施策略
本文深入解析虚拟化环境中实现内存弹性管理的五大核心技术与实施策略。内容涵盖内存架构演进、关键技术原理、性能优化方法及典型问题解决方案,助力提升虚拟机密度与资源利用率。
284 0
|
6月前
|
边缘计算 算法 Java
Java 绿色计算与性能优化:从内存管理到能耗降低的全方位优化策略与实践技巧
本文探讨了Java绿色计算与性能优化的技术方案和应用实例。文章从JVM调优(包括垃圾回收器选择、内存管理和并发优化)、代码优化(数据结构选择、对象创建和I/O操作优化)等方面提出优化策略,并结合电商平台、社交平台和智能工厂的实际案例,展示了通过Java新特性提升性能、降低能耗的显著效果。最终指出,综合运用这些优化方法不仅能提高系统性能,还能实现绿色计算目标,为企业节省成本并符合环保要求。
241 0
|
弹性计算 安全 数据库
【转】云服务器虚拟化内存优化指南:提升性能的7个关键策略
作为云计算服务核心组件,虚拟化内存管理直接影响业务系统性能表现。本文详解了内存优化方案与技术实践,助您降低30%资源浪费。
252 0
【转】云服务器虚拟化内存优化指南:提升性能的7个关键策略
|
存储 算法 Java
Java内存管理深度剖析与优化策略####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,重点分析了堆内存的分配策略、垃圾回收算法以及如何通过调优提升应用性能。通过案例驱动的方式,揭示了常见内存泄漏的根源与解决策略,旨在为开发者提供实用的内存管理技巧,确保应用程序既高效又稳定地运行。 ####
|
11月前
|
机器学习/深度学习 存储 PyTorch
PyTorch内存优化的10种策略总结:在有限资源环境下高效训练模型
在大规模深度学习模型训练中,GPU内存容量常成为瓶颈,特别是在训练大型语言模型和视觉Transformer时。本文系统介绍了多种内存优化策略,包括混合精度训练、低精度训练(如BF16)、梯度检查点、梯度累积、张量分片与分布式训练、
507 14
PyTorch内存优化的10种策略总结:在有限资源环境下高效训练模型
|
11月前
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略