Mycat對於導入和擴容遷移性能壓測

Mycat對於導入和擴容遷移性能壓測

1.      測試環境

wKioL1ZvZwDwviMxAAB7IE8flZs787.png

 

1.1.    硬件環境

機器ip

OS

CPU

CPU Processors

內存

172.16.54.135

CentOS Linux release 7.1.1503

Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz

24

64G

172.16.54.136

CentOS Linux release 7.1.1503

Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz

24

64G

172.16.54.138

CentOS Linux release 7.1.1503

Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz

24

64G

1.2.    軟件環境

軟件名稱

版本

Jdk

1.8.0_45

Mycat

1.4.1

Mysql

5.6

PostgreSQL

9.2.14





 

2.      對於Mysql壓測

2.1.    基本配置

  • wrapper.conf

# Java AdditionalParameters
#wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
wrapper.java.additional.5=-XX:MaxDirectMemorySize=5G
wrapper.java.additional.6=-Dcom.sun.management.jmxremote
wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984
wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false
# Initial JavaHeap Size (in MB)
#wrapper.java.initmemory=3
wrapper.java.initmemory=3072
# Maximum JavaHeap Size (in MB)
#wrapper.java.maxmemory=64
wrapper.java.maxmemory=3072
  • schema.xml

<schemaname="testdb" checkSQLschema="false"sqlMaxLimit="100">
                <table name="user"dataNode="dn1,dn2" rule="mod-long"/>
        </schema>
        <dataNode name="dn1"dataHost="mycat" database="db1"/>
        <dataNode name="dn2"dataHost="mycat2" database="db1"/>
 
        <dataHost name="mycat"maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native"
                       switchType="1">
                <heartbeat>selectuser()</heartbeat>
                <writeHosthost="host1" url="dev-2:3306" user="test"password="test"/>
        </dataHost>
         <dataHost name="mycat2"maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native"
                        switchType="1">
                <heartbeat>selectuser()</heartbeat>
                <writeHosthost="host2" url="dev-3:3306" user="test"password="test"/>
        </dataHost>
  • 數據庫腳本

create databasedb1;
create tabledb1.user(id int, user_name varchar(20), email varchar(20), phone varchar(20));

2.2.    導入方案

由於Mycat支持Mysql協議,所以Mycat對於Mysql數據導入方案有三種:

  1. jdbc直接進行insert操作

根據官網測試結果:在16核上insert性能可以達到12w/s

wKioL1ZvZwCw4pmjAABeMutFtcg198.png

本輪測試數據量200w,測試工具爲testtool.tar.gz。結論:tps8w

wKiom1ZvZvrC1jXAAACBEVY0qi0693.png

  1. mysqldump操作

mysqldump操作原理與insert相同,數據量100w,沒有預熱。結論tps3w

wKioL1ZvZwHS-xmqAAAW-FpTwYI295.png

  1. load data infile操作

官網說法:是insert性能的幾十倍,如下

wKiom1ZvZvuzObiNAAA3cGJ25lg440.png

wKiom1ZvZ6eTemSWAABGf8yqJlY022.png

Load data功能在1.4版本+支持,經過測試發現,如果導入數據量比較大(大於10w),則會出現文件找不到情況,官網羣中有人出現同樣問題,原因待查。

wKioL1ZvZwPx4QuMAAAbAYM8cNA420.png

根據其他人測試結果:loaddata local infile命令64M23萬條數據用到500M內存

wKioL1ZvZwTDu42jAACNVRp-IJE799.png


2.3.  擴容遷移方案

wKioL1ZvZwTwfTOJAAB7-eCzLLU474.png

schema db1遷移擴容到db2。由於mycql不支持自動擴容,所以需要手動進行rehash

wKiom1ZvZv6BWSsTAAB2lJESDaM822.png

目前方案有:

  1. 將數據導出本分,清空數據,通過上述導入方案的三種方式進行擴容遷移

性能結果如上測試

  1. 手動遷移(注意:此方案只適合單節點遷移):

  2. 1)        使用mycatRehashLauncher重新進行hash算法,得出rehashid列表

  3. 2)        mysql上使用mysqldump根據rehashid列表,導出數據

  4. 3)        mycatmysqldump,導入數據

  5. 4)        mysql上刪除遷移的數據

對於1)步驟,有2bug

  • 取得id值時錯誤

bug已經提交到mycate1.4mycat master分支,並已合併

wKiom1ZvZv-htqNWAAA-NGcWl6U492.png

  • hash後的host比較錯誤

bug已經提交到1.4分支,並已合併

wKiom1ZvaDfApeUmAAAxNFEbFKQ567.png

         對於2),3),4)步驟可以採用shell腳本自動運行,官網腳本如下:

# arg1=start, arg2=end, format: %s.%N  
function getTiming() {
    start=$1
    end=$2
 
    start_s=$(echo$start | cut -d '.' -f 1)
    start_ns=$(echo$start | cut -d '.' -f 2)
    end_s=$(echo $end |cut -d '.' -f 1)
    end_ns=$(echo $end |cut -d '.' -f 2)
 
    time=$(( ( 10#$end_s- 10#$start_s ) * 1000 + ( 10#$end_ns / 1000000 - 10#$start_ns / 1000000 ) ))
 
    echo "$timems"  
}
 
#rehash節點
rehashNode=$1
#mycat節點
expanNode=$2
#遷移數據
order_fn="$3"
 
#遷移數據庫
rehash_db=db1
#遷移表
rehash_table=user
 
#mysql配置
mysql_port=3306
mysql_user=test
mysql_pwd=test
 
#mycat配置
mycat_port=8066
mycat_user=mysql
mycat_pwd=123456
mycat_db=testdb
 
start=$(date +%s.%N)
 
if [ "$#" = "0" ]; then
echo "Please input parameter, for example:"
echo "ReRouter.sh 192.168.84.13 192.168.84.14/home/mycat/T_CMS_ORDER"
echo " "
exit
fi;
echo "需要進行遷移的主機總量爲:$#, 主機 IP 列表如下:"
for i in "$@"
do
echo "$i"
done
echo " "
#取出 rehash 需要的 SerNum(已經用 in 拼接好)
for n in `cat $order_fn`
do
condOrder=$n
done
 
echo "************* 導出 *************"
date
# 1) 首先調用 mysqldump 進行數據導出
echo "開始導出主機:$ 表:T_CMS_ORDER."
mysqldump -h$rehashNode -P$mysql_port -u$mysql_user-p$mysql_pwd $rehash_db $rehash_table --default-characterset=utf8 --extende
d-insert=false --no-create-info --add-locks=false--completeinsert --where=" id in $condOrder " >./T_CMS_ORDER_temp.sql
echo "導出結束."
echo " "
 
echo "************* 導入 *************"
date
# 2) 調用 mycat 接口進行數據導入
echo "開始導入 T_CMS_ORDER 表數據"
mysql -h$expanNode -P$mycat_port -u$mycat_user -p$mycat_pwd$mycat_db --default-character-set=utf8 < ./T_CMS_ORDER_temp.sql
echo "導入結束."
echo " "
 
echo "************* 刪除數據 *************"
date
# 3) 當前兩步都無誤的情況下,刪除最初的導出數據.
echo "開始刪除已導出的數據表:."
mysql -h$rehashNode -Pmycat_port -u$mysql_user-p$mysql_pwd  -e "use $rehash_db;DELETE FROM $rehash_table
WHERE id in $condOrder ; commit; "
echo "刪除結束."
echo " "
echo "************* 清空臨時文件 *************"
date
# 4) 清空臨時文件
rm ./T_CMS_ORDER_temp.sql
echo "清空臨時文件"
echo "#####################主機:$rehashNode 處理完成#####################"
date
echo " "
 
echo "ReHash 運行完畢."
 
end=$(date +%s.%N)
getTiming $start $end

此腳本運行1)執行的文件,會報如下錯誤:

wKioL1Zva9mQSFCkAAAvmFent5g921.png


這是由於1)會一次性根據id列表,採用in語句查詢出所有數據,當數據量過大時,報錯。本輪測試採用優化方案:

  • 1)步驟每1w爲一行

RehashLauncher代碼如下:

public class RehashLauncher {
    private final class RehashRunner implements Runnable {
        private final File   output;
        private final String table;
        
        private RehashRunner(File output, String table) {
            this.output = output;
            this.table = table;
        }
        
        public void run(){
            int pageSize=500;
            int page=0;
            List<Map<String, Object>> list=null;
            
            int total=0;
            int rehashed=0;
            String hostWithDatabase=args.getHostWithDatabase();
            
            PrintStream ps=null;
            try {
                ps=new PrintStream(output);
                StringBuilder rehashData = new StringBuilder();
                list = JdbcUtils.executeQuery(dataSource, "select "
                    + args.getShardingField() + " from " + table + " limit ?,?", page++ * pageSize,
                    pageSize);
                while (!CollectionUtil.isEmpty(list)) {
                    for(int i=0,l=list.size();i<l;i++){
                        Map<String, Object> sf=list.get(i);
                        Integer hash=alg.calculate(sf.get(args.getShardingField()).toString());
                        String host=rehashHosts[hash];
                        total++;
                        if(!host.equals(hostWithDatabase)){
                            rehashed++;
                            rehashData.append(sf.get(args.getShardingField())).append(",");
                            if(rehashed % 10000 == 0){
                                ps.println("(" + rehashData.substring(0, rehashData.length() - 1) + ")");
                                rehashData.delete(0, rehashData.length());
                            }
                            
                        }
//                        ps.println(sf+"=>"+host);
                    }
                    
                    list = JdbcUtils.executeQuery(dataSource, "select "
                        + args.getShardingField() + " from " + table + " limit ?,?", page++ * pageSize,
                        pageSize);
                }
                if(rehashData.length() >= 1){
                    ps.println("(" + rehashData.deleteCharAt(rehashData.length() - 1) + ")");
                }
//                ps.println("rehashed ratio:"+(((double)rehashed)/total));
            } catch (Exception e) {
                throw new RehashException(e);
            }finally{
                if(ps!=null){
                    ps.close();
                }
                latch.countDown();
            }
        }
    }

program argument:

-jdbcDriver=com.mysql.jdbc.Driver -jdbcUrl=jdbc:mysql://172.16.54.136:3306/db1 -host=172.16.54.136:3306 -user=test -database=db1 -password=test -tablesFile=F:/certusnetSVN/books/mycat/rehash\tables.txt -shardingField=id -rehashHostsFile=F:/certusnetSVN/books/mycat/rehash/hosts.txt -hashType=mod -rehashNodeDir=F:/certusnetSVN/books/mycat/rehash/tmp

hosts.txt配置:

172.16.54.136:3306/db1
172.16.54.138:3306/db1
172.16.54.136:3306/db2
172.16.54.138:3306/db2

tables.txt配置:

user
  • 2),3),4)腳本改爲shell多線程,每次處理一行的方案

腳本如下:

# arg1=start, arg2=end, format: %s.%N  
function getTiming() {
    start=$1
    end=$2

    start_s=$(echo $start | cut -d '.' -f 1)
    start_ns=$(echo $start | cut -d '.' -f 2)
    end_s=$(echo $end | cut -d '.' -f 1)
    end_ns=$(echo $end | cut -d '.' -f 2)

    time=$(( ( 10#$end_s - 10#$start_s ) * 1000 + ( 10#$end_ns / 1000000 - 10#$start_ns / 1000000 ) ))

    echo "$time ms"  
}

#rehash節點
rehashNode=$1
#mycat節點
expanNode=$2
#遷移數據
order_fn="$3"

#遷移數據庫
rehash_db=db1
#遷移表
rehash_table=user

#mysql配置
mysql_port=3306
mysql_user=test
mysql_pwd=test

#mycat配置
mycat_port=8066
mycat_user=mysql
mycat_pwd=123456
mycat_db=testdb

total_start=$(date +%s.%N)

if [ "$#" = "0" ]; then
echo "Please input parameter, for example:"
echo "ReRouter.sh 192.168.84.13 192.168.84.14 /home/mycat/T_CMS_ORDER"
echo " "
exit
fi;
echo "需要進行遷移的主機總量爲:$#, 主機 IP 列表如下:"
for i in "$@"
do
echo "$i"
done
echo " "
#取出 rehash 需要的 SerNum(已經用 in 拼接好)
while read condOrder
do
{
file_id=${condOrder:3:10}
echo "************* 導出 *************"
date
# 1) 首先調用 mysqldump 進行數據導出
echo "開始導出主機:$ 表:T_CMS_ORDER."
mysqldump -h$rehashNode -P$mysql_port -u$mysql_user -p$mysql_pwd $rehash_db $rehash_table --no-create-info --skip-add-locks -c
--where=" id in $condOrder " > ./T_CMS_ORDER_$file_id.sql
echo "導出結束."
echo " "

echo "************* 導入 *************"
date
# 2) 調用 mycat 接口進行數據導入
echo "開始導入 T_CMS_ORDER 表數據"
mysql -h$expanNode -P$mycat_port -u$mycat_user -p$mycat_pwd -D$mycat_db < ./T_CMS_ORDER_$file_id.sql
echo "導入結束."
echo " "

echo "************* 刪除數據 *************"
date
# 3) 當前兩步都無誤的情況下,刪除最初的導出數據.
echo "開始刪除已導出的數據表:."
mysql -h$rehashNode -Pmycat_port -u$mysql_user -p$mysql_pwd  -e "use $rehash_db; DELETE FROM $rehash_table
WHERE id in $condOrder ; commit; "
echo "刪除結束."
echo " "
echo "************* 清空臨時文件 *************"
date
# 4) 清空臨時文件
rm ./T_CMS_ORDER_$file_id.sql
echo "清空臨時文件"
echo "#####################主機:$rehashNode 處理完成#####################"
date
echo " "

echo "ReHash 運行完畢."
}&
done < $order_fn
wait

echo "操作總消耗時長:"
total_end=$(date +%s.%N)
getTiming $total_start $total_end

執行結果100w遷移,耗時約:20s

wKioL1ZvZwbhExwaAAAwL50Q7wo232.png

 

3.      對於postgresql壓測

wKiom1ZvZwDAkw_jAAB8NX2cyiU757.png

3.1.  基本配置

  • schema.xml

<schemaname="testdb" checkSQLschema="false"sqlMaxLimit="100">
                <tablename="user_test" dataNode="dn1,dn2"rule="mod-long"/>
        </schema>
        <dataNode name="dn1"dataHost="mycat" database="db1"/>
        <dataNode name="dn2"dataHost="mycat2" database="db1"/>
 
        <dataHost name="mycat"maxCon="1000" minCon="10" balance="0"writeType="0" dbType="postgresql" dbDriver="jdbc"
                        switchType="1">
                <heartbeat>select1</heartbeat>
                <writeHosthost="host1" url="jdbc:postgresql://dev-2:5432/db1"user="postgres" password="123456"/>
        </dataHost>
         <dataHost name="mycat2"maxCon="1000" minCon="10" balance="0"writeType="0" dbType="postgresql" dbDriver="jdbc"
                       switchType="1">
                <heartbeat>select1</heartbeat>
                <writeHosthost="host2" url="jdbc:postgresql://dev-3:5432/db1"user="postgres" password="123456"/>
        </dataHost>
  • postgresql.conf

shared_buffers = 128MB
max_connections = 1000
fsync = off
wal_buffers = -1
commit_delay = 10000
commit_siblings = 500
  • 數據庫腳本

create databasedb1;
create table user_test(idint, user_name varchar(20), email varchar(20), phone varchar(20));

3.2.  導入方案

Mycat對於postgresql的導入方案只有一種,採用jdbcinsert方式。

本輪測試數據量100w,測試工具爲testtool.tar.gz。結論:tps6w

wKioL1ZvZwiiP_0UAABiX6N-04s151.png

 

3.3.  擴容遷移方案

對於postgresql遷移,也只能採用編程程序的方式進行,方案可以參考mysql遷移方案,此輪不再測試。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章