全方位数据库性能压测

  一般我们的java应用系统都是部署在4核8g的服务器上,每秒大概能抗住几百个请求左右。而我们通常都是java程序读取mysql数据,经过逻辑处理后响应到页面。所以很大程度上,mysql的性能直接影响了我们的系统能承载多大的并发量。一般数据库都是选择8核16g起步,每秒1~2000并发没问题;甚至是16核32G的机器更加合适一些,每秒2~3000、3~4000也是可以的。因为数据库对CPU、磁盘、IO、内存的要求比较很高。

TPS

安装sysbench

  我们在规划数据库服务器配置的时候,可以做个压测。就是sysbench,这个工具可以自动帮你在数据库里构造出来大量的数据,你想要多少数据,他就自动给你构造出来多少条数据。

1.  curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
2.  sudo yum -y install sysbench
3.  sysbench --version
  如过可以看到 sysbench 的版本号就是安装成功了,然后我们可以开始构造测试表和测试数据。我这里先创建好了一个test库,账号密码root/123456;现在是让sysbench生成20张表,每个表有100万条数据,然后用10个线程去并发连续访问300秒。
[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


测试数据库的只读性能,使用的是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=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_read_only --db-ps-mode=disable run
测试数据库的写入性能,使用的是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=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_write_only --db-ps-mode=disable run
测试数据库的删除性能,使用的是oltp_delete模式
  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_delete --db-ps-mode=disable run
测试数据库的更新索引字段性能,使用的是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=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_update_index --db-ps-mode=disable run
测试数据库的更新非索引字段性能,使用的是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=root --mysql-password=123456 --mysql-db=test --tables=20 --table_size=1000000 oltp_update_non_index --db-ps-mode=disable run
测试数据库的插入性能,使用的是oltp_insert模式
  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_insert --db-ps-mode=disable run
cleanup命令,可以清空之前的所有数据
  sysbench --db-driver=mysql --time=30 --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_write_only --db-ps-mode=disable cleanup

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

全方位数据库性能压测

我们这里讨论的是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

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这个水平。

  全方位数据库性能压测

内存负载

  全方位数据库性能压测

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都很正常,

全方位数据库性能压测

全方位数据库性能压测

上一篇:LevelDB基于LSM Tree的相关设计


下一篇:mysql 中 group by 用法