1. 程式人生 > >Mycat之——讀寫分離與主從切換案例

Mycat之——讀寫分離與主從切換案例

一、環境準備

軟體版本:
作業系統:CentOS-6.5-x86_64-bin-DVD1.iso
JDK版本:jdk1.7.0_80
Mycat版本:Mycat-server-1.5.1-RELEASE-20170717215510-Linux.tar.gz (下載原始碼自行編譯的)
MySQL:5.6.32

二、安裝資料庫並配置主從複製

1、不同主機安裝資料庫

2、同一主機安裝多資料庫

這裡,再給大家介紹一種如何在同一主機上安裝多個MySQL資料庫,

2.1安裝主庫

tar -xvf mysql-5.6.32.tar.gz
cd mysql-5.6.32

time cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql3317 -DMYSQL_DATADIR=/home/data/mysql3317/data -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_UNIX_ADDR==/usr/local/mysql3317/mysql.sock -DMYSQL_USER=mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci

time make
time make install 

chown -R mysql /home/data/
chgrp -R mysql /home/data/
chown -R mysql /usr/local/mysql

chown -R mysql /usr/local/mysql3317
chgrp -R mysql /usr/local/mysql

chgrp -R mysql /usr/local/mysql3317/
mkdir -p /home/data/mysql3317/binlog/
chown -R mysql.mysql /home/data/mysql3317/binlog/
mkdir -p /home/data/mysql5610/binlog/
chown -R mysql.mysql /home/data/

cd /usr/local/mysql3317
time scripts/mysql_install_db  --user=mysql --basedir=/usr/local/mysql3317 --datadir=/home/data/mysql3317/data --defaults-file=/usr/local/mysql3317/my.cnf

cp support-files/mysql.server /etc/init.d/mysql3317
chmod 700 /etc/init.d/mysql3317
echo "export PATH=$PATH:/usr/local/mysql3317/bin">>/etc/profile 
source /etc/profile
chkconfig --add mysql3317

service mysql3317 start

2.2安裝從庫

tar -xvf mysql-5.6.32.tar.gz
cd mysql-5.6.32

time cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql3327 -DMYSQL_DATADIR=/home/data/mysql3327/data -DWITH_INNOBASE_STORAGE_ENGINE=1 -DMYSQL_UNIX_ADDR==/usr/local/mysql3327/mysql.sock -DMYSQL_USER=mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci

time make
time make install 


chown -R mysql /home/data/
chgrp -R mysql /home/data/
chown -R mysql /usr/local/mysql

chown -R mysql /usr/local/mysql3327
chgrp -R mysql /usr/local/mysql

chgrp -R mysql /usr/local/mysql3327/
mkdir -p /home/data/mysql3327/binlog/
chown -R mysql.mysql /home/data/mysql3327/binlog/
mkdir -p /home/data/mysql5610/binlog/
chown -R mysql.mysql /home/data/


cd /usr/local/mysql3327
time scripts/mysql_install_db  --user=mysql --basedir=/usr/local/mysql3327 --datadir=/home/data/mysql3327/data --defaults-file=/usr/local/mysql3327/my.cnf

cp support-files/mysql.server /etc/init.d/mysql3327
chmod 700 /etc/init.d/mysql3327
echo "export PATH=$PATH:/usr/local/mysql3327/bin">>/etc/profile 
source /etc/profile
chkconfig --add mysql3327
service mysql3327 start
主從複製參見博文《MySQL之——主從複製的配置

三、安裝Mycat

將Mycat上傳到指定路徑並解壓。

四、資料同步測試

1、配置schema.xml

然後修改mycat的schema.xml:
balance為1:讓全部的readHost及備用的writeHost參與select的負載均衡。
switchType為2:基於MySQL主從同步的狀態決定是否切換。
heartbeat:主從切換的心跳語句必須為show slave status。


2、資料錄入

mysql> explain create table company(id int not null primary key,name varchar(100));
+-----------+---------------------------------------------------------------------+
| DATA_NODE | SQL                                                                 |
+-----------+---------------------------------------------------------------------+
| dn1       | create table company(id int not null primary key,name varchar(100)) |
| dn2       | create table company(id int not null primary key,name varchar(100)) |
| dn3       | create table company(id int not null primary key,name varchar(100)) |
+-----------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql> create table company(id int not null primary key,name varchar(100));
Query OK, 0 rows affected (0.01 sec)

mysql> explain  insert into company(id,name) values(1,'liuyazhuang');
+-----------+--------------------------------------------------+
| DATA_NODE | SQL                                              |
+-----------+--------------------------------------------------+
| dn1       | insert into company(id,name) values(1,'liuyazhuang') |
| dn2       | insert into company(id,name) values(1,'liuyazhuang') |
| dn3       | insert into company(id,name) values(1,'liuyazhuang') |
+-----------+--------------------------------------------------+
3 rows in set (0.10 sec)

mysql>  insert into company(id,name) values(1,'liuyazhuang');
Query OK, 1 row affected (0.00 sec)

mysql>

3、主庫驗證

[[email protected] logs]# /usr/local/mysql3317/bin/mysql -uroot -p -P3317 --socket=/usr/local/mysql3317/mysql.sock -e "select @@port;select * from db1.company";
Enter password: 
+--------+
| @@port |
+--------+
|   3317 |
+--------+
+----+---------+
| id | name    |
+----+---------+
|  1 | liuyazhuang |
+----+---------+
[[email protected] logs]#

4、從庫驗證

[[email protected] logs]# /usr/local/mysql3327/bin/mysql -uroot -p -P3327 --socket=/usr/local/mysql3327/mysql.sock -e "select @@port;select * from db1.company";
Enter password: 
+--------+
| @@port |
+--------+
|   3327 |
+--------+
+----+---------+
| id | name    |
+----+---------+
|  1 | liuyazhuang |
+----+---------+
[[email protected] logs]#

五、讀寫分離

1、修改mycat的schema.xml

balance為1:讓全部的readHost及備用的writeHost參與select的負載均衡。
switchType為2:基於mysql主從同步的狀態決定是否切換。
heartbeat:主從切換的心跳語句必須為show slave status。
並增加讀節點:

<readHost host="hostR1" url="127.0.0.1:3327" user="root" password="root"></readHost>
具體如下:
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
    writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">
    <heartbeat>show slave status</heartbeat>
    <writeHost host="hostM1" url="127.0.0.1:3317" user="root" password="root">
        <readHost host="hostR1" url="127.0.0.1:3327" user="root" password="root"></readHost>
    </writeHost>
    <writeHost host="hostS2" url="127.0.0.1:3327" user="root" password="root"></writeHost>
</dataHost>

2、開啟debug模式

開啟mycat下的log4j.xml檔案將

<level value="info" />
修改為
<level value="debug" />

3、執行查詢讀操作

mysql> explain select * from company where id=1;
+-----------+----------------------------------------------+
| DATA_NODE | SQL                                          |
+-----------+----------------------------------------------+
| dn3       | SELECT * FROM company WHERE id = 1 LIMIT 100 |
+-----------+----------------------------------------------+
1 row in set (0.14 sec)

mysql> select * from company where id=1;
+----+---------+
| id | name    |
+----+---------+
|  1 | liuyazhuang |
+----+---------+
1 row in set (0.01 sec)

mysql>
後臺日誌顯示出只在3327上執行:
07/18 01:35:01.536  DEBUG [$_NIOREACTOR-3-RW] (PhysicalDBPool.java:452) -select read source hostS2 for dataHost:wgq_idc_mon_1_11
07/18 01:35:01.537  DEBUG [$_NIOREACTOR-3-RW] (MySQLConnection.java:445) -con need syn ,total syn cmd 2 commands SET names latin1;SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;schema change:false con:MySQLConnection [id=14, lastTime=1453052101537, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=false, threadId=3326, charset=latin1, txIsolation=0, autocommit=true, attachment=dn1{SELECT *
FROM company
WHERE id = 1
LIMIT 100}, respHandler=SingleNodeHandler [node=dn1{SELECT *
FROM company
WHERE id = 1
LIMIT 100}, packetId=0], host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
07/18 01:35:01.546  DEBUG [$_NIOREACTOR-2-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=14, lastTime=1453052101529, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=false, threadId=3326, charset=latin1, txIsolation=3, autocommit=true, attachment=dn1{SELECT *
FROM company
WHERE id = 1
LIMIT 100}, respHandler=SingleNodeHandler [node=dn1{SELECT *
FROM company
WHERE id = 1
LIMIT 100}, packetId=5], host=127.0.0.1, port=3327, [email protected]fb43f0f, writeQueue=0, modifiedSQLExecuted=false]
07/18 01:35:01.547  DEBUG [$_NIOREACTOR-2-RW] (PhysicalDatasource.java:403) -release channel MySQLConnection [id=14, lastTime=1453052101529, user=root, schema=db1, old shema=db1, borrowed=true, fromSlaveDB=false, threadId=3326, charset=latin1, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]

4、執行寫操作

Mycat視窗寫操作:


後臺log顯示寫操作在3317上:

07/18 01:39:54.550  DEBUG [$_NIOREACTOR-3-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=7, lastTime=1453052394535, user=root, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=163, charset=latin1, txIsolation=3, autocommit=true, attachment=dn3{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:39:54.550  DEBUG [$_NIOREACTOR-3-RW] (PhysicalDatasource.java:403) -release channel MySQLConnection [id=7, lastTime=1453052394535, user=root, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=163, charset=latin1, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
07/18 01:39:54.550  DEBUG [$_NIOREACTOR-3-RW] (MultiNodeQueryHandler.java:171) -received ok response ,executeResponse:true from MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=dn2{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:39:54.551  DEBUG [$_NIOREACTOR-3-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=dn2{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:39:54.551  DEBUG [$_NIOREACTOR-3-RW] (PhysicalDatasource.java:403) -release channel MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]

六、主從切換

1、schema.xml配置如下

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
    writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">
    <heartbeat>show slave status</heartbeat>
    <writeHost host="hostM1" url="127.0.0.1:3317" user="root" password="root">
        <readHost host="hostR1" url="127.0.0.1:3327" user="root" password="root"></readHost>
    </writeHost>
    <writeHost host="hostS2" url="127.0.0.1:3327" user="root" password="root"></writeHost>
</dataHost>

2、關閉主庫,寫操作切換到從褲3327埠

[[email protected] conf]# service mysql3317 stop
Shutting down MySQL....                                    [確定]
[[email protected] conf]#
Mycat後臺報錯
07/18 01:50:01.037   INFO [Timer0] (PhysicalDatasource.java:373) -not ilde connection in pool,create new connection for hostM1 of schema db1
07/18 01:50:01.038   INFO [$_NIOConnector] (AbstractConnection.java:458) -close connection,reason:java.net.ConnectException: 拒絕連線 ,MySQLConnection [id=0, lastTime=1453053001035, user=root, schema=db1, old shema=db1, borrowed=false, fromSlaveDB=false, threadId=0, charset=utf8, txIsolation=0, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3317, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
07/18 01:50:01.038   INFO [$_NIOConnector] (SQLJob.java:111) -can't get connection for sql :show slave status
07/18 01:50:01.038   WARN [$_NIOREACTOR-1-RW] (MySQLDetector.java:139) -found MySQL master/slave Replication err !!! DBHostConfig [hostName=hostR1, url=127.0.0.1:3327]error reconnecting to master '[email protected]:3317' - retry-time: 60  retries: 1
0

看到主從失效,因為主down了。

因為我們通過mycat配置了主從切換模式,現在3317埠主庫down了,那麼寫庫應該自動切換到從褲3327上面,如果在mycat上面寫入,就應該寫到3327埠的從庫了,驗證如下:在Mycat視窗錄入資料,在3327從庫檢視資料,如果3327從庫有在Mycat視窗錄入的資料表明驗證成功。

而且此時,Mycat的dnindex屬性檔案中writeHost已經變成了第二個了

#update
#Tue Aug 08 22:13:41 CST 2017
localhost1=1
注意:Mycat的dnindex屬性檔案中writeHost順序是從0開始,即0代表第一個

3、啟動原來的3317主庫

再啟動原來的主庫3317埠,在mycat上做寫操作,後臺mysql寫庫還是原來的從庫3327埠:
這個時候就會報錯,主從連線失敗,原因是從庫3327會再重新從主庫3317同步所有的資料,但是從庫已經有了,所以就會報錯,如下所示:

我們可以在命令列輸入如下命令解決這個問題:

stop slave;
set global sql_slave_skip_counter=1;
start slave;
show slave status\G
一個個忽略過後,就正常了,沒有報錯:

但是這個時候如果再在mycat視窗上錄入資料,debug分析,還是會寫入到3327裡面去


Mycat後臺日誌如下:

07/18 01:55:54.550  DEBUG [$_NIOREACTOR-3-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=7, lastTime=1453052394535, user=root, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=163, charset=latin1, txIsolation=3, autocommit=true, attachment=dn3{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:55:54.550  DEBUG [$_NIOREACTOR-3-RW] (PhysicalDatasource.java:403) -release channel MySQLConnection [id=7, lastTime=1453052394535, user=root, schema=db3, old shema=db3, borrowed=true, fromSlaveDB=false, threadId=163, charset=latin1, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
07/18 01:55:54.550  DEBUG [$_NIOREACTOR-3-RW] (MultiNodeQueryHandler.java:171) -received ok response ,executeResponse:true from MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=dn2{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:55:54.551  DEBUG [$_NIOREACTOR-3-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=dn2{insert into company values(3,'baidu')}, res[email protected]42bed1e7, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
07/18 01:55:54.551  DEBUG [$_NIOREACTOR-3-RW] (PhysicalDatasource.java:403) -release channel MySQLConnection [id=3, lastTime=1453052394535, user=root, schema=db2, old shema=db2, borrowed=true, fromSlaveDB=false, threadId=162, charset=latin1, txIsolation=3, autocommit=true, attachment=null, respHandler=null, host=127.0.0.1, port=3327, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
至此,mycat主從切換成功。