ITPub博客

首页 > 数据库 > > TDSQL-Percona与MySQL- 5.7 性能对比与分析

TDSQL-Percona与MySQL- 5.7 性能对比与分析

作者:浪花小雨滴 时间:2020-05-19 14:37:23 0 删除 编辑

本文是我最初于2017年发表在我的个人微信公众号里面,现发布在这里。


概述

过去这一年多,我们为了实现TDSQL分布式事务处理(TDSQL XA) 功能,经过对比MariaDB-10.1.9与MySQL-5.7在XA方面的功能实现的可靠性,决定使用MySQL-5.7作为TDSQL XA的后端数据库。为了使用到线程池,我们使用了Percona-server-5.7. 我们对Percona-server-5.7做了大量的改进,包括修复其分布式事务处理方面的所有发现的bug,以及把TDSQL-MariaDB的各种功能实现和性能改进(包括我们自己实现的强同步等待机制)移植到Percona中,形成了TDSQL-Percona。现在TDSQL XA开发完成后经过实测对比发现TDSQL-Percona不仅完全满足了TDSQL XA 的各种功能需求,而且它的实际性能也比MySQL-5.7有巨大优势。本文将通过性能测试对比以及分析,告诉用户为什么TDSQL-Percona-5.7比社区版的MySQL-5.7 能够有巨大的性能优势。


性能测试

测试环境和配置
硬件:TS85(Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz 64GB内存)
操作系统:linux内核3.10.104-1-tlinux2-0041.tl2
MySQL版本:MySQL-5.7.17 社区版 + 半同步 (无线程池可用)
Percona版本:TDSQL-Percona 5.7.17-11V1.0R010D001-20170410-0955-log + 强同步 + 线程池
主备都在同一个IDC中,网络响应时间 0.80ms,数据库的innodb buffer都设置为30G。
使用sysbench-0.5进行性能测试。

本文使用的性能测试及其结果由我组的summer同学实施和完成汇总和图表制作。

本文的测试结果图表以及文字中所有的’mysql’和‘MySQL-5.7’都是指 MySQL-5.7.17;所有的’tdsql’或者‘TDSQL-Percona’指的是‘TDSQL-Percona-server-5.7.17-11’。

Percona 线程池参数:
thread_pool_max_threads=2000
thread_pool_oversubscribe = 10
thread_pool_stall_limit = 50
thread_handling = 2
Mysql半同步参数:
全部使用默认值
Binlog_order_commits: ON
sysbench参数
数据初始化
create database caccts ;
./sysbench --num-threads=500 --test=./tests/db/oltp.lua.bak --oltp-table-size=2180000 --oltp-tables-count=10 --oltp-point-selects=1 --oltp-simple-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --oltp-index-updates=1 --oltp-non-index-updates=0 --report-interval=1 --mysql-user=xxxxxx --mysql-password=xxxxxx --mysql-host=xxxxxx --mysql-db=caccts --max-time=360000 --max-requests=2000000000 prepare
非索引更新(update)
./sysbench --num-threads=500 --test=./tests/db/update_non_index.lua --oltp-table-size=2180000 --oltp-tables-count=10 --percentile=99 --report-interval=1 --mysql-host=xxxx--mysql-user=xxx --mysql-password=xxx --mysql-db=caccts --max-time=360000 --max-requests=2000000000 --mysql-port=3306 run
只读(select)
./sysbench --num-threads=500 --test=./tests/db/select.lua --oltp-table-size=2180000 --oltp-tables-count=10 --percentile=99 --report-interval=1 --mysql-host=xxxx --mysql-user=xxx --mysql-password=xxx --mysql-db=caccts --max-time=360000 -- max-requests=2000000000 --mysql-port=3306 run
oltp
./sysbench_orig --num-threads=500 --test=./tests/db/oltp_new.lua --oltp-read-only=off --oltp-table-size=2180000 --oltp-tables-count=10 --oltp-point-selects=1 --oltp-simple-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --oltp-distinct-ranges=0 --oltp-index-updates=1 --oltp-non-index-updates=0 --percentile=99 --report-interval=1 --mysql-host=xxxx -- mysql-user=xxx --mysql-password=xxx --mysql-db=caccts --max-time=360000 --max-requests=2000000000 --mysql-port=3306 run
测试方法
用TDSQL-Percona和MySQL-5.7在相同的3台机器上面,分别创建一主两备的集群,然后各自灌入相同规模的数据。TDSQL-Percona集群开启强同步,使用线程池;MySQL-5.7集群开启半同步,不使用线程池(因为没有)。然后使用sysbench分别压测这两个集群,记录性能数据。同一时间只有一个集群的mysqld进程在运行,另一个集群的mysqld以及其他相关进程退出。使用Sysbench的3个官方测试用例select.lua, update_non_index.lua和oltp.lua。由于在select.lua和update_non_index.lua中并没有启动显式事务,而是执行单条语句并且autocommit=ON,所以我们关注的是‘QPS’而不是’TPS’,其实本质上是一样的。测例oltp.lua的实测内容依赖于sysbench配置的参数,在我们的上述配置下,在oltp.lua中启动了显式事务并且每个事务中有一条点查询select,一条点更新(索引字段),一条删除和一条插入(相同的主键)。Sysbench测例的数据行每行略大于200字节,我们使用10个表,每个表约2.18M行,总的数据量在4.5GB左右。另有一个整数列的辅助索引,占用空间约500MB。
测试结果

数据统计




图形对比











测试结果分析

从结果看出TDSQL-Percona 比MySQL的性能要好很多,在更新类测例中优势非常显著,在只读查询测例中性能优势也很大。
首先,这个测试的数据集是5GB左右,而innodb buffer pool是30GB,因此所有数据都是放在内存中的。我们这么设计是因为我们对比的目标就是要展示Percona的线程池(我们做了额外优化)和TDSQL-Percona特有的强同步机制的性能优势。所有其他方面的功能,二者的实现几乎是完全相同的。尽管TDSQL-Percona做了很多bug fix和定制功能,但是从性能角度看这些改动不会影响性能,因而本文只关注TDSQL-Percona的线程池和强同步带来的性能提升。

Select.lua

这个测试做一个随机行的点查询,它的结果有这么几个特点:
1. mysql与TDSQL-Percona的QPS相差不算特别大(mysql的QPS比TDSQL-Percona小 10%到20%),
2. 连接数<=200时,而且平均响应时间和99%请求的响应时间比TDSQL-Percona都略短。
3. 连接数>500后,mysql的99% 请求的响应时间变的更长

这个测例和结果显示了使用线程池的优势和劣势。 使用线程池的时候,TDSQL-Percona的线程池的一组N个工作线程服务M个用户连接,通常N<<M(N远远小于M)。以500个连接为例,M=500,N通常只有20到50左右。收到了客户端请求的用户连接被线程池的监听线程放入线程池的请求队列,然后这N个线程从队列中摘取请求然后执行其SQL语句。直连时mysql内部会为每个用户连接创建一个专属的工作线程来服务这个连接的请求,因而每个请求不必经历放入队列,等待处理,取出队列的过程。在连接数较少的时候(200以内),直连(mysql)由于少了这些工序,所以比使用线程池(percona)消耗的响应时间更少。
但是每个线程都会占用一定数量的linux内核资源,以及内存和CPU时间片。首先,在线程池模式下运行时,对于任何一个线程来说,在性能测试这种饱和工作量下,每个线程执行完毕立刻得到下一个请求(可能属于另一个连接)并且继续执行,因而有更大概率可以用尽它的时间片,特别是在本测例里面数据可以完全放入innodb buffer pool的情况下更是如此;另外,在本例中服务器CPU有48核,也就是说TDSQL-Percona的工作线程几乎总是不需要等待就可以得到CPU,每次用尽其时间片后又可以得到下一个时间片继续使用CPU,因而可以满负荷运行。
在直连情况下,工作线程则必须等到结果发回给客户端,然后客户端发来下一个请求后,才能继续执行,这个过程中的网络读(下一个请求)操作通常会导致这个工作线程阻塞而产生线程调度(看dstat的csw列会比线程池模式下高很多)。另外由于直连模式下CPU核数量远远小于工作线程的数量,也导致大量工作线程需要等待被linux内核调度使用CPU,却常常由于网络读等系统调用阻塞而无法用尽其时间片。并且大量的线程运行就意味着每个线程得到CPU资源所需的等待时间(在就绪队列等待)更长,而且其时间片会更短(详见 Linux的completely fare scheduler的工作机制)。所有这些缺陷都使得mysql反而变慢了,包括其QPS降低和响应时间变长。

Update_non_index.lua与oltp.lua

Update_non_index.lua测试做一个随机行的更新并且并不更新索引字段,并且是autocommit的也就是每个update语句自成一个事务;在我们的测试所做的sysbench配置下,oltp.lua做的是在一个事务中完成一个随机行的点查询,一个随机行的更新(需要更新索引)以及一个随机行的删除和插入。这3个随机行可能相同(几率很小)也可能不同。这两个测试的结果都有这样一些特点:
1. TDSQL-Percona的QPS始终保持在mysql的接近两倍,无论多少个连接
2. TDSQL-Percona的时耗始终保持在mysql的大约一半到70%,无论多少个连接
3. Oltp.lua的QPS比update_non_index.lua高很多,基本是后者的4到5倍,这是正常的。因为oltp.lua的一个事务有4条SQL语句,而update_non_index.lua的每条update语句都是一个事务。如果看TPS的话二者应该差不多而且update_non_index.lua比oltp.lua的TPS会略高。

这两个测例的结果展示了TDSQL-Percona的强同步的机制在性能方面的优势。目前TDSQL-MariaDB与TDSQL-Percona使用相同的强同步实现机制,该机制与MySQL/MariaDB官方的半同步实现机制完全不同。TDSQL强同步最显著的优点是:

1. TDSQL做强同步等待期间不占用工作线程

TDSQL做强同步等待期间是不占用工作线程的---工作线程在需要等待备机ack之前,把需要做等待的连接会话(THD)对象放入等待队列并且立刻去处理下一个请求。等那个连接所需要的备机ack收到后,会有另外的工作线程继续处理它,完成针对该请求的剩余任务。因而这种强同步等待是“异步”的,因为工作线程自身并没有阻塞 --- 任何一个连接在等待备机ack期间,没有占用任何一个工作线程。
MySQL/MariaDB在做强同步等待期间,由于rpl_semisync_master插件的实现方式的限制,工作线程不得不阻塞等待备机的ack。rpl_semisync_master插件不得不这么做是因为MySQL预留的插件接口就只允许这样同步等待备机ack,社区版的MySQL/MariaDB的工作线程无法在任何时刻中断处理当前请求并转而处理其他请求,处理任何一个请求必须“一气呵成”。如果不侵入式地大量修改MySQL/MariaDB的核心代码的话,就不可能做到TDSQL这样的异步等待。经过腾讯公司内外大量实际业务的无数次的实践检验和验证,TDSQL的强同步机制是可靠的,稳定的。

2. TDSQL-Percona的强同步等待不会阻塞其他事务提交

在全默认配置下(binlog_order_commits=ON, rpl_semisync_master_wait_point=AFTER_SYNC)的情况下,MySQL的半同步等待是由sync 阶段的leader线程为该阶段里面的每个连接上面的事务依次做半同步等待的。MySQL-5.7的3阶段组提交流水线机制要求每个阶段只能有一组事务。如果在此期间,前一个阶段(flush stage) 已经完成了,那么这个flush阶段的事务也只能继续等待处于sync阶段的那些事务离开sync阶段,它们才能进入sync阶段。同时,那些等待进入flush阶段的事务也只能阻塞等待当前flush阶段的事务离开该阶段。也就是说所有这些将要开始组提交和正在做组提交的事务,都要等待sync阶段的leader线程为该阶段的每个事务完成半同步等待。如果备机ack延迟到达,那么这个延迟会把master上面正在提交的事务都变慢,降低TPS和QPS,延长响应时间。MariaDB社区版的半同步等待没有这个问题。
与社区版MySQL不同的是,TDSQL-Percona的强同步等待并不会阻塞任何事务的提交流程,因为这个等待并不是通过leader线程做阻塞等待实现的,而是直接把会话对象(THD)放入等待队列实现的,没有任何线程需要阻塞等待备机的ack。MySQL-5.7的3阶段组提交流水线可以顺畅运行,不再需要等待备机ack。因此可以大幅提高TPS,缩短事务提交的响应时间。
由于TDSQL的这些技术优势,在update_non_index测例中,TDSQL-Percona的性能优势非常明显:这个测例中每个update语句自成一个事务,该事务提交期间对TDSQL-Percona来说要做强同步等待,对MySQL来说要做半同步等待。由于TDSQL-Percona的强同步等待不占用工作线程,因此工作线程经常可以不阻塞立刻处理下一个请求;而MySQL则需要工作线程一直阻塞等待,CPU利用率和吞吐量(throughput, QPS)就无法与TDSQL-Percona相匹敌。对于MySQL-5.7来说,服务器配置再高,如果无法利用其硬件性能,那么这些硬件配置也只能浪费。另外,由于MySQL的半同步等待还会延长其他正在提交的语句等待的时间,所以自然每个语句的时延都会更长。

总结

通过这一系列测试,我们可以看到TDSQL-Percona凭借其与官方半同步完全不同的强同步机制,以及优化改进的线程池,获得了比MySQL社区版更加优秀的巨大的性能优势。这些自研的强大功能,经过腾讯公司内外大量实际业务的无数次的实践检验和验证证明是可靠的,稳定的。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3145631/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    40013