其他分享
首页 > 其他分享> > 分布式 | 开源分布式中间件DBLE容器化快速安装部署

分布式 | 开源分布式中间件DBLE容器化快速安装部署

作者:互联网

作者简介

蓝寅,开源分布式中间件DBLE项目负责人;持续专注于数据库方面的技术, 始终在一线从事开发;对数据复制,读写分离,分库分表的有深入的理解与实践。

 

问题起因

用benchmarksql_for_mysql对原生MyCAT-1.6.1和DBLE-2.17.07版做性能测试对比,发现DBLE性能只到原生版MyCAT的70%左右。

 

问题分析过程

分析过程主要有以下内容:包括现象,收集数据,分析猜测原因,验证猜测的方式来进行。

 

1.分析瓶颈

1.1 先对两者进行一个CPU占用的堆栈分析

通过对CPU火焰图的比较,发现DBLE用在纯排序上的CPU占用在15%以上,而MyCAT在排序上没有看到明显的CPU占用。( 复盘时的思考:这里有明显的可疑之处,应当及早观察两者是否公平)

 

1.2 首先猜测可能的原因

 

1.3 对猜测原因的验证

 

2.分析DBLE排序的问题

2.1 猜测一:源码实现原因

梳理DBLE源码排序逻辑的实现细节,是多路归并的排序,理论上是最优选择。

实际上具体的实现上有可优化的空间,如下图, N个数的K路排序的初始化值理论最优复杂度是O(N),而这里变成了O(N*logK*2) ,并且由于K本身是4,所以这里的2不能忽视。

 

为了快速将排序的因素排除,将cmp函数直接返回1再次做测试。结果提升了10%的性能,所以虽然cmp是有性能问题,但致性能如此大还有其他原因。TODO()

 

2.2 猜测二:limit不公平原因

由于DBLE实现时,对聚合函数以及排序的SQL并没有做limit 的改写,猜测是这样导致的不公平。

 

将limit配置改到10000,测试结果是性能问题仍旧。

解释:即使没有limit 100的sql改写,本身结果集也就平均为大约300以内,并不会造成如此大的差异。(复盘思考:这里应当做一次函数调用统计来证明排序次数是公平的)

 

2.3 猜测三:线程池实现原因

DBLE线程池有2个,一个是专门处理复杂查询的,是个无界的线程池。而mycat只有一个有界的线程池。

 

通过修改线程池的实现方式,发现性能无改善。

 

2.4 猜测四:并发数有关

验证:将压力并发数改成1,仍然有10%的性能差距。

 

2.5 猜测五:回到排序SQL

之上的猜测都没有命中,重新回到排序SQL;

查看源码和抓包的输出,发现MyCAT对排序有bug却没有报出响应的错误。查看原因是B-SQL的排序case实际只使用了1个(这里吐槽下B-SQL的实现,HardCode使得)。所以以上所有的性能问题是都是一个排序SQL引起的。

使用单一排序的sysbench压力压排序,结果诡异:

这个结论和B-SQL复合压测结论是相反的,B-SQL的结论是:

 

2.5.2 收集线程信息

 

2.7 调整参数 校准结果,结论如下:

  

3.分析多线程10%性能差距原因

3.1 猜测聚合函数的影响

猜测这10%是由于聚合函数引起的,但yourkit的结果并不支持这个擦测。

还是尝试去掉聚合函数比较一下。测试结果证明和聚合函数无关。

 

3.2 猜测流量不同

猜测发给MyCAT 和DBLE的流量不同导致延迟

单线程压力抓包分析DBLE会多发一个SET SESSION TRANSACTION ISOLATION,但理论上不会有更大的延迟(复盘思考:这里其实是很重要的线索,不应放掉每一处不同的细节)。

 

3.3 观测发现线程切换问题

通过yourkit观察调用发现DBLE采用的是异步处理IO,MyCAT是同步的。

这个变更是因为前后端连接池是公用的,前端同步IO在某些场景会阻塞等待后端IO的返回结果,可能引发死锁。(注:未来考虑需要阻塞的部分和计算过于复杂的IO请求变更为异步的,其余部分用同步即可)

考虑在目前测试场景中并没有引发死锁的case,将代码变更回滚。(注:实际是有的,复杂查询建立新连接时就会, 简单的代码回滚会有hang死的问题,此问题可以在hang住时通过jstack发现)

 

结论:

 

至此,IO问题影响10%的性能确认。未来对此项需要做改进 。

  

 

4.回到排序问题

4.1 改进cmp函数问题

修改DBLE源码,将cmp中的初始化逻辑复杂度改为O(n)。

 

结论:改进cmp有效。

 

4.2 改进limit 问题

修改DBLE源码,将复杂查询中的聚合函数和排序加上limit逻辑。

 

结论:limit改进有效。

 

 

5.复合B-SQL压力问题

继续验证时但在使用B-SQL复合压力时,仍然有问题出现:

现象如下:

对于现象3 ,原因是DBLE和mycat对分布式事务处理方式不同,事务中,DBLE即使碰到插入数据主键冲突也要显式rollback,而B-SQL的代码中没有做这个步骤,导致可能会在mysql节点上有未提交的事务,如果超过innodb_lock_wait_timeout(50s)的设置就会发生。

所以问题就集中在现象2上了。

 

5.1 猜测原因是并发太多

并发数可能影响排序性能。

将排序除去,64数据量,64并发,DBLE的性能是MyCAT的96%。

证明确实和排序有关。

 

6.分析多并发压力排序性能的原因

6.1 猜测排序算法在特殊场景下的适用性

由于MyCAT排序采用的是timsort, 时间复杂度的可能最优是O(n)。

而DBLE的多路归并排序在B-SQL这个场景下时间复杂度最差情况是O(n*(k-1)).

猜测timSort排序在B-SQL多并发场景下可能会优于多路归并。

用sysbench压order by并统计函数调用次数

用B-SQL压测并统计函数调用次数。

 

结论:

1.在sysbench场景下,

2.在B-SQL场景下,

 

7. 分析DBLE的cmp函数次数调用多的原因

7.1 猜测是count(distinct) 的原因

因为有count(distinct) 的实现,所以DBLE 需要排序的次数多。

因为上述矛盾的结论,这里走了一些弯路,把焦点集中在了线程切换的消耗上了,尝试修改线程模型并测试发现相关性不强。

在这种情况下yourkit拉取函数调用次数,发现DBLE比较函数(cmp)的调用次数是mycat的7倍以上,说明现象与 count(distinct)并不强相关。

 

8. 分析DBLE排序时cmp函数次数调用多的原因

问题集中在了为什么DBLE会有更多次的比较函数调用。

8.1 验证压力下发的sql是否与cmp函数调用相符是否下发的SQL就不公平

分析B-SQL源码这里发现只有delete的数据为0才会引发死循环。

在引发死循环的原因找到之前,先修改代码验证测试。无论result是否是0都设置newOrderRemoved=true使得B-SQL跳出死循环。

验证测试,DBLE性能终于符合预期,是mycat的93%,如果改成IO模型为同步,则变为mycat的105%。

至此,B-SQL有排序引发DBLE性能下降的原因找到了,某种场景下B-SQL对DBLE执行delete,影响行数为0,导致此时会有死循环,发送了大量排序请求,严重降低了DBLE性能,并且并发压力越大越容易出现,但也有一定几率不会触发。

 

9.分析哪种场景下delete行数为0

9.1隔离级别测试

因为对隔离级别并不熟悉,花了很长时间才想到原因,在mysql上做了一个实验:

也就是说,在并发情况下确实有可能有死循环出现。

 

9.2 分析一下为什么只有在DBLE上有这个问题而在MyCAT上没有这个问题 

原因是DBLE和mycat的默认隔离级别都是REPEATED_READ,但mycat的实现有bug,除非客户端显式使用set语句,mycat后端连接使用的隔离级别都是下属结点上的默认隔离级别,而DBLE会在获取后端连接后同步上下文,使得session级别的隔离级别和DBLE配置相同。而后端的四个结点中除了102是REPEATED_READ,其他三个结点都是READ_COMMITTED。这样同样的并发条件,DBLE100%会触发,而mycat只有25%的概率触发。

 

9.3 验证测试

将DBLE上的配置添加<property name="txIsolation">2</property>(默认是3)与默认做对比,

性能比是1:0.75.符合期望,性能原因全部找到。

 

10. 吐槽

最后吐槽一下B-SQL,找了官方的B-SQL4.1版和5.0版,4.1版并未对此情况做任何改进,仍有可能陷入死循环影响测试。

而5.0的对应代码处有这么一段注释,不知道PGSQL是否这里真的会触发异常,但mysql并不会触发异常,仍有可能陷入死循环。

 

11. 性能原因回顾

1.IO模型的不同,DBLE有10%的损失。未来可以调整模型改进

2.cmp函数时候初始化值的问题,已改进。

3.limit的问题,已改进

4.配置参数的不同,要调整为一致。

5.隔离级别的问题,需要将mysql结点都改为READ_COMMITED,再将配置改为<property name="txIsolation">2</property>,避开MyCAT和B-SQL的bug。

6.不算性能问题,由于要保证分布式事务的原子性,事务中插入数据时发生类似主键冲突的错误也必须显式回滚,这点和mysql行为不同,暂时没有更好的解决方案。

 

12. 收获

1.测试环境的搭建无论是配置参数还是各个节点的状态都要同步,保证公平。

2.性能分析工具的使用。

3.性能测试可能一次的结果具有偶然性,需要多次验证。

4.当有矛盾的结论时候,可能就快接近问题的真相了,需要持续关注。

 

最后,感谢黄炎对于性能优化的指导,感谢朱妮娜辛苦的测试与收集数据。

 

 

开源分布式中间件DBLE

GitHub主页:https://github.com/actiontech/dble

技术交流群:669663113

开源数据传输中间件DTLE

GitHub主页:https://github.com/actiontech/dtle

技术交流群:852990221

 

标签:性能,中间件,MyCAT,DBLE,SQL,排序,猜测,分布式
来源: https://blog.csdn.net/ActionTech/article/details/94459249