MySQL原理简介—3.生产环境的部署压测

大纲

1.普通的Java应用系统能抗多少请求

2.高并发下的数据库用什么样的机器

3.部署完数据库之后需要先进行压测

4.QPS和TPS之间的区别

5.IO相关的压测性能指标

6.压测时需要关注的其他性能指标

7.一台机器每秒可以抗多少并发的影响因素

8.sysbench是非常好用的数据库压测工具

9.压测中除了QPS和TPS外还要观察机器性能

10.压测时如何观察机器的CPU负载情况

11.压测时如何观察机器的内存负载情况

12.压测时如何观察机器的磁盘IO情况

13.压测时观察网卡的流量情况

14.使用sysbench压测数据库总结

1.普通的Java应用系统能抗多少QPS

部署Java应用系统时,常选用的机器配置是2核4G和4核8G;部署数据库时,常选用的机器配置最低是8核16G,正常16核32G。

一般Java应用系统部署在4核8G的机器上时,每秒能抗500左右的请求。一台机器每秒能抗多少请求,往往跟每个请求处理耗费多长时间有关。假设每个请求1s可以处理完,则一台机器每秒可以处理100个请求;假设每个请求100ms可以处理完,则一台机器每秒可以处理几百个请求。

4核8G的机器部署普通的Java系统,每秒能抗下几百的请求。从每秒一两百请求到每秒七八百请求都有可能,关键还是看每个请求处理要耗费多长时间。

2.高并发下的数据库用什么样的机器

Java应用系统处理请求的耗费时间主要用在与数据库进行交互。若Java系统仅仅只在内部运行一些普通的业务逻辑,性能是很高的。当Java系统和数据库产生交互时,耗时最多的便是:将网络请求发送到数据库 + 等待数据库执行SQL语句返回结果。

常说Java系统压力很大负载很高,主要是指依赖的数据库压力很大。当数据库需要执行大量增删改查的SQL语句时,需要对内存和磁盘文件进行大量IO操作,所以数据库的负载会很高。

一般8核16G的机器部署的MySQL数据库,每秒能抗一两千请求。对于16核32G的机器部署的MySQL数据库,每秒能抗两到四千请求。此外,数据库所在机器最好采用SSD固态硬盘而不是普通机械硬盘。

3.部署完数据库之后需要先进行压测

部署完数据库后,需要先对该数据库进行基准压测。即先基于一些工具模拟一个系统每秒发出1000个请求到数据库上去,观察它的CPU负载、磁盘IO负载、网络IO负载、内存负载。然后看数据库能否处理掉这1000个请求,还是只能处理500个请求。

数据库的压测和Java系统的压测是两回事。因为对于Java系统的压测,首先得知道数据库最大能抗多大压力。然后再根据数据库的最大压力,去看Java系统能抗多大压力。比如可能Java系统每秒抗2000请求,但数据库每秒只能抗500请求。

4.QPS和TPS之间的区别

QPS,指的是每秒可以处理多少个请求,可以理解为一个请求就是一条SQL语句。所以QPS指数据库每秒可以处理多少个SQL语句。

TPS,指的是每秒可以处理的事务量,所以TPS指数据库每秒会处理多少次事务提交或者回滚。一个事务会包含多个SQL语句,这些SQL语句要么一起成功,要么一起回滚。

5.IO相关的压测性能指标

(1)IOPS

(2)吞吐量

(3)latency

压测时需要关注如下的IO相关的性能指标:

(1)IOPS

IOPS指机器的随机IO并发处理能力。比如机器可以达200的IOPS,表示每秒可以执行200个随机IO读写请求。

IOPS这个指标很关键。因为InnoDB更新内存中的脏数据时,最后都会由后台IO线程在不确定的时间刷回到磁盘里,这就涉及随机IO。如果IOPS指标太低,那么会导致内存里的脏数据刷回磁盘的效率不高。

(2)吞吐量

吞吐量指的是机器的磁盘存储每秒可以读写多少字节的数据量。

吞吐量这个指标也很关键。因为MySQL在执行各种SQL语句、提交事务时,都会大量写redo日志、binlog日志,这些日志都会写到磁盘文件。所以一台机器的磁盘存储每秒可以读写多少字节的数据量,就决定了它每秒可以把多少日志写入到磁盘里。

一般写redo之类的日志,都是对磁盘文件进行顺序写入的,也就是一行接着一行的写,而不会进行随机读写。普通磁盘的顺序写入的吞吐量每秒都可以达到200MB左右。通常而言,机器的磁盘吞吐量都是足够承载高并发请求的。

(3)latency

latency指的是往磁盘里写入一条数据的延迟。

latency这个指标同样很重要。因为MySQL在执行一条SQL语句和提交事务时,都需要顺序写一条redo日志和一条binlog日志到磁盘文件。所以此时写一条日志到磁盘文件里去,到底是延迟1ms还是延迟100us,很影响数据库SQL语句的执行性能。一般来说,磁盘读写延迟越低,数据库的性能就越高,执行每个SQL语句和事务的时候速度就会越快。

6.压测时需要关注的其他性能指标

(1)CPU负载

(2)网络负载

(3)内存负载

除了QPS、TPS、IOPS、吞吐量、latency这些指标外,在压测时还需要关注机器的一些其他性能指标:

(1)CPU负载

CPU负载是一个很重要的性能指标。假设数据库压测到了每秒处理3000请求,可能其他的性能指标还都正常,但CPU负载特别高,这也说明数据库不能继续往下压测更高的QPS了。

(2)网络负载

这个要看机器带宽在压测到一定的QPS和TPS时,每秒钟机器的网卡会输入和输出多少MB数据。因为有可能机器的网络带宽最多每秒传输100MB的数据,如果当QPS为1000时网卡就打满了,那么即使其他指标正常,此时也不能继续压测了。

(3)内存负载

就是看在压测到一定情况下,机器内存耗费了多少。如果机器内存耗费过高,说明也不能继续压测了。

7.一台机器每秒可以抗多少并发的影响因素

影响因素:线程数、线程处理请求时间、CPU、内存、磁盘IO、网络带宽

(1)4核8G机器上的Java系统处理每个请求只需0.01ms每秒能抗多少请求

理论上通过增加线程数、内存读写,抗几千并发甚至上万并发都是可以的。但线程数越来越多后,切换上下文很费CPU、导致CPU负载也会变高。因此当请求源源不断进来时,可能会导致挤压从而拖垮系统。

一台机器每秒可以处理的请求数 = 可用线程数 * 每个线程每秒处理请求数;但即使该Java程序处理一个请求需要0.01ms,能扛多少请求还需考虑:内存能抗多少、CPU能支撑多少线程、网卡流量多大的负载能打满等,综合这些因素才能得出一台机器究竟能扛多少请求。

一般的机器配置,如果Java程序不依赖数据库只是请求处理,那么每个请求处理只需要0.01ms,此时每秒还是可以扛上万请求的。

总之,一台机器到底可以每秒抗下多少并发请求,跟CPU、内存、磁盘IO、网络带宽都有关系。

(2)如何区分QPS和TPS

一个交易系统会拆分很多服务。对于单个服务来说,每秒处理请求数量就是QPS。对于整个交易系统来说一次交易请求需要调用多个服务,那么其每秒处理完这些服务的的交易笔数则是TPS。

8.sysbench是非常好用的数据库压测工具

(1)sysbench的用途

(2)在Linux安装sysbench工具

(3)数据库压测的测试用例

(4)基于sysbench构造测试表和测试数据

(5)对数据库进行360度全方位测试

(6)压测结果分析

(1)sysbench的用途

可以在数据库里自动构造出大量的数据,可以模拟几千个线程并发访问数据库,可以模拟使用各种SQL语句来访问数据库,可以模拟出各种事务提交到数据库里,可以模拟出几十万的TPS去压测数据库。

(2)在Linux安装sysbench工具

先设置yum repo仓库,接着基于yum来安装sysbench即可;

$ curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
$ sudo yum -y install sysbench
$ sysbench --version

(3)数据库压测的测试用例

接着需要在数据库里创建好一个测试库,可以取名为test_db。同时创建好对应的测试账号,可以叫test_user。然后要基于sysbench构建20个测试表,每个表里有100万条数据。接着使用10个并发线程去对这个数据库发起访问,连续访问5分钟。

(4)基于sysbench构造测试表和测试数据

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_read_write --db-ps-mode=disable prepare

上面构造了一个sysbench命令,加入了很多参数,下面是这些参数解释:

1.--db-driver=mysql:意思是基于mysql的驱动去连接mysql数据库,这里可以选oracle、sqlserver等
2.--time=300:意思是连续访问300秒
3.--threads=10:意思是用10个线程模拟并发访问
4.--report-interval=1:意思是每隔1秒输出一下压测情况
5.--mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=test_user --mysql-password=test_user:意思是连接到哪台机器的哪个端口上的MySQL库
6.--mysql-db=test_db --tables=20 --table_size=1000000:意思是在test_db这个库里,构造20个测试表,每个测试表里构造100万条测试数据,测试表的名字将类似于sbtest1、sbtest2
7.oltp_read_write:意思是执行oltp数据库的读写测试
8.--db-ps-mode=disable:意思是禁止ps模式
9.prepare:意思是参照这个命令的设置去构造出我们需要的数据库里的数据,它会自动创建20个测试表,每个表里创建100万条测试数据

(5)对数据库进行360度全方位测试

a.测试数据库的综合读写TPS,使用oltp_read_write模式。命令中最后不是prepare而是run,代表的就是运行压测:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_read_write --db-ps-mode=disable run

b.测试数据库的只读性能,使用oltp_read_only模式。命令中的oltp_read_write已经变成oltp_read_only了:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_read_only --db-ps-mode=disable run

c.测试数据库的删除性能,使用oltp_delete模式:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_delete --db-ps-mode=disable run

d.测试数据库的更新索引字段的性能,使用oltp_update_index模式:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_update_index --db-ps-mode=disable run

e.测试数据库更新非索引字段的性能,使用oltp_update_non_index模式:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_update_non_index --db-ps-mode=disable run

f.测试数据库的插入性能,使用oltp_insert模式:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_insert --db-ps-mode=disable run

g.测试数据库的写入性能,使用的是oltp_write_only模式:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_write_only --db-ps-mode=disable run

使用上面的命令,sysbench工具会构造出各种各样的SQL语句,然后根据这些SQL语句去更新或者查询20张测试表里的数据,同时检测出数据库的压测性能指标,最后完成压测后可以执行下面的cleanup命令进行清理数据:

$ sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 \
--mysql-port=3306 --mysql-user=test_user --mysql-password=test_user --mysql-db=test_db --tables=20 \
--table_size=1000000 oltp_read_write --db-ps-mode=disable cleanup

(6)压测结果分析

按照上面的命令,让sysbench每隔1秒输出一次压测报告,此时每秒输出类似如下的数据:

[22s] thds:10 tps:380.99 qps:7312.66 (r/w/o:5132.99/1155.86/1321.55) lat(ms,95%):21.33 err/s:0.00 reconn/s:0.00

该输出的意思是:这是第22s输出的一段压测统计报告,后面是具体的统计字段:

1.thds: 10,意思是有10个线程在压测
2.tps:380.99,意思是每秒执行了380.99个事务
3.qps:7312.66,意思是每秒可以执行7612.66个请求
4.(r/w/o:5132.99/1155.86/1321.55),意思是每秒7612.66个请求中,有5132.99个请求是读请求,1155.86个请求是写请求,1321.55个请求是其他请求
5.lat(ms,95%):21.33,意思是95%的请求的延迟都在21.33毫秒以下
6.err/s:0.00 reconn/s:0.00,意思是每秒有0个请求是失败的,每秒发生了0次网络重连

完成压测后,最后会显示一个总的压测报告,如下:

SQL statistics:
    queries performed:
        read:1480084 //意思是在300s的压测期间执行了148万多次的读请求
        write:298457 //意思是在压测期间执行了29万多次的写请求
        other:325436 //意思是压测期间执行了32万多次的其他请求
        total:2103977 //意思是一共执行了210万多次的请求
    transactions:105180 (350.6 per sec.) //意思是一共执行了10万多个事务,每秒执行350多个事务
    queries:2103977 (7013.26 per sec.) //意思是一共执行了210万多次的请求,每秒执行7000+请求
    ignored errors: 0 (0.00 per sec.)
    reconnects: 0 (0.00 per sec.)
//下面的意思是一共执行了300s压测,执行了10万+的事务
General saticstics:
    total time:300.0052s
    total number of events:105180
Latency(ms):
    min:4.32 //请求中延迟最小的是4.32ms
    avg:13.42 //所有请求平均延迟是13.42ms
    max:45.66 //延迟最大的请求是45.56ms
    95th percentile:21.33 //95%的请求延迟都在21.33ms以内

9.压测中除了QPS和TPS外还要观察机器性能

上面例子使用了10个线程去压测数据库。如果机器的性能很高,10个线程是没法压测出数据库的最高负载能力的。可以在sysbench中不停的增加线程的数量,比如使用20个线程,甚至100个线程去并发的访问数据库,直到发现数据库的QPS和TPS上不去。

当然,不停地提高线程数,让数据库不停地承载更高的QPS的过程,还需要配合对机器性能表现的观察来做,不能盲目增加线程。

为什么在不停增加线程数量的时候,要密切关注机器性能?首先假设数据库当前抗下了每秒2000的QPS,同时这时CPU负载、内存负载、网络负载、磁盘IO负载,都在正常范围。负载相对较高一些,但是还没有达到这些硬件的极限,那么可认为这台数据库在高峰期能抗每秒2000QPS。

但如果一直不停的在压测过程中增加sysbench的线程数量,然后数据库此时勉强抗到了每秒5000的QPS了。但这时发现机器CPU已满负荷运行、内存使用率特别高、内存快耗尽,然后网络带宽几乎被打满、磁盘IO的等待时间特别长,那么这时就说明机器已到了极致了。所以这时压测出的5000QPS是没什么代表性的,因为在生产环境根本不可能让数据库抗下这么高的QPS,因为到这么高的QPS就说明数据库几乎已经快挂掉了,这是不现实的。

所以在压测的过程中:必须是不停增加sysbench的线程数量,持续让数据库承载更高的QPS,同时密切关注CPU、内存、磁盘和网络的负载。在硬件负载情况比较正常的范围内,哪怕负载相对较高一些,也还是可以继续增加线程数量和提高数据库的QPS的。

然后当不停增加线程数量,发现数据库可以抗下下一个QPS的数值时,机器的CPU、内存、网络和磁盘的负载已经比较高了,机器已经到了一个有一定风险的临界值了,那么此时就不能继续增加线程数量和提高数据库压测的QPS了。

10.压测时如何观察机器的CPU负载情况

先来看一个最常用的监测Linux机器性能的命令,就是top命令。在linux命令行输入top命令就会看到如下一行信息:

top - 15:52:00 up 42:35, 1 user, load average: 0.15, 0.05, 0.01

这行信息是最直观可以看到机器的CPU负载情况的:首先15:52:00指的是当前时间;up 42:35指的是机器已经运行了多长时间;1 user就是说当前机器有1个用户在使用;最重要的是load average: 0.15, 0.05, 0.01这行信息,这说的是CPU在1分钟、5分钟、15分钟内的负载情况。

CPU负载指(假设在4核CPU机器执行top命令):

一.如果CPU负载是0.15,则说明4核CPU中连一个核都没用满,4核CPU基本都很空闲没怎么使用;

二.如果CPU负载是1,则说明4核CPU中有一个核已被使用得比较繁忙,另外3个核还是比较空闲的;

三.如果CPU负载是1.5,说明有一个核被使用繁忙,另外一个核也在使用,但是没那么繁忙,此时还有2个核可能是空闲的;

四.如果CPU负载是4,那说明4核CPU都被跑满了;

五.如果CPU负载是6,那说明4核CPU被繁忙的使用还不够处理当前的任务,很多进程可能一直在等待CPU去执行自己的任务。

所以上面看到的load average实际上就是:CPU在最近1分钟5分钟15分钟内的平均负载数值。

上面看到的负载是0.15,说明CPU根本没怎么用。如果压测过程中发现4核CPU的load average已经达到3.5或者4了,则说明CPU基本都跑满了,已经在满负荷运转了。此时就不要再继续提高线程的数量和增加数据库的QPS了。

11.压测时如何观察机器的内存负载情况

在执行top命令后,中间跳过几行内容,可以看到如下一行内容:

Mem: 33554432k total, 20971520k used, 12268339 free, 307200k buffers

这说的就是当前机器的内存使用情况:总内存有32G,已使用20G内存,还有10多G内存是空闲的,有大概300MB左右的内存用作OS内核的缓冲区。

对于内存而言,同样要在压测的过程中紧密观察。如果内存的使用率在80%以内,基本都还能接受,在正常范围内。但是如果机器的内存使用率到了70%~80%了,就说明有点危险了。此时就不要继续增加压测的线程数量和QPS了,差不多就可以了。

12.压测时如何观察机器的磁盘IO情况

可用dstat命令查看存储的IO吞吐量、IOPS等信息。

一.使用命令:dstat -d,会看到如下的信息:

-dsk/total -
read writ
103k 211k
  0   11k

在上面可以清晰看到:存储的IO吞吐量是每秒钟读取103KB的数据,每秒写入211KB的数据。像这个存储IO吞吐量基本上都不算多的,因为普通的机械硬盘都可以做到每秒钟上百MB的读写数据量。

二.使用命令:dstat -r,可以看到如下的信息:

--io/total-
read writ
0.25 31.9
  0   253
  0   39.0

这个意思就是读IOPS和写IOPS分别是多少。也就是说随机磁盘读取每秒钟多少次,随机磁盘写入每秒钟执行多少次。

一般来说,随机磁盘读写每秒在两三百次都是可以承受的。所以在这里就需要在压测的时候密切观察机器的磁盘IO情况:如果磁盘IO吞吐量已经太高了,都达到极限的每秒上百MB的磁盘IO了,或者随机磁盘读写每秒都到极限的两三百次IOPS了,此时就不要继续增加线程数量了,否则磁盘IO负载就太高了;

13.压测时观察网卡的流量情况

可以使用命令:dstat -n,查看网卡流量信息:

-net/total-
recv send
16k  17k

这个说的就是:每秒钟网卡接收到的流量有多少KB;每秒钟通过网卡发送出去的流量有多少KB。

如果机器使用的是千兆网卡,那么每秒网卡的总流量也就在100MB左右,在压测时也要观察网卡的流量。如果网卡传输流量已到极限值,那么此时再怎么提高sysbench线程数量,数据库的QPS也上不去,因为这台机器每秒已无法通过网卡传输更多的数据。

14.使用sysbench压测数据库总结

在数据库压测的过程中,必须不停的增加sysbench的线程数量,测试数据库能抗下的QPS。同时通过各种命令观察机器的CPU、内存、磁盘和网络的负载情况。如果发现某个硬件负载已经很高,此时就可以不再提高数据库的QPS。

在硬件的合理负载范围内,把数据库的QPS提高到最大。这就是数据库压测时最合理的一个极限QPS值。而不是不管机器的各个硬件的负载,盲目增加sysbench的线程数量。

CPU负载:top

内存负载:top下的Mem

磁盘IO吞吐量:dstat -d (每秒上百MB)

磁盘IOPS:dstat -r (每秒两三百)

网卡流量:dstat -n (千兆网卡每秒100MB左右)

#牛客创作赏金赛#
MySQL底层原理与应用 文章被收录于专栏

MySQL底层原理与应用

全部评论

相关推荐

CDN代表内容分发网络(Content Delivery Network)。它是由位于全球各地的服务器组成的网络,旨在提供高速和可靠的内容传递服务。使用CDN加速网站访问的主要原理是将网站的静态资源(如图片、CSS和JavaScript文件)复制到CDN的服务器上,并将这些资源分布到全球各个位置的边缘节点。当用户请求访问网站时,CDN会根据用户的位置选择最近的边缘节点,并将资源从最近的节点传递给用户,从而加快内容传递速度。要使用CDN来加速网站的访问,您可以按照以下步骤进行:https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mg58Em&uuid=b48bebe08e474db8b80b853b12bafd48选择CDN提供商:有许多CDN提供商可供选择,如Akamai、Cloudflare、Fastly等。根据您的需求和预算选择一个合适的CDN提供商。配置CDN:注册并配置CDN服务。这包括添加您的网站域名,并将CDN提供商提供的DNS设置应用到您的域名上。设置缓存规则:通过CDN提供商的控制面板,您可以设置缓存规则,例如缓存时间、缓存行为等。根据您的网站需求进行调整,以达到最佳的缓存效果。将静态资源上传到CDN:将网站的静态资源(如图片、CSS和JavaScript文件)上传到CDN的服务器上。这可以通过CDN提供商提供的API、FTP或其他实用工具进行。测试和优化:确保设置正确并经过测试。根据实际情况进行优化,例如调整缓存规则、删除不必要的资源等。使用CDN可以显著提高网站的访问速度和性能,特别是对于全球范围的访问。它通过减少距离和优化传输路径,将内容更快地传递给用户。
点赞 评论 收藏
分享
点赞 2 评论
分享
牛客网
牛客企业服务