全方位数据库性能压测
一般我们的java应用系统都是部署在4核8g的服务器上,每秒大概能抗住几百个请求左右。而我们通常都是java程序读取mysql数据,经过逻辑处理后响应到页面。所以很大程度上,mysql的性能直接影响了我们的系统能承载多大的并发量。一般数据库都是选择8核16g起步,每秒1~2000并发没问题;甚至是16核32G的机器更加合适一些,每秒2~3000、3~4000也是可以的。因为数据库对CPU、磁盘、IO、内存的要求比较很高。
TPS
安装sysbench
我们在规划数据库服务器配置的时候,可以做个压测。就是sysbench,这个工具可以自动帮你在数据库里构造出来大量的数据,你想要多少数据,他就自动给你构造出来多少条数据。
[root@localhost wulei]# sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_read_write --db-ps-mode=disable prepare sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2) Initializing worker threads... Creating table 'sbtest5'... Creating table 'sbtest6'... Creating table 'sbtest1'... Creating table 'sbtest2'... Creating table 'sbtest3'... .... 中间的就省略了 Creating a secondary index on 'sbtest17'... Creating a secondary index on 'sbtest15'... Creating a secondary index on 'sbtest19'... Creating a secondary index on 'sbtest18'... Creating a secondary index on 'sbtest12'... [root@localhost wulei]#
--db-driver=mysql: 这个很简单,就是说他基于mysql的驱动去连接mysql数据库,你要是oracle,或者sqlserver,那自然就是其他的数据库的驱动了
--time=300: 这个就是说连续访问300秒
--threads=10: 这个就是说用10个线程模拟并发访问
--report-interval=1: 这个就是说每隔1秒输出一下压测情况
--mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password=root:这一大串,就是说连接到哪台机器的哪个端口上的MySQL库,他的用户名和密码是什么
--mysql-db=test --tables=20 --table_size=1000000:这一串的意思,就是说在test这个库里,构造20个测试表,每个测试表里构造100万条测试数据,测试表的名字会是类似于sbtest1,sbtest2这个样子的
oltp_read_write: 这个就是说,执行oltp数据库的读写测试
--db-ps-mode=disable:这个就是禁止ps模式
prepare: 意思是参照这个命令的设置去构造出来我们需要的数据库里的数据。
性能测试
测试数据库的综合读写TPS,使用的是oltp_read_write模式(把最后的prepare替换成run了,就是运行压测了)
[root@localhost wulei]# sysbench --db-driver=mysql --time=300 --threads=10 --report-interval=1 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_read_write --db-ps-mode=disable run sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2) Running the test with following options: Number of threads: 10 Report intermediate results every 1 second(s) Initializing random number generator from current time Initializing worker threads... Threads started! [ 1s ] thds: 10 tps: 13.88 qps: 419.43 (r/w/o: 318.29/63.46/37.68) lat (ms,95%): 733.00 err/s: 0.00 reconn/s: 0.00 [ 2s ] thds: 10 tps: 48.16 qps: 965.27 (r/w/o: 678.30/190.65/96.33) lat (ms,95%): 530.08 err/s: 0.00 reconn/s: 0.00 [ 3s ] thds: 10 tps: 63.06 qps: 1255.12 (r/w/o: 873.78/255.23/126.11) lat (ms,95%): 240.02 err/s: 0.00 reconn/s: 0.00 [ 4s ] thds: 10 tps: 57.03 qps: 1136.56 (r/w/o: 800.39/222.11/114.06) lat (ms,95%): 272.27 err/s: 0.00 reconn/s: 0.00 .... 中间的就省略了 [ 297s ] thds: 10 tps: 76.97 qps: 1520.32 (r/w/o: 1062.52/303.86/153.93) lat (ms,95%): 215.44 err/s: 0.00 reconn/s: 0.00 [ 298s ] thds: 10 tps: 90.10 qps: 1787.89 (r/w/o: 1247.32/360.38/180.19) lat (ms,95%): 167.44 err/s: 0.00 reconn/s: 0.00 [ 299s ] thds: 10 tps: 85.66 qps: 1738.11 (r/w/o: 1218.17/348.62/171.32) lat (ms,95%): 193.38 err/s: 0.00 reconn/s: 0.00 [ 300s ] thds: 10 tps: 82.30 qps: 1631.02 (r/w/o: 1143.22/323.19/164.61) lat (ms,95%): 207.82 err/s: 0.00 reconn/s: 0.00 SQL statistics: queries performed: read: 331828 write: 94808 other: 47404 total: 474040 transactions: 23702 (78.97 per sec.) queries: 474040 (1579.41 per sec.) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) General statistics: total time: 300.1342s total number of events: 23702 Latency (ms): min: 4.66 avg: 126.60 max: 734.88 95th percentile: 215.44 sum: 3000611.67 Threads fairness: events (avg/stddev): 2370.2000/17.62 execution time (avg/stddev): 300.0612/0.04 [root@localhost wulei]#
-------------------- 压测结果分析 -------------------
[ 298s ] thds: 10 tps: 90.10 qps: 1787.89 (r/w/o: 1247.32/360.38/180.19) lat (ms,95%): 167.44 err/s: 0.00 reconn/s: 0.00
[ 298s ] 表示第298s输出的一些统计信息
thds: 10 表示有10个线程在压测
tps: 90.10 表示每秒执行了90.1个事务
qps: 1787.89 表示每秒可执行1787.89个请求
(r/w/o: 1247.32/360.38/180.19) 表示每秒1787.89个请求中,有1247.32个读请求、360.38个写请求、180.19个其它请求。
lat (ms,95%): 167.44 表示95%的请求,都延迟在167毫秒以内
err/s: 0.00 reconn/s: 0.00 表示每秒0个请求失败,发生了0次网络重连
SQL statistics:
queries performed:
read: 331828 // 表示300s内执行了33.1828w次读请求
write: 94808 // 表示执行了9.4808w次写请求
other: 47404 // 表示执行了4.7404w次其它请求
total: 474040 // 压测期间执行的总请求次数
transactions: 23702 (78.97 per sec.) // 一共执行了2.3702w个事务,每秒78.97个事务
queries: 474040 (1579.41 per sec.) // 一共47.404w个请求,每秒1579.41个请求
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
// 300s的压测时间内,一共执行了23702个事务
General statistics:
total time: 300.1342s
total number of events: 23702
Latency (ms):
min: 4.66 // 请求最小延迟为4.66毫秒
avg: 126.60 // 平均延迟126毫秒
max: 734.88 // 最大延迟734毫秒
95th percentile: 215.44 // 95%请求延迟在215毫秒以内
sum: 3000611.67
Threads fairness:
events (avg/stddev): 2370.2000/17.62
execution time (avg/stddev): 300.0612/0.04
CPU负载
实际上压测效果一定是要基于服务器本身性能而言的,qps和tps并不是唯一指标。比如服务器性能比较好,10条线程根本没法测出数据库真实最高负载能力,我们需要在硬件负载比较正常的情况下慢慢加大我们的线程数。
如何看CPU核数
# CPU 个数 cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l # 核数 cat /proc/cpuinfo | grep "core id" | sort | uniq | wc -l # 线程 cat /proc/cpuinfo | grep "processor" | sort | uniq | wc -l 也可以直接lscpu
TOP
top - 20:28:35 up 4:37, 6 users, load average: 6.03, 2.07, 0.77
top - 20:28:35 表示当前系统时间
up 4:37 指的是机器已经运行了多长时间,
6 user 就是说当前机器有6个用户在使用
load average: 6.03, 2.07, 0.77 描述的是CPU在1分钟、5分钟、15分钟内的负载情况
比如4核的cpu,负载是1.5就表示一个核被使用繁忙、另一个也在使用,还剩两个处于空闲;如果负载是4,那说明4核CPU都被跑满了;如果负载是6,那说明4核CPU被繁忙的使用还不够处理当前的任务,很多进程可能一直在等待CPU。一般cpu负载70~80%是比较正常的,也就是说4*0.8=3.2这才是我的正常负载水平。而我现在修改为3条线程之后压测之后,CPU负载在维持在2.9~3.2这个水平。
我们这里讨论的是cpu负载,不是cpu占用率,下面这行表示得才是cpu占用率,两点是有区别的哦
%Cpu(s): 0.9 us, 1.8 sy, 0.0 ni, 96.3 id, 0.2 wa, 0.0 hi, 0.8 si, 0.0 st
内存负载
KiB Mem : 1867292 total, 68976 free, 468228 used, 1330088 buff/cache
内存情况
1867292 total, 内存总量(1.8GB)
68976 free, 空闲内存总量(0.038GB)
468228 used, 使用中的内存总量(0.45GB)
1330088 buff/cache 缓存的内存量 (1.29GB)
内存使用率: used/ total 一般在70~80%就差不多了,不要再增加压测力度了。
磁盘io、流量
这些数值会随系统配置而有很大的不同,依测试者在测试时的控制变因而异,控制变因包括读取及写入的比例、其中循序访问及随机存取的比例及配置方式、线程数量及访问队列深度,以及数据区块的大小。现在一般的盘吞吐量上百MB,每秒几百的iops都很正常,
。