经过OB的自动分区负载均衡后,负载更不均衡了~

【 使用环境 】测试环境 OceanBase_CE_V4.2.1.7

一开始,OceanBase 默认的自动负载均衡,对于 不同表的负载 以及 多表之间的关联 并不了解,所以 数据表分区 的负载不太均衡,甚至触发负载告警。

于是,我创建了3个表组,按照 业务关联程度 以及 业务负载,将 部分业务表 分为了3组。
而且,这 3个表组 的 数据表 的主副本 各分布在一个单独的 Zone上。比如 表组1 的 主副本 都位于 Zone1,表组2 位于 Zone2,表组3 位于 Zone3。

观察了几天,发现 3个Zone 的 CPU负载相对均衡了不少。

但是,今天又发现,OceanBase 自动负载均衡,又把这3个表组的 主副本 全部都自动迁移到了 同一个 Zone。

导致这个 Zone 的 CPU负载 比其他 2个 Zone的负载高了3倍以上,并触发了 load 负载超限的告警( 负载主要来自于 查询 )。

不知道 OceanBase 的 自动负载均衡 是怎么一个算法,为什么自动负载均衡后,负载反而更不均匀了呢

我只能自己通过 enable_transfer = false 禁用 OB 的自动迁移来解决这个问题么 ?
关闭该配置之后,如果某个 Zone 发生故障,该 Zone 中数据表的主副本,OB 还会进行自动故障转移,以保证服务可用么 ?

您的zone优先级是随机的么
分区均衡策略的优先级顺序如下:分区属性对齐(table group对齐) > 分区数量均衡 > 分区磁盘均衡
主副本所在节点损坏主副本会自动切换。

Primary Zone 优先级是默认的 RANDOM。
我 3 个 Table Group 的 SHARDING 属性 都是 None。

但是感觉这个 分区数量均衡 的策略 似乎也不够均衡。
因为我的 表组3 里面有一个 大的分区表,有 2000 个分区;表组2 有个分区表,有 1024 个分区。

现在 它们 ( 3个表组里的所有表 ) 都被放到 Zone 1 了,所有分区表都在这里面。

这就导致 Zone 1 的负载很高,另外两个 Zone 2 的 负载很低。

在大多数业务上,感觉按照 分区数量 和 磁盘 去均衡,似乎不是一个好的主意。

先说磁盘,如果3个Zone都是全功能副本,那么三者占用的磁盘空间几乎是相差无几的,除非 单个 Zone 里面 存在 多个机器节点。

再说 分区数量,以电商为例,有些业务表 如 用户、商品、订单、支付, 这些核心业务表,读写 都是非常频繁的,数据量也会很大,会占用大部分的 CPU 使用。

而其他一些数据表,比如 费率配置、意见反馈、后台员工、后台角色,这些表不仅数据量少,并且读写频率很低。

没有分区的两个表,在分区数量上可能都是1,但是 数据量、读写频率 却可能天壤之别。

我觉得,如果按照 每个表(或分区) 的 查询次数、CPU 占比、数据量、磁盘IO 来综合评估 负载均衡【或者允许 开发人员 给每个表设置 权重值,先表组对齐,再加权负载均衡】,可能更符合实际业务场景。

如果一个 Zone 有多台机器节点,再按照 每个表的负载、磁盘占用率 进一步加权负载均衡,会更合理。

1 个赞

select table_name,partition_name,subpartition_name,ls_id,zone from oceanbase.DBA_OB_TABLE_LOCATIONS where table_name in(’’) and role=‘LEADER’;
查看下是否leader都在ZONE1上。

你说的均衡方式确实有一定道理,这边联系下相关同学看一下。

目前权重分区均衡已经在做了,预期将在425bp1上线

是的,我就是这样查询确认过的

SELECT zone, table_name  
FROM
  oceanbase.DBA_OB_TABLE_LOCATIONS 
WHERE
  database_name = 'db_name' 
  AND role = 'LEADER'
  AND zone = 'zone1'
  AND table_type='USER TABLE'
  GROUP BY zone, table_name
  ORDER BY zone

我前几天创建3个表组后,当时查看 3个表组的 表 都是在不同的 Zone,负载表现也比较均衡正常。
今天 Zone 1 资源占用超过其他两个 Zone 3倍以上,触发了负载告警,我再去看的时候,这3个表组的数据表主副本 就全部在 Zone 1 了。

好的,非常期待,万分感谢您的热心回复。

请问,我现在是需要手动将 enable_transfer 设为 false 吗 ?这个应该不影响 节点故障 时的 自动转移吧 ?

感觉你的集群并不是仅有三个表组。
系统租户查看下这条sql是否仅有三个表组
SELECT * FROM oceanbase.CDB_OB_TABLEGROUPS;

我们这个 OB 里面有 2 个数据库,相当于两个不同的环境:一个 db_dev,一个 db_test

db_test 这个表用了 生产环境 的数据来做 模拟测试,所以数据量较大,读写也比较多。
db_dev 虽然是一样的 表,但都是开发自用,数据量 和 读写 都可以忽略不计。

对了,还有两个 XXL JOB 的数据库:一个 xxl_job_dev,一个 xxl_job_test

db_test 里面有3个表组,就是我前面反馈的这3个。
db_dev 里面也有3个表组,只不过表组名称分别加了后缀 _dev

我们在添加表组的时候,发现 表组 似乎是 独立于 数据库之外的,但是在某些场景下,添加多个数据库的数据表到同一个表组会报错,所以我们就按照环境分开了,各管各的。

截图看一下目前每个zone的表组分布呢

表组主副本分布.csv.zip (493 字节)

【表组之外的数据表没有包含在内哦】

截图貌似不好弄,我导出成 csv 格式了。由于上传不支持该格式,我只好压缩为 .zip 格式。

你的查询sql是什么样的,这里面的表都是leader么

是的,都是 LEADER 的。

-- 按 zone 分组所有表的 LEADER 分布
SELECT zone, database_name, table_name, tablegroup_name
FROM
  oceanbase.DBA_OB_TABLE_LOCATIONS	
WHERE
  database_name IN ( 'db_dev', 'db_test' )
  AND role = 'LEADER'
  AND table_type='USER TABLE'
	AND tablegroup_name IS NOT NULL
  GROUP BY database_name, zone, table_name
  ORDER BY database_name, zone, tablegroup_name

我刚刚和同事确认了一下,这次负载均衡可能和他操作了 db_dev 的某个表有关:

  1. 他把 tab_1 这个分区表(大概有2000个分区,位于表组 g1_dev 中)备份重命名为了 tab_1_old
  2. 然后他新建了一个同名的分区表 tab_1,也有 2000个分区左右,但没有加入任何表组
  3. 这就相当于在 表组 之外多了2000多个表分区,虽然里面没几条数据,但OB 检测到分区数量变动,所以触发了自动负载均衡。

不过,按照 表分区的数量 进行负载均衡,仍然不是一个好的 IDEA。
期待 按照权重进行加权负载均衡 的新功能 能够尽快上线。

看着不太对劲,g3_dev表组呢
查看下zone分布及优先级
SELECT * FROM oceanbase.DBA_OB_ZONES;
查看下表组个数
SELECT * FROM oceanbase.CDB_OB_TABLEGROUPS;
查看下leader分布
select count(table_name), TABLEGROUP_NAME ,zone from DBA_OB_TABLE_LOCATIONS where database_name IN ( ‘db_dev’, ‘db_test’ )
AND role = ‘LEADER’
AND table_type=‘USER TABLE’
group by TABLEGROUP_NAME,zone
order by 1;

db_dev 没有 g3_dev

db_test.g3 这个表组在业务上也是不需要的,只是我们之前发现创建了2个表组后,Zone 2 的负载有点偏高,所以把一些 表组2 之外的业务表,通过加入新建表组的形式,让 OB 将其 主副本 转移到了 Zone 1,这样每个Zone的负载能够均衡点。

然后,由于我们同事昨天进行了 上述数据表 操作,所以 OB 就触发了自动负载均衡,也就带来了现在的问题。

image

image

我已经让同事,将昨天操作的 tab_1_old 表删除掉,然后将新建的 tab_1 加入 之前的表组

enable_transfer 设为 false 不会影响节点故障后的leader自动转移。