Mycat學習1--實現MySQL讀寫分離與高可用

Mycat 下載地址:https://github.com/MyCATApache/Mycat-download

MySQL 離線rpm安裝包:https://download.csdn.net/download/weixin_29115985/12288220

數據庫讀寫分離對於大型系統或者訪問量很高的互聯網應用來說,是必不可少的一個重要功能。對於MySQL來說,標準的讀寫分離是主從模式,一個寫節點Master後面跟着多個讀節點,讀節點的數量取決於系統的壓力,通常是1-3個讀節點的配置。

 

如圖所示,writeHost表示主節點,readHost表示從節點,Mycat內部定期對一個dataHost裏所有的writeHost與readHost節點發起心跳檢測(writeHost與readHost都可以配置多個,至於數據同步的問題則需要我們從mysql層面實現了,Mycat並不提供數據同步的支持,本文只講mysql一主一從),正常情況下,Mycat會將第一個writeHost作爲寫節點,所有的DML SQL會發送給此節點,若Mycat開啓了讀寫分離,則Select SQL會根據讀寫分離策略發往readHost(+writeHost)執行。當一個dataHost裏面配置了多個writeHost時,如果第一個writeHost宕機,則Mycat會在默認的3次心跳檢查失敗後,自動切換到下一個可用的writeHost,以此類推。

這存在一個問題,就是當宕機的writeHost恢復後,怎麼重新加入Mycat,要不要恢復爲原來的寫節點? 最佳建議方式是:保持現有狀態不變,改旗易幟,恢復後的mysql節點作爲從節點,跟隨新的主節點,重新配置主從同步,原來跟隨該節點做同步的從節點也同樣換帥,重新配置同步源,這些節點的數據手工完成同步後,再加入Mycat裏。

Mycat實現讀寫分離和高可用,需要MySQL的主從複製機制配合。

 

MySQL 主從複製

 

主從配置需要注意的地方

1、主DB server和從DB server數據庫的版本一致

2、主DB server和從DB server數據庫數據名稱一致

3、主DB server開啓二進制日誌,主DB server和從DB server的server_id都必須唯一

 

MySQL 主服務器配置

1、修改 vi /etc/my.cnf 文件,在 [mysqld] 段下添加:

# 設置表名不區分大小寫     
lower_case_table_names=1
			
# 啓用二進制日誌
log-bin=mysql-bin
			
# 主服務器唯一ID,一般取IP最後一段
server-id=30

2、重啓mysql服務:service mysqld restart

3、建立帳戶並授權給用戶:(不建議用root用戶,% 表示所有客戶端都可能連,不安全!此處是個人學習用,嫌麻煩才用root

GRANT FILE ON *.* TO 'root'@'%' IDENTIFIED BY 'Root@123';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'root'@'%' IDENTIFIED BY 'Root@123';
# 嫌權限配置麻煩的話,可以賦全權出去,但是不太安全
# GRANT ALL PRIVILEGES ON *.* to 'root'@'%' IDENTIFIED BY 'Root@123'; 

4、刷新權限:FLUSH PRIVILEGES;

5、查詢master的狀態:show master status;

  

 

MySQL 從服務器配置

1、修改 vi /etc/my.cnf 文件,在 [mysqld] 段下添加:

# 設置表名不區分大小寫     
lower_case_table_names=1
			
# 主服務器唯一ID,一般取IP最後一段
server-id=203

2、配置從服務器:

# ''master_host'' 主庫地址,''master_port''主庫端口,''master_user'' 主庫用戶,''master_password'' 主庫密碼
# ''master_log_file'' 主庫File號(見主庫master狀態),''master_log_pos'' 主庫Position號(同見主庫master狀態)
change master to master_host='192.168.8.30',master_port=3306,master_user='root',master_password='Root@123',master_log_file='mysql-bin.000004',master_log_pos=5832;

3、啓動從服務器複製功能:start slave;

4、檢查從服務器複製功能狀態:show slave status\G;

  

注:Slave_IO_Running 及 Slave_SQL_Running 進程必須正常運行,即 YES 狀態,否則都是錯誤的狀態(如:其中一個NO均屬錯誤)。

 

* 問題排查:主從數據庫不同步,導致數據不一致,查看從庫狀態,發現 Slave_IO_Running 一直處於 Connecting 狀態?          

* 問題解決:經過查看同步日誌和狀態,發現從庫同步主庫時,密碼輸入不正確,所以重新停止從庫同步再重新鏈接到主庫即可解決!

1、停止從庫同步:stop slave;

2、重置主庫:reset master;

3、重置從庫:reset slave;

4、重新綁定主庫:change master to master_host='192.168.8.30',master_port=3306,master_user='root',master_password='Root@123',master_log_file='mysql-bin.000004',master_log_pos=5832;

5、開啓從庫同步:start slave;

 

Mycat 配置

Mycat的配置非常簡單,不用針對每個表進行配置,只需要在schema.xml中的元素上增加dataNode="defaultDN"屬性,並配置此dataNode對應的真實物理數據庫的database,然後dataHost開啓讀寫分離功能即可。

1、將MyCat配置到環境變量中,vi /etc/profile ,增加以下內容:

MYCAT_HOME=/usr/local/mycat
PATH=$MYCAT_HOME/bin:$PATH

2、保存後退出,執行source命令使配置生效,source /etc/profile

3、server.xml和rule.xml不做修改,用默認的即可,簡單配置下schema.xml,然後重啓 mycat restart ,可通過 mycat console 查看啓動日誌。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="mycat_db" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- 實現讀寫分離,寫走hostM1,讀走hostS1,若hostM1宕機了, hostS1也不可用 -->
                <writeHost host="hostM1" url="192.168.8.30:3306" user="root" password="Root@123">
                        <readHost host="hostS1" url="192.168.8.203:3306" user="root" password="Root@123" />
                </writeHost>
                <!-- 實現高可用,hostM1宕機了, hostM2頂上 -->
                <!-- <writeHost host="hostM2" url="192.168.8.203:3306" user="root" password="Root@123" /> -->
        </dataHost>
</mycat:schema>

配置說明:以下內容摘取於<<分佈式數據庫架構及企業實踐基於Mycat中間件>>一書中的官方解析,度娘上找的很多都是錯的!

1、balance屬性:負載均衡類型

balance="0":不開啓讀寫分離機制,所有讀操作都發送到當前可用的 writeHost 上。
balance="1":所有讀操作隨機分發到當前 writeHost 對應的 readHost 和備用的 writeHost。這樣就可以減輕主庫的壓力,高效地提供寫操作,而由其他服務器承擔耗費資源的讀操作。
balance="2":所有讀操作隨機分發到所有的 writeHost 和 readHost 上。適用於主庫壓力不是很大時,也可以分擔讀操作,更合理地利用資源。
balance="3":所有讀操作隨機分發到當前 writeHost 對應的 readHost 上執行,writeHost 不負擔讀壓力。此項只在Mycat1.4及之後版本纔有,適用於雙主熱備、多個 slave 的情況。

2、writeType屬性:負載均衡類型取值

writeType="0":所有寫操作都發送到配置的第1個 writeHost 上,writeHost1 掛了則切到 writeHost2 上,重新恢復 writeHost1 節點後,不會再切回來,還是以 writeHost2 爲準,切換記錄在配置文件 dnindex.properties 中。
writeType="1":所有寫操作都隨機地發送到配置的 writeHost 上,Mycat1.5版本以後不再推薦使用該值。

3、switchType屬性:切換模式

switchType="-1":表示不自動切換。
switchType="1":默認值,表示自動切換。
switchType="2":基於 MySQL 主從同步的狀態決定是否切換,心跳語句爲  show slave status 。
switchType="3":基於 Cluster 的切換機制(適合集羣,Mycat 從1.4.1版本開始支持),心跳語句爲  show status like 'wsrep%' 。

 

* 問題排查:完成讀寫分離配置後,通過Navicat進行數據測試,發現在主庫新增表格,從庫複製能成功,但是mycat的數據庫打開表格時出現報錯,如下:

[WARN ][$_NIOREACTOR-3-RW] execute  sql err : errno:1146 Table 'testdb.company' doesn't exist con:MySQLConnection [id=12, lastTime=1584423906412, user=root, schema=mycat_db, old shema=mycat_db, borrowed=true, fromSlaveDB=false, threadId=52, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROM `TESTDB`.`company` LIMIT 0, 1000}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROM `TESTDB`.`company` LIMIT 0, 1000}, packetId=1], host=192.168.8.203, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] frontend host:192.168.8.46/53392/root  (io.mycat.backend.mysql.nio.handler.SingleNodeHandler:SingleNodeHandler.java:249)

* 問題解決:經過 schema.xml 配置文件內容參數的排查,發現問題的根源在於 checkSQLschema 屬性!當該值設置爲 false (默認值),我們執行語句**SELECT * FROM company**,則Mycat會把 schema 字符增加進去,把 SQL 語句修改爲**SELECT * FROM `TESTDB`.`company`**併發送到後端數據庫執行,導致報錯。只要把 checkSQLschema 屬性改爲 true 即可!

 

測試結果展示

1、一般情況,查詢會走slave節點寫入走master節點,對master節點數據庫的增、刪、改操作最終會同步到slave節點

但這個同步所需要的時間不好掌握(網絡延時等因素),如果延時太長,我們新增一條數據後立即去查詢,很有可能會查詢不到剛新增的的數據。

2、如果對數據的實時性要求比較高的查詢,我們可以通過強制查詢走master節點或slave節點。

#強制走master:

/*!mycat:db_type=master*/ SELECT * FROM company

#強制走slave:

/*!mycat:db_type=slave*/ SELECT * FROM company

 

參考

1. Mycat - 實現數據庫的讀寫分離與高可用

2. MySQL以及MyCat的安裝和使用

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