最近有金融客户使用 TiDB 适配批处理场景,数据量在数亿级。对于相同的数据量的处理耗时,TiDB 有 35 分钟,Oracle 有 15 分钟,足足相差 20 分钟。从之前的经验来看,在批处理场景上 TiDB 的性能是要好过 Oracle 的,这让我们感到困惑。经过一番排查最终定位是批处理程序问题。调整后,在应用服务器有性能瓶颈、数据库压力依然不高且没有进行参数优化的情况下,TiDB 处理时间缩短到 16 分钟,与 Oracle 几乎持平。
远程排查
通过 Grafana 发现执行批处理时数据库集群的资源使用率非常低,判断应用发来的压力较小,将并发数从 40 提高到 100,资源使用率和 QPS 指标几乎没有变化。通过 connection count 监控看到,连接数随着并发数增加而增加,确认并发数修改是生效的。执行 show processlist 发现大部分连接是空闲状态。简单走查了下应用程序代码,是 Spring batch + MyBatis 结构。因为 Spring batch 设置并发的方式很简单,所以考虑线程数的调整应该是生效且可以正常工作的。
虽然还没有搞清资源使用率低的问题,但还是有其他收获,ping 应用和 TiDB 集群的网络延迟,达到了 2~3 ms。为了排除高网络延迟的干扰,将应用部署到 TiDB 集群内部运行,批处理耗时从 35 分钟下降到 27 分钟,但依然和 Oracle 有较大差距。因为数据库本身没有压力,所以调整数据库参数也没什么意义。
因为应用提高并发的效果不符合预期,所以考虑线程可能造成了阻塞,但也没有证据,于是想了这样的场景来简单验证到底是应用的问题还是数据库的问题:
在 TiDB 集群中创建两个完全相同的 Database,d1 和 d2,使用两个完全相同的批处理应用分别对 d1,d2 中的数据进行处理,等同于双倍压力写入 TiDB 集群,预期结果是对于双倍的数据量,同样可以在 27 分钟处理完,同时数据库资源使用率应大于一个应用的。
测试结果符合预期,证明应用没有真正的提高并发。
可能的原因?
-
应用并发太高,CPU 繁忙导致应用性能瓶颈。

通过对批处理程序的深入排查,发现MyBatis在处理大量数据时因JDK8中ConcurrentHashMap.computeIfAbsent方法导致线程阻塞,严重影响性能。通过升级JDK版本及MyBatis自身优化,成功解决了该问题。
最低0.47元/天 解锁文章
878

被折叠的 条评论
为什么被折叠?



