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安裝從庫
主從複製參見博文《MySQL之——主從複製的配置》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
三、安裝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主從切換成功。