做者简介mysql
蓝寅,开源分布式中间件DBLE项目负责人;持续专一于数据库方面的技术, 始终在一线从事开发;对数据复制,读写分离,分库分表的有深刻的理解与实践。git
问题原由:github
用benchmarksql_for_mysql对原生MyCat-1.6.1和DBLE-2.17.07版作性能测试对比,发现DBLE性能只到原生版MyCat的70%左右。算法
问题分析过程:sql
分析过程主要有如下内容:包括现象,收集数据,分析猜想缘由,验证猜想的方式来进行。数据库
开源分布式中间件DBLE:
社区官网,获取DBLE快速入门指南及最新资讯:
https://opensource.actionsky.com
GitHub主页,查看官方文档:
https://github.com/actiontech/dble
社区技术交流群,迅速获取官方支持:
QQ群:669663113
1.1 先对二者进行一个CPU占用的堆栈分析后端
经过对CPU火焰图的比较,发现DBLE用在纯排序上的CPU占用在15%以上,而MyCat在排序上没有看到明显的CPU占用。( 复盘时的思考:这里有明显的可疑之处,应当及早观察二者是否公平)session
1.2 首先猜想可能的缘由并发
1.3 对猜想缘由的验证分布式
2.1 猜想一:源码实现缘由
2.1.1 猜想描述
梳理DBLE源码排序逻辑的实现细节,是多路归并的排序,理论上是最优选择。
实际上具体的实现上有可优化的空间,以下图, N个数的K路排序的初始化值理论最优复杂度是O(N),而这里变成了O(NlogK2) 。
2.1.2 验证猜想
为了快速将排序的因素排除,将cmp函数直接返回1再次作测试。结果提高了10%的性能,因此虽然cmp是有性能问题,但致使性能如此大还有其余缘由。(复盘:新版本已优化此处10%的性能差别)
2.2 猜想二:回到排序SQL
查看B-SQL源码,有3个排序SQL,其中有2个排序SQL的排序列不在select 项中,这原本应该引起MyCat的bug的,但咱们在返回集和抓包中都没有发现。再仔细阅读源码,原来B-SQL经过hard code的方式使得压力永远跑不到这两个代码路径上,这样咱们又排除了2个干扰因素,问题集中到剩下的那个排序上了。
将排序除去,64数据量,64并发,DBLE的性能是MyCat的96%。
证实确实和排序有关。
3.1 猜想排序算法在特殊场景下的适用性
3.1.1 猜想描述
因为MyCat排序采用的是timsort, 时间复杂度的可能最优是O(n)。
而DBLE的多路归并排序在B-SQL这个场景下时间复杂度最差状况是O(n*(k-1)).
猜想timSort排序在B-SQL多并发场景下可能会优于多路归并。
3.1.2 验证猜想
用B-SQL压测并统计函数调用次数。
结论:
在B-SQL场景下:
问题集中在了为何DBLE会有更屡次的比较函数调用。
4.1 验证压力下发的SQL是否与cmp函数调用相符是否下发的SQL就不公平
4.1.1收集数据
用抓包的方式分别抓取B-SQL发给MyCat和DBLE的包,结果发现 DBLE的全部SQL中排序这条SQL的发生次数是MyCat的10倍左右。
再次用yourkit查看调用次数和CPU分布验证,发现调用次数确实符合抓包的结论,CPU分布也是DBLE分了大量的时间用于排序,而MyCat对排序的分配几乎能够忽略。这也与最一开始的火焰图结论同样。
用wireshark分析DBLE抓包结果,发现某些链接执行一段时间以后大量的重复出现排序+delete的query请求直到压力结束,举例以下图。
4.1.2 分析缘由
分析B-SQL源码这里发现只有delete的数据为0才会引起死循环。
4.1.3 验证测试
在引起死循环的缘由找到以前,先修改代码验证测试。不管result是不是0都设置newOrderRemoved=true使得B-SQL跳出死循环。
验证测试,DBLE性能终于符合预期,变为MyCat的105%。
至此,B-SQL有排序引起DBLE性能降低的缘由找到了,某种场景下B-SQL对DBLE执行delete,影响行数为0,致使此时会有死循环,发送了大量排序请求,严重下降了DBLE性能,而且并发压力越大越容易出现,但也有必定概率不会触发。
5.分析哪一种场景下delete行数为0
5.1隔离级别测试
由于对隔离级别并不熟悉,花了很长时间才想到缘由,在MySQL上作了一个实验:
也就是说,在并发状况下确实有可能有死循环出现。
5.2 分析为何只有在DBLE上有这个问题而在MyCat上没有这个问题
缘由是DBLE和MyCat的默认隔离级别都是REPEATED_READ,但MyCat的实现有bug,除非客户端显式使用set语句,MyCat后端链接使用的隔离级别都是下属结点上的默认隔离级别;而DBLE会在获取后端链接后同步上下文,使得session级别的隔离级别和DBLE配置相同。然后端的四个结点中除了1台是REPEATED_READ,其余三个结点都是READ_COMMITTED。这样一样的并发条件,DBLE100%会触发,而MyCat只有25%的几率触发。
5.3 验证测试
将DBLE上的配置添加<property name="txIsolation">2</property>(默认是3)与默认作对比:
性能比是1:0.75.符合指望,性能缘由所有找到。
最后吐槽一下B-SQL,找了官方的B-SQL4.1版和5.0版,4.1版并未对此状况作任何改进,仍有可能陷入死循环影响测试。
而5.0的对应代码处有这么一段注释,不知道PGSQL是否这里真的会触发异常,但MySQL并不会触发异常,仍有可能陷入死循环。
1.cmp函数时候初始化值的问题,影响部分性能,非主要性能瓶颈,新版本已改进。
2.同时触发了MyCat和B-SQL的两个bug,致使测试的性能数据负负得正;
须要将MySQL结点都改成READ_COMMITED,再将配置改成<property name="txIsolation">2</property>,避开上述的bug。
1.测试环境的搭建不管是配置参数仍是各个节点的状态都要同步,保证公平。
2.性能分析工具的使用。
3.性能测试可能一次的结果具备偶然性,须要屡次验证。
4.当有矛盾的结论时候,可能就快接近问题的真相了,须要持续关注。
| 使用指南
开源分布式中间件 DBLE 快速入门指南
DBLE 自定义拆分算法
DBLE Server.xml 配置解析
DBLE Schema.xml 配置解析
DBLE rule.xml 配置解析
| 案例分析
DBLE和Mycat跨分片查询结果不一致案例分析
开源分布式中间件DBLE
社区官网: https://opensource.actionsky.com/
GitHub主页: https://github.com/actiontech/dble
技术交流群:669663113
开源数据传输中间件DTLE
社区官网: https://opensource.actionsky.com/
GitHub主页: https://github.com/actiontech/dtle
技术交流群:852990221