1. 程式人生 > >mysql+mycat壓力測試一例

mysql+mycat壓力測試一例

mysql mycat sysbench

前言

有很多人擔心生產系統上新東西的程序怕壓力跟不上和穩定性不行,是的,大家都怕,所以領導要求做一次壓力測試,我個人也覺得是有必要的.

如果按原理來說,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壓力測試一例