暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OB 内存分配概述

数据库技术闲谈 2021-11-01
779

本文分享 OB 内存分配简单原理,掌握后能够应对一些 OB 写内存报错问题。文末也有视频分享《如何压测OB内存不破防》。

如何管理 OB 内存

有关 OceanBase 相关的内存可以先看这个内存分配图。



下面逐个详细介绍。

进程总内存

OceanBase 进程启动后会从主机那里拿到绝大部分资源(CPU/内存/空间),具体多少就是由集群参数控制的。其中集群节点进程启动需要多少内存是由参数 memory_limit
 和 memory_limit_percentage
 共同控制的。生产环境通常是不设置 memory_limit
 值(默认值为 0),只设置 memory_limit_percentage
 值(默认值 80% )。这样每个节点进程获取的总内存是主机可用内存的 80% 。当主机内存扩容后(比如说是虚拟机),OB 节点能获得的内存也相应增加。如果设置了 memory_limit
 的值,那进程获取的总内存就是它指定的具体的值。这个值最少不能少于 8G 。设置这个参数通常是测试环境跑 OB ,或者想单机启动多个 OB 进程测试用。
这两个参数可以在线调整,但是注意,最大不能超过主机可用内存,最小不能少于 8G 。通常调大是安全的,调小可能有风险。

保留内存

OceanBase 内部租户除了 SYS 租户外,还有一批不可见的内部租户需要一些内存,这部分内存通过参数 system_memory
 大小控制。不同版本的 OB,这个参数默认值不一样。生产环境主机内存有 386G 内存以上的时候,这个参数默认值是 50G 。如果主机内存只有 256G 的时候,这个参数内存可以小一些,如 30G 左右。第 2 课里为了在 10G 内存的机器上跑 OB ,这个参数值是 3~5G 。

这个内存在内部租户 ID 500 的租户下,是给业务租户某些内部操作使用,是有作用的。

SYS 租户内存

SYS 租户是集群初始化的时候自动创建,SYS 租户的资源规格随着可用内存大小、版本变化,会有一些细节差别。SYS 租户的内存大小是由默认资源单元 sys_unit_config
 的规格定义的。
select unit_config_id, name, round(max_memory/1024/1024) max_mem_MB, round(min_memory/1024/1024) min_mem_MB from __all_unit_config where unit_config_id = 1;
+----------------+-----------------+------------+------------+
| unit_config_id | name | max_mem_MB | min_mem_MB |
+----------------+-----------------+------------+------------+
| 1 | sys_unit_config | 1536 | 1024 |
+----------------+-----------------+------------+------------+
1 row in set (0.009 sec)

复制
默认的 sys_unit_config
 的内存规格最小值和最大值不一样,为了更准确的计算集群可用资源,建议把这个内存最小值跟最大值更新为同一个值(只能变大,不要小于默认最大值)。后续创建业务租户的时候,也强烈建议 CPU 和 内存的最小值和最大值保持一致。
alter resource unit sys_unit_config min_memory = '1536M';


复制
如果集群节点规模在 10台以内, SYS 租户资源通常不需要调大。如果集群规模有几十台时,观察一下 SYS 租户的内存和CPU 利用率,如果有出现资源瓶颈,就适当调整 SYS 租户资源规格。最大的时候只需要独占一台机器资源。SYS 租户最多只需要独占 3台机器。

MEMSTORE 内存

每个租户分得的内存,默认有一半用于存放租户的增量数据,也叫 MEMSTOER 。这个内存大小通过参数 memstore_limit_percentage
控制。默认值是 50%
 。当写多读少的时候,可以将这个参数值调高,比如说在大批量导数据的时候,没有读的时候,可以临时调整到 80%
。当然这个这个参数也不是任意可以调整。租户的内存除去增量数据占用的内存外,其他的放静态的数据(KVCache
)、SQL执行计划缓存等(PLAN CACHE
)、SQL运算的临时内存等(SQLAREA
)。如果这些内存资源过少,可能有时候会有报错,或者性能很慢的现象出现。目前 OB 对内存的管理还是手动分配为主,将来或许可以做到动态管理。
OceanBase 的读写模型是 LSM-Tree,写操作也是追加模式。数据表是以有序表格,又叫 SSTABLE
,全称 SORTED STRING TABLE
 。写不是在原来的数据块上修改,而是新开辟内存记录变化的增量。原有的数据保存在 KVCache
 不变,称之为基线数据。绝大部分业务一天的数据变化量相当于数据总量来说比重很小,OceanBase 的这种增量写是很节省内存的。所以,通常说 OceanBase 的增量数据都是在内存里不落盘的。严格来说并不对,是延迟落盘。

如何对OB 集群进行合并

OceanBase 会每天定时将这部分增量数据跟基线数据在内存中合并成新的数据块然后以追加方式写回到磁盘数据文件中。这个合并操作叫 major freeze
,合并的时间调度是通过参数 major_freeze_duty_time
 设定,默认值是 02:00
 。每天调度一次。合并操作也可以手动发起。合并的时候会消耗一定资源,对影响有一些影响。不过合并的并发也是可以通过参数 merge_thread_count
 控制的,并且参数 merger_warm_up_duration_time
 调整合并线程启动时间。调整这两个参数可以在合并的速度和稳定性之间取一个最佳平衡。
当租户内存不是很大,或者业务写量非常大的时候,这个租户的增量内存可能会写满,然后业务就写不进去,报错 NO MEMORY
 。这是 OceanBase 运维要极力避免的。
命令:alter system major freeze; 
SELECT ZONE,svr_ip,major_version,ss_store_count,merged_ss_store_count,modified_ss_store_count,merge_start_time,merge_finish_time,merge_process
FROM __all_virtual_partition_sstable_image_info
order by major_version desc ;

复制
最终合并结果确认是查看 合并状态。
select * from __all_zone where name in ('merge_status','all_merged_version','broadcast_version');


复制
正常情况都是 'IDLE',且合并版本和广播版本保持一致。

如何对OB 集群进行限速和转储

首先,OceanBase 针对租户可以有一个增量内存写限速的设计,触发限速有两个维度,一是增量内存利用率到达参数 writing_throttling_trigger_percentage
 设置,二是预估剩余增量内存持续可用时间小于或等于参数 writing_throttling_maximum_duration
 定义。默认 writing_throttling_trigger_percentage
 参数的值是 100%
,就是不限速。实际业务建议都改为 最大 90%
 。这个限速设计并不是特别精准,所以如果写入量非常大的话的,这个参数还要适当再调低。当业务写被限速的时候,业务表现为普通的 DML SQL 性能会变慢(延时变大),等待事件是 mem allocation
 等。限速很影响性能,所以也是要极力避免的。这就要靠下一个机制。
第二,OceanBase 除了 major freeze
 操作可以释放内存外,还有 minor freeze
 操作也可以释放内存,这个通常也叫转储。转储相比合并,对资源的占用更少,对性能的影响也很小。转储是直接将内存中的增量数据以 SSTABLE 格式直接写到磁盘数据文件中,从而释放增量内存。
转储的触发有两个机制。一是手动触发,命令是 
alter system minor freeze ; 
。命令立即返回,命令发生时内存中的增量块会被冻结禁止写入,新的写入会生成新的增量内存块去接受写入。二是自动触发,当增量内存部分的利用率达到参数 freeze_trigger_percentage
 指定的值(默认是 70
,表示 70%
),自动触发 minor freeze
 操作。转储可以有很多轮,当转储的次数达到参数 minor_freeze_times
 指定的值,会自动触发合并(major freeze
)操作。
转储也是可以调优的,通过调整转储的并发参数(
minor_merge_concurrency
),也可以在转储的速度和稳定性之间取得一个平衡。
实际经验表明,当租户内存规模在 50G 以上时,通过调整转储参数,绝大部分时候是可以避免增量内存写入限速或内存不足的错误。如果业务增量写非常大的时候,那说明租户内存有瓶颈了,那就是要对内存资源扩容的信号。
注意:如果是临时大批量导入数据,可以临时对租户内存进行扩容。等导入完毕后,一轮合并结束后,就可以最租户内存进行缩容。在线扩容和缩容,也是 OceanBase 最核心和实用的能力。
参数调整示例:
show parameters like '%memory%';
alter system set memory_limit_percentage = 90; -- OB占系统总内存的比例,提高OB可用的内存量。
alter system set memstore_limit_percentage = 70; -- memstore占租户的内存比,尽量增大memstore的空间(也不是无限制大,会挤压其他模块内存影响使用)。
alter system set freeze_trigger_percentage = 40; -- 启动major/minor freeze的时机,让转储(minor freeze)尽早启动,memstore内存尽早释放。
alter system set minor_freeze_times = 50; -- minor freeze的次数,尽量不在测试期间触发major freeze。为 0 表示不开启转储。
alter system set minor_warm_up_duration_time = 0; -- 加快minor freeze
alter system set merge_thread_count = 8; -- 增大合并的线程数。
alter system set minor_merge_concurrency = 8; -- 增大转储的线程数,期望提高转储的速度。
alter system set _mini_merge_concurrency = 4; -- 增大mini_merge的线程数,期望提高mini_merge的速度(默认值为3)。

复制

详细分析和解决方法,请参考下面视频《如何压测 OB 内存不破防》。


更多讨论

文章转载自数据库技术闲谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论