本文分享 OB 内存分配简单原理,掌握后能够应对一些 OB 写内存报错问题。文末也有视频分享《如何压测OB内存不破防》。
如何管理 OB 内存
进程总内存
memory_limit
和
memory_limit_percentage
共同控制的。生产环境通常是不设置
memory_limit
值(默认值为 0),只设置
memory_limit_percentage
值(默认值 80% )。这样每个节点进程获取的总内存是主机可用内存的 80% 。当主机内存扩容后(比如说是虚拟机),OB 节点能获得的内存也相应增加。如果设置了
memory_limit
的值,那进程获取的总内存就是它指定的具体的值。这个值最少不能少于 8G 。设置这个参数通常是测试环境跑 OB ,或者想单机启动多个 OB 进程测试用。
保留内存
OceanBase 内部租户除了 SYS 租户外,还有一批不可见的内部租户需要一些内存,这部分内存通过参数 system_memory
大小控制。不同版本的 OB,这个参数默认值不一样。生产环境主机内存有 386G 内存以上的时候,这个参数默认值是 50G 。如果主机内存只有 256G 的时候,这个参数内存可以小一些,如 30G 左右。第 2 课里为了在 10G 内存的机器上跑 OB ,这个参数值是 3~5G 。
这个内存在内部租户 ID 500 的租户下,是给业务租户某些内部操作使用,是有作用的。
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';
复制
MEMSTORE 内存
memstore_limit_percentage
控制。默认值是
50%
。当写多读少的时候,可以将这个参数值调高,比如说在大批量导数据的时候,没有读的时候,可以临时调整到
80%
。当然这个这个参数也不是任意可以调整。租户的内存除去增量数据占用的内存外,其他的放静态的数据(
KVCache
)、SQL执行计划缓存等(
PLAN CACHE
)、SQL运算的临时内存等(
SQLAREA
)。如果这些内存资源过少,可能有时候会有报错,或者性能很慢的现象出现。目前 OB 对内存的管理还是手动分配为主,将来或许可以做到动态管理。
SSTABLE
,全称
SORTED STRING TABLE
。写不是在原来的数据块上修改,而是新开辟内存记录变化的增量。原有的数据保存在
KVCache
不变,称之为基线数据。绝大部分业务一天的数据变化量相当于数据总量来说比重很小,OceanBase 的这种增量写是很节省内存的。所以,通常说 OceanBase 的增量数据都是在内存里不落盘的。严格来说并不对,是延迟落盘。
如何对OB 集群进行合并
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');
复制
如何对OB 集群进行限速和转储
writing_throttling_trigger_percentage
设置,二是预估剩余增量内存持续可用时间小于或等于参数
writing_throttling_maximum_duration
定义。默认
writing_throttling_trigger_percentage
参数的值是
100%
,就是不限速。实际业务建议都改为 最大
90%
。这个限速设计并不是特别精准,所以如果写入量非常大的话的,这个参数还要适当再调低。当业务写被限速的时候,业务表现为普通的 DML SQL 性能会变慢(延时变大),等待事件是
mem allocation
等。限速很影响性能,所以也是要极力避免的。这就要靠下一个机制。
major freeze
操作可以释放内存外,还有
minor freeze
操作也可以释放内存,这个通常也叫转储。转储相比合并,对资源的占用更少,对性能的影响也很小。转储是直接将内存中的增量数据以 SSTABLE 格式直接写到磁盘数据文件中,从而释放增量内存。
转储的触发有两个机制。一是手动触发,命令是
alter system minor freeze ;
。命令立即返回,命令发生时内存中的增量块会被冻结禁止写入,新的写入会生成新的增量内存块去接受写入。二是自动触发,当增量内存部分的利用率达到参数
freeze_trigger_percentage
指定的值(默认是
70
,表示
70%
),自动触发
minor freeze
操作。转储可以有很多轮,当转储的次数达到参数
minor_freeze_times
指定的值,会自动触发合并(
major freeze
)操作。
转储也是可以调优的,通过调整转储的并发参数(
minor_merge_concurrency
),也可以在转储的速度和稳定性之间取得一个平衡。
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 社区版官网问答区 https://open.oceanbase.com/answer
钉钉群(群号:33254054 )
文章转载自数据库技术闲谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。