tiflash 不同节点负载不均衡

tidb version: v6.1.1
集群配置及拓扑如下:
image

集群内约4000张表,1.1T 存储空间,2.3万 region:

tikv的store size, leader, region如下:


image

所有表都设置了tiflash副本数为4,共1.8万 region,4个节点完全对称

在该集群上执行压测,20并发回放约450万条SQL
SQL比例约95%为ap, 5%为tp,为生产环境抓取,涉及到差不多一半的表

4个tidb节点,连接均匀分布,cpu负载也较为平衡:

4个tikv节点的负载也较为平衡:

但是tiflash的负载非常的不平衡,打开文件数也同样不平衡,如图:


tiflash_file

我注意到git上有关于此问题的issue,仍然是open状态:
https://github.com/pingcap/tidb/issues/35418

按照issue中的描述,某个tiflash节点挂掉再恢复,tidb的region缓存会导致其上无负载
为此我重启了所有节点的tidb服务(tiup cluster restart xxx -R tidb -y)
重新跑压测,重跑后未发生任何tiflash服务异常
tiflash的负载依然很不平衡,但是各节点的负载比例发生了很大的变化:

接下来我重启了整个集群(tiup cluster restart xxx -y)
重新跑压测,重跑后未发生任何tiflash服务异常
tiflash负载和上一个图类似:

我的问题是:
tidb将mpp任务下发给哪个tiflash节点的原理是啥?为什么会造成这种不平衡?如何解决?

麻烦用这个工具 https://metricstool.pingcap.com/ 导出 tiflash-summary 监控
另外,你的集群有几张表?

好的,我弄一下试试,还没玩过这个

集群有4000多张表,上面帖子里说了

mc-TiFlash-Summary_2022-09-21T09_14_08.949Z.json (915.8 KB)


image
image
确实存在不同 tiflash 节点间请求不均衡的情况

目前 TiDB 在生成 TiFlash MPP 任务的时候,会根据这个表的所有 region 在所有 TiFlash 之间做一个均衡,比如如果这个表有 100 个region,那么 TiDB 会尽量保证每个 TiFlash 读 25 个 region,你们这个场景里面应该有 4 节点 4 副本,所以应该能保证每个 TiFlash 读 25 个 region 的。
但是 TiDB 只会在一个 query 内部做这种均衡,假设你这个表的 region 比较少,比如极端情况下只有一个 region,然后有 100 个并发来读这个表的话,TiDB MPP目前没有在 query 之间做这种均衡,所以这种情况下是有可能出现各个 TiFlash 之间负载不均衡的情况的。考虑到你们集群 4000 多个表只有 2.3w region 的话,是有可能出现后面这种情况的。
你们可以把 TiDB 的 debug log 开开,对于 MPP 的 query 会有类似下面的 log:
Before region balance xxxx
After region balance xxxx

继续请教一下:
假设有4个节点分别叫ABCD,sql是在A节点的tidb服务上执行的
假设这个SQL只涉及到一个表的一个region,这个region有ABCD 4个tiflash副本可用,那么选择哪个副本的逻辑是啥?

如果是用 MPP 或者 BatchCop 访问 TiFlash 的话,是选择了一个 region 的副本之后一直用这个副本,直到这个副本上遇到错误,如果是用 cop 访问 TiFlash 的话,每次查询是会切换到下一个副本的。

这样确实解释了我这个现象了
这个balance的逻辑是最近加的吗?我最早用5.4版本压测好像挺均衡的

我现实的业务场景,就是这个数据分布和SQL分布,tiflash资源就浪费了
该怎么办才能让负载平衡呢?有没有什么参数可以设的

我研究了一下代码,把这个参数从 false 改为了 true
image

因为我发现 GetTiFlashRPCContext 函数内部,如果loadBalance= false 的话,总是返回找到的所有store中的第一个,就造成了热点,改为true的话每次会换一个。

目前编译替换后,跑压测就完全平衡了:

但是不知道原来传入false是什么考虑,改为true了有什么副作用没?是不是就是注释里说的:
// loadBalance is an option. For MPP and batch cop, it is pointless and might cause try the failed store repeatly.
如果仅仅是这样,那在我的业务场景下倒是可以接受,因为store fail的几率还是很小的

请专家指点

这个 5.0 开始就有了,没遇到估计是概率问题

这个是历史原因造成的,目前对 MPP 来说,完全可以改成 true,batchCop 可能还有问题,但是因为 batchCop 基本上可以被 MPP 完全代替,所以改成 true 没什么问题。

如果不放心 batchCop 可以判断 mppStoreLastFailTime 是否为 nil,不为 nil 的话,是 MPP,为 nil 的话是 batchCop,这样可以只对 mpp 开启 region load balance

夜里跑完了全部压测,没有出任何异常情况
所以就简单的改这个参数了
建议咱们tidb可以在新版本增加个参数来控制这个balance
感谢指点!

1赞

是的,我们加了 query 内之间的 load balance 之后忽略了 query 之间的 load balance 了,准备在最新的 tidb 上 fix 一下这个问题。

提了一个相关的 issue:https://github.com/pingcap/tidb/issues/38113

好的,赞