mysql+mycat压力测试一例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql+mycat压力测试一例相关的知识,希望对你有一定的参考价值。

前言

有很多人担心生产系统上新东西的程序怕压力跟不上和稳定性不行,是的,大家都怕,所以领导要求做一次压力测试,我个人也觉得是有必要的.

如果按原理来说,mycat如果不做分片,纯粹只是代理的话,他所做的事情,其实更多的是数据转发,而这个转发能力,当然就是看他能有多强.

既然理论上转发能力很强,那么是不是就可以忽略不计呢,当然不是,所以需要用直连mysql的测试数据来做对比.


测试前准备

服务器分配情况:

10.21.128.156:mycat1.6.5,sysbench0.4

10.21.128.157:mysql5.7.20主库

10.21.128.158:mysql5.7.20从库1

10.21.128.159:mysql5.7.20从库2

第一步当然是安装好mysql,这里就不详细介绍怎么安装了,但是,my.cnf的参数是有些变化的,主要原因是要适应高并发压测环境,不然就被参数限制,然后程序退出.当然了,如果你想尽量模拟线上环境,那这些限制你得思考在内,更改就需要谨慎一些,我这里只是给出一例来参考.

#首先,就是要把系统的连接数和打开文件数搞起来
ulimit -SHn 65535
#想永久生效就要这样
echo "
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
" >> /etc/security/limits.conf

然后,更改mysql配置文件参数

#打开配置文件
vim /usr/local/mysql/my.cnf
#其他参数我们暂时忽略,只看这些关乎压测的参数
[mysqld]
#每台机都需要不一样的ID,主从环境下
server-id = 128157
#全局最大打开文件数,不可以超过系统设定的最大文件数,不然无效
open_files_limit = 65530
#innodb引擎限制一次打开表空间文件.ibd的文件描述符数量
innodb_open_files = 65530
#允许存到缓存里的表的句柄数量,压测自然要打开很多表,设大一点就对了,受系统limit和上面两个参数一起限制
table_open_cache = 65000
#最大连接数,×××,不然压着不通就麻烦
max_connections=30000
#最大每用户连接数,和上面一样
max_user_connections=20000
#最大数据包大小,做压测改大一点还是有必要
max_allowed_packet = 128M
#限制了同一时间在mysqld上所有session中prepared 语句的上限,平时不用理这个参数,但是压测就需要调大一点
max_prepared_stmt_count=100000

其他参数我就不一一列举,自己看情况来设置就行,然后,重启生效待命.


软件安装

先说说压测工具的选择问题,在MySQL协议上Mycat不兼容tpcc,所以放弃tpcc。然后sysbench1.0对mycat兼容也比较欠佳,压测不明原因失败次数多,所以也只能放弃.最后选定sysbench0.4和0.5来使用,可以顺利测出结果,而且从压测的原理来说也比较客观.

所以,我们需要安装的软件有:mysql(默认已装),mycat,sysbench0.4或0.5

mysql怎么安装和授权什么的,这里就不细说了,还请各位自己搭建好.

先安装mycat:

1)搭建jdk环境

由于mycat是java程序,所以需要安装JDK,版本至少要jdk1.6以上,下载好安装包后,

tar xf jdk-8u144-linux-x64.tar.gz

mv jdk1.8.0_144/ /usr/local/

ln -sf jdk1.8.0_144/ jdk

创建环境变量

vim /etc/profile.d/java.sh

export JAVA_HOME=/usr/local/jdk

export JRE_HOME=/usr/local/jdk/jre

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib

export PATH=$PATH:$JAVA_HOME/bin

重载环境变量

source /etc/profile

验证安装

java -version

java version "1.8.0_144"

Java(TM) SE Runtime Environment (build 1.8.0_144-b01)

Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

安装完成,可以使用.

 

2)配置mycat

了解java程序的同学应该知道,java程序只要配置好,直接启动就能用,所以没有安装的概念,直接将mycat配置做好就可以用.

因为没有涉及分库分表,mycat只需要设置server.xml和schema.xml即可,具体mycat存放路径没规定,我将他放在/usr/local了.

先看基本环境设置server.xml,大部分设置都可以不动,注意添加修改下面配置就可以了,注意标签:

vim /usr/local/mycat/conf/server.xml

<system>
<property name="idleTimeout">2880000</property> <!--设置超时时间为28800秒 -->
<property name="maxPacketSize">134217728</property> <!--设置最大网络包为128M -->
<property name="charset">utf8</property> <!--设置默认字符集为utf8 -->
<property name="txIsolation">2</property> <!--设置隔离级别为RC -->
<property name="sqlExecuteTimeout">600</property> <!--设置sql执行的超时时间为600秒 -->
</system>
<!--下面是设置mycat的用户名/密码和权限控制,和mysql的用户名密码无关 -->
<user name="root" defaultAccount="true">
                <property name="password">mycat123</property>
                <property name="schemas">sbtest,testppp</property>
</user>
<user name="sysbench">
                <property name="password">sb123</property>
                <property name="schemas">sbtest</property>
        </user>
<user name="test">
                <property name="password">test</property>
                <property name="schemas">sbtest</property>
                <property name="readOnly">true</property>
                <privileges check="false">
                        <schema name="sbtest" dml="0001" >
                        <table name="sbtest11" dml="1111"></table>
                        </schema>
                </privileges>
</user>

设置了一些必要项目,和创建了三个用户root,sysbench,test.这三个用户和数据库的用户没有关联,是独立的,即使这个用户密码被破解,数据库的密码依然安全.其中root有完全控制权限,sysbench只能控制sbtest库,test也只能控制sbtest库,而且限制了读写权限.

然后设置逻辑库配置文件schema.xml,这里改动比较多,所以直接贴上整个文件:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="sbtest" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
        </schema>
        <schema name="testppp" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn2">
        </schema>
        <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                /> -->
        <dataNode name="dn1" dataHost="10.21.128.157" database="sbtest" />
        <dataNode name="dn2" dataHost="10.21.128.157" database="testppp" />
        <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
         <dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" />
        <dataNode       name="jdbc_dn2" dataHost="jdbchost" database="db2" />
        <dataNode name="jdbc_dn3"       dataHost="jdbchost" database="db3" /> -->
        <dataHost name="10.21.128.157" maxCon="3000" minCon="20" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="-1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="10.21.128.157:3306" user="root" password="128157">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="10.21.128.158:3306" user="root" password="128157" />
                        <readHost host="hostS3" url="10.21.128.159:3306" user="root" password="128157" />
                </writeHost>
                <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
        </dataHost>
</mycat:schema>

设置了两个逻辑库sbtest和testppp(和真实库同名,其实可以不同),指向的真实数据库的主从环境dn1和dn2,里面有一主两从三台真实服务器地址,并开启读写分离(事务只走主库).

3) 启动mycat,

#启动mycat
Mycat start
#重启mycat
Mycat restart
#关闭mycat
Mycat stop
#而Mycat默认的连接端口是8066,管理端口是9066,可以在server.xml修改.
ss -ntplu |grep java
tcp    LISTEN     0      100      :::9066                 :::*                   users:(("java",pid=115779,fd=168))
tcp    LISTEN     0      100      :::8066                 :::*                   users:(("java",pid=115779,fd=172))
#看到端口起来了,就可以使用了,因为mycat支持mysql原生协议,所以连上8066端口是不会和一般mysql有什么区别,直接就能使用了.
#如果更改了任何配置文件,可以登录进管理端口执行下列命令实时热刷新配置,相当方便.
mysql -uroot -pmycat123 -h10.21.128.156 -P9066 
#更改server的配置可以
Mysql>reload @@config
如果改了逻辑库的配置,需要这个命令
Mysql>reload @@config_all

加载完成就可以使用新配置了,哪怕是改了登录用户名也能热加载.


搭建sysbench

下载下来后,只要有c运行库就能编译安装,但是要创建mysql库文件的软连接,不然会报错找不到库文件,

#先创建mysql库文件的软连接
ln -sf /usr/local/mysql/lib/* /usr/lib64/
#然后执行:
cd /tmp/sysbench-0.4.12-1.1
./autogen.sh
./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib
Make
#如果 make 没有报错,就会在 sysbench 目录下生成二进制命令行工具 sysbench
cd /tmp/sysbench-0.4.12-1.1/sysbench
ls -l sysbench
-rwxr-xr-x 1 root root 3293186 Sep 21 16:24 sysbench

在此,环境就搭建完毕了.


开始测试

环境准备好了,就开始测试了,测试前要先准备测试数据,需要使用命令来制造出来,需要比较长的时间,重点是要关注硬盘空间是否足够:

#避免不必要的错误,直连数据库操作
mysql -uroot -p128157 -h10.21.128.157 -P3306
#创建测试数据库,sysbench默认库名是sbtest,也可以指定库名
mysql> create database sbtest
#进入sysbench程序目录
cd /tmp/sysbench-0.4.12-1.1/sysbench
#开始造数据,
./sysbench --mysql-host=10.21.128.157 --mysql-port=3306 --mysql-user=root --mysql-password=128157  --test=tests/db/oltp.lua --oltp_tables_count=15 --oltp-table-size=40000000 --mysql-table-engine=innodb --rand-init=on prepare

参数解析:

--test=tests/db/oltp.lua    表示调用 tests/db/oltp.lua 脚本进行 oltp 模式测试
--oltp_tables_count=15    表示会生成 15 个测试表
--oltp-table-size=40000000    表示每个测试表填充数据量为 40000000
--rand-init=on    表示每个测试表都是用随机数据来填充的

--mysql-table-engine=innodb    表示表的引擎是innodb

prepare    用于准备测试需要的数据,准备完后执行run来测试,测试完成后如果需要清理数据就用cleanup来清除测试数据

所以这里创造了15个表,里面每个表有4000万行的数据,数据为随机输入,这个数据量大概需要150G硬盘空间,估计可以涵盖大部分情况了吧,当然,你也可以创建更多数据.

然后就可以进行正式测试了,我们先进行测试普通主从架构:

#进入sysbench程序目录
cd /tmp/sysbench-0.4.12-1.1/sysbench
#执行测试命令
./sysbench --mysql-host=10.21.128.157 --mysql-port=3306 --mysql-user=root --mysql-password=128157  --test=tests/db/oltp.lua --oltp_tables_count=15 --oltp-table-size=40000000 --mysql-table-engine=innodb --num-threads=1024 --oltp-read-only=off  --report-interval=10 --rand-type=uniform --max-time=3600 --max-requests=0 --percentile=99 run >> /tmp/sysbench_oltpX_32_20171113-1.log

参数解析:

--num-threads=1024    表示发起1024个并发连接
--oltp-read-only=off    表示不要进行只读测试,也就是会采用读写混合模式测试
--report-interval=10    表示每10秒输出一次测试进度报告
--rand-type=uniform    表示随机类型为固定模式,其他几个可选随机模式:uniform(固定),gaussian(高斯),special(特定的),pareto(帕累托)
--max-time=3600    表示最大执行时长为3600秒,测试将在这个时间后结束
--max-requests=0    表示总请求数为 0,因为上面已经定义了总执行时长,所以总请求数可以设定为 0;也可以只设定总请求数,不设定最大执行时长
--percentile=99    表示设定采样比例,默认是 95%,即丢弃1%的长请求,在剩余的99%里取最大值

根据上面的解析,最后输出到一个文件.

然后到mycat代理环境:

./sysbench --mysql-host=10.21.128.156 --mysql-port=8066 --mysql-user=sysbench --mysql-password=sb123 \ 
--test=tests/db/oltp.lua --oltp_tables_count=15 --oltp-table-size=40000000 --mysql-table-engine=innodb --num-threads=1024 --oltp-read-only=off --report-interval=10 --rand-type=uniform --max-time=3600 --max-requests=40000000 --percentile=99 run >> /home/logs/sysbench_oltpX_32_20171113-2.log

和上面一样,设定了并发为1024个线程,测试时间为3600秒即1小时,同时也是用到刚才制造出来的15个4000万行的表,设定取值采样平均值为99%的数据,输出到另一个log文件.


阅读测试报告

测试完了,就来看结果了,我们拿其中一个结果来解析说一下:

#忽略掉一些每10秒统计值,只看最后的统计值
vim /tmp/sysbench_oltpX_32_20171113-1.log
sysbench 0.5:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1024
Report intermediate results every 10 second(s)
Random number generator seed is 0 and will be ignored


Threads started!
-- 每10秒钟报告一次测试结果,tps、每秒读、每秒写、99%以上的响应时长统计
[  10s] threads: 1024, tps: 364.69, reads/s: 6324.66, writes/s: 1765.66, response time: 4292.46ms (99%)
[  20s] threads: 1024, tps: 475.80, reads/s: 6037.91, writes/s: 1640.10, response time: 4088.05ms (99%)
[  30s] threads: 1024, tps: 439.40, reads/s: 6349.45, writes/s: 1808.89, response time: 3248.44ms (99%)
[  40s] threads: 1024, tps: 487.70, reads/s: 6438.46, writes/s: 1879.72, response time: 4385.98ms (99%)
[  50s] threads: 1024, tps: 395.70, reads/s: 6498.99, writes/s: 1849.00, response time: 3845.88ms (99%)
    .
    .
    .
[3560s] threads: 1024, tps: 385.80, reads/s: 4949.60, writes/s: 1503.80, response time: 19827.73ms (99%)
[3570s] threads: 1024, tps: 249.70, reads/s: 3679.90, writes/s: 1009.40, response time: 12016.58ms (99%)
[3580s] threads: 1024, tps: 328.90, reads/s: 4511.40, writes/s: 1301.40, response time: 7419.06ms (99%)
[3590s] threads: 1024, tps: 196.40, reads/s: 3058.90, writes/s: 815.30, response time: 12092.35ms (99%)
[3600s] threads: 1024, tps: 386.60, reads/s: 5282.74, writes/s: 1537.78, response time: 13614.18ms (99%)
OLTP test statistics:
    queries performed:
        read:                            16913554        -- 读总数
        write:                           4832444        -- 写总数
        other:                           2416222        -- 其他操作总数(SELECT、INSERT、UPDATE、DELETE之外的操作,例如COMMIT等)
        total:                           24162220        -- 全部总数
    transactions:                        1208111 (335.29 per sec.)        -- 总事务数(每秒事务数)
    deadlocks:                           0      (0.00 per sec.)        -- 发生死锁总数
    read/write requests:                 21745998 (6035.29 per sec.)        -- 读写总数(每秒读写次数)
    other operations:                    2416222 (670.59 per sec.)        -- 其他操作总数(每秒其他操作次数)

General statistics:
    total time:                          3603.1388s        -- 总耗时
    total number of events:              1208111        -- 共发生多少事务数
    total time taken by event execution: 3688348.3797s        -- 所有事务耗时相加(不考虑并行因素)
    response time:
         min:                                 28.41ms        -- 最小耗时
         avg:                               3052.99ms        -- 平均耗时
         max:                              48667.93ms        -- 最长耗时
         approx.  99 percentile:           12708.40ms        -- 超过99%平均耗时

Threads fairness:
    events (avg/stddev):           1179.7959/29.07
    execution time (avg/stddev):   3601.9027/1.01

所以,每秒事务数Tps达335.29,每秒查询数Qps达6035.29.

看完解析,来看结果,下面是直接测主从环境的结果:

OLTP test statistics:
    queries performed:
        read:                            21161868
        write:                           6046248
        other:                           3023124
        total:                           30231240
    transactions:                        1511562 (419.65 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 27208116 (7553.71 per sec.)
    other operations:                    3023124 (839.30 per sec.)
 
General statistics:
    total time:                          3601.9548s
    total number of events:              1511562
    total time taken by event execution: 3687391.4160s
    response time:
         min:                                 17.05ms
         avg:                               2439.46ms
         max:                              34582.27ms
         approx.  99 percentile:           11020.73ms
 
Threads fairness:
    events (avg/stddev):           1476.1348/27.71
execution time (avg/stddev):   3600.9682/0.33

每秒事务数Tps达419.65,每秒查询数Qps达7553.71

下面是通过mycat代理的结果

OLTP test statistics:
    queries performed:
        read:                            23383990
        write:                           6681140
        other:                           3340570
        total:                           33405700
    transactions:                        1670285 (463.76 per sec.)
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 30065130 (8347.72 per sec.)
    other operations:                    3340570 (927.52 per sec.)
 
General statistics:
    total time:                          3601.5979s
    total number of events:              1670285
    total time taken by event execution: 3687347.4150s
    response time:
         min:                                 21.40ms
         avg:                               2207.62ms
         max:                              23365.26ms
         approx.  99 percentile:            8844.22ms
 
Threads fairness:
    events (avg/stddev):           1631.1377/26.35
execution time (avg/stddev):   3600.9252/0.36

每秒事务数Tps达463.76,每秒查询数Qps达8347.72

从总体说个结果,果然和我预料差不多,损耗在5%之内.






以上是关于mysql+mycat压力测试一例的主要内容,如果未能解决你的问题,请参考以下文章

Centos 7使用MyCat搭建 MySQL-读写分离

Mycat开发实践---Mycat的网络通信框架

mysql 第十七篇文章~mycat的读写分离

MySQL数据库集群-PXC方案

MySQL数据库集群-PXC方案

mycat实现mysql读写分离,热切换,集群