通過MyCAT中間件實現讀寫分離

緊接着上一章節的《MySQL一主多從配置》,本章節將介紹如何搭建mycat中間件,並用mycat來做讀寫分離.

本章概要

1、MyCat關鍵特性
2、下載MyCat主程序
3、基礎設施
4、配置MyCat&驗證

Mycat關鍵特性

關鍵特性
支持SQL92標準
支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等DB的常見SQL語法
遵守Mysql原生協議,跨語言,跨平臺,跨數據庫的通用中間件代理。
基於心跳的自動故障切換,支持讀寫分離,支持MySQL主從,以及galera cluster集羣。
支持Galera for MySQL集羣,Percona Cluster或者MariaDB cluster
基於Nio實現,有效管理線程,解決高併發問題。
支持數據的多片自動路由與聚合,支持sum,count,max等常用的聚合函數,支持跨庫分頁。
支持單庫內部任意join,支持跨庫2表join,甚至基於caltlet的多表join。
支持通過全局表,ER關係的分片策略,實現了高效的多表join查詢。
支持多租戶方案。
支持分佈式事務(弱xa)。
支持XA分佈式事務(1.6.5)。
支持全局序列號,解決分佈式下的主鍵生成問題。
分片規則豐富,插件化開發,易於擴展。
強大的web,命令行監控。
支持前端作爲MySQL通用代理,後端JDBC方式支持Oracle、DB2、SQL Server 、 mongodb 、巨杉。
支持密碼加密
支持服務降級
支持IP白名單
支持SQL黑名單、sql注入攻擊攔截
支持prepare預編譯指令(1.6)
支持非堆內存(Direct Memory)聚合計算(1.6)
支持PostgreSQL的native協議(1.6)
支持mysql和oracle存儲過程,out參數、多結果集返回(1.6)
支持zookeeper協調主從切換、zk序列、配置zk化(1.6)
支持庫內分表(1.6)
集羣基於ZooKeeper管理,在線升級,擴容,智能優化,大數據處理(2.0開發版)。
什麼是MYCAT
一個徹底開源的,面向企業應用開發的大數據庫集羣
支持事務、ACID、可以替代MySQL的加強版數據庫
一個可以視爲MySQL集羣的企業級數據庫,用來替代昂貴的Oracle集羣
一個融合內存緩存技術、NoSQL技術、HDFS大數據的新型SQL Server
結合傳統數據庫和新型分佈式數據倉庫的新一代企業級數據庫產品
一個新穎的數據庫中間件產品

以上來源於官方說明,MyCat將在未來協助我們實現MySQL的高可用、高性能集羣,並且完全實現了與業務代碼解耦,無侵入。

下載MyCat主程序

直接訪問http://www.mycat.org.cn/官方地址,可以找到當前最新版本,本案例使用1.6版本實現。目前爲WIN64系統進行驗證,故直接下載WIN版本解壓即可。
注:MyCat依賴JDK環境,故需要確保已經正常安裝Jdk。

基礎設施

目前本地已經運行有3個實例服務
Master 127.0.0.1:3310
Slave 127.0.0.1:3321
Slave 127.0.0.1:3322
本案例主要驗證讀寫分離,故數據庫均爲springboot1,且用戶名密碼均爲root。

配置MyCat

Conf目錄下存放配置文件:
1、server.xml是Mycat服務器參數調整和用戶授權的配置文件;
2、schema.xml是邏輯庫定義和表以及分片定義的配置文件;
3、rule.xml是分片規則的配置文件,分片規則的具體一些參數信息單獨存放爲文件,也在這個目錄下,配置文件修改,需要重啓Mycat或者通過9066端口reload;
4、wrapper.conf:JVM配置參數等設置;

第一步、我們需要配置的是schema.xml:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="springboot1" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3310" user="root"
password="root">
<!-- can have multi read hosts -->
<readHost host="hostS2" url="127.0.0.1:3322" user="root" password="root" />
</writeHost>
<writeHost host="hostS1" url="localhost:3321" user="root"
password="root" />
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
主要參數說明:
A、schema:邏輯庫,與MySQL中的Database(數據庫)對應,一個邏輯庫中定義了所包括的Table。
B、dataNode: MyCAT的邏輯數據節點,是存放table的具體物理節點,也稱之爲分片節點,通過DataSource來關聯到後端某個具體數據庫上,一般來說,爲了高可用性,每個DataNode都設置兩個DataSource,一主一從,當主節點宕機,系統自動切換到從節點。
C、dataHost:定義某個物理庫的訪問地址,用於捆綁到dataNode上。
C.1、dataHost有兩個參數需要注意:balance和 switchType
其中,balance指的負載均衡類型,目前的取值有4種:
1. balance="0", 不開啓讀寫分離機制,所有讀操作都發送到當前可用的writeHost上。
2. balance="1",全部的readHost與stand by writeHost參與select語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,並且M1與 M2互爲主備),正常情況下,M2,S1,S2都參與select語句的負載均衡。
3. balance="2",所有讀操作都隨機的在writeHost、readhost上分發。
4. balance="3",所有讀請求隨機的分發到wiriterHost對應的readhost執行,writerHost不負擔讀壓力
switchType指的是切換的模式,目前的取值也有4種:
1. switchType='-1' 表示不自動切換
2. switchType='1' 默認值,表示自動切換
3. switchType='2' 基於MySQL主從同步的狀態決定是否切換,心跳語句爲 show slave status
4. switchType='3'基於MySQL galary cluster的切換機制(適合集羣),心跳語句爲 show status like 'wsrep%'。
因此,該配置文件中的balance="1"意味着作爲stand by writeHost的hostS1和hostS2將參與select語句的負載均衡,這就實現了主從的讀寫分離,switchType='-1'意味着當主掛掉的時候,不進行自動切換,即hostS1和hostS2並不會被提升爲主,仍只提供讀的功能。這就避免了將數據讀進slave的可能性,畢竟,單純的MySQL主從集羣並不允許將數據讀進slave中,除非配置的是雙master。
C.2、注意writeHost/readHost中的url,user,password的值均爲上述基礎設施中的Mysql的連接信息。

第二步、上面我們將數據源的關係全部配置完畢,既然我們需要通過MyCat訪問最終的數據源,則需要在server.xml配置連接信息: 
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
</user>
參數說明:
name:用戶名
password:密碼
schemas:實例名,和schema.xml定義的schema對應,這裏的實例名是虛擬名,也就是對mycat服務的一種別名,是 應用程序以及客戶端連接的入口。

第三步、爲了後續可以比較好的驗證監控,我們需要將log級別調整爲debug:
日誌存放在logs/mycat.log中,每天一個文件,日誌的配置是在conf/log4j.xml中,根據自己的需要,可以調整輸出級別爲debug,debug級別下,會輸出更多的信息,方便排查問題。

第四步、啓動服務,在Windows 下 運行:mycat.bat console在控制檯啓動程序,也可以裝載成服務,若此程序運行有問題,也可以運行startup_nowrap.bat,確保java命令可以在命令執行,我們直接通過startup_nowrap.bat啓動服務:

啓動服務後默認數據端口爲8066,管理端口爲9066。
(通過如下命令可以安裝爲服務
安裝mycat服務 :mycate install 
啓動mycat服務 :mycate start
停止mycat服務 :mycate stop
注意:當修改配置文件後,需要重啓mycat服務)

驗證
1、首先需要連接上MyCat,我們進入任意一個MySQL打開客戶端連接即可,通過mysql -uroot -p -h127.0.0.1 -P8066

也可以通過客戶端工具連接


2、在登錄時沒有指定邏輯庫,我們通過use TESTDB命令切換:


3、此時我們即可進行查詢:

特別關注上述的紅色部分,在Master中我們爲111,由於我們是單向複製,故我將在3321中的數據做了點手腳

從而也證明了確實是從Slave庫讀取的數據,我們來看下日誌呢
2017-02-05 13:53:21.139 DEBUG [$_NIOREACTOR-3-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=11, lastTime=1486274001132, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=false, threadId=3033, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROm t_sys_user r}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROm t_sys_user r}, packetId=126], host=localhost, port=3321, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]
此次正好從我們上述調整的3321服務中讀取數據,也證明了爲何讀取的非111,而是1111,既然我們有兩個從服務,也不會每次的讀取都是1111結果,如下即從3322服務讀取

2017-02-05 15:11:25.788 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=16, lastTime=1486278685777, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=true, threadId=15, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROm t_sys_user r}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROm t_sys_user r}, packetId=127], host=127.0.0.1, port=3322, statusSync=io.mycat.backend.mysql.nio.MySQLConnection$StatusSync@1bac8b63, writeQueue=0, modifiedSQLExecuted=false]
可以看到MyCat已經爲我們很好的實現了負載均衡。

4、既然讀取確實是我們期望的,那麼寫入呢,直接通過命令行新增一個數據行

通過對Master和2個Slave庫的查詢,均有新增數據,那麼此次數據的插入是通過哪個服務呢,繼續關注日誌,
2017-02-05 14:09:03.447 DEBUG [$_NIOREACTOR-2-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) - release connection MySQLConnection [id=10, lastTime=1486274943433, user=root, schema=springboot1, old shema=springboot1, borrowed=true, fromSlaveDB=false, threadId=3087, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{INSERT INTO springboot1.t_sys_user ( password, `loginName`) VALUES ('12', '12')}, respHandler=SingleNodeHandler [node=dn1{INSERT INTO springboot1.t_sys_user ( password, `loginName`) VALUES ('12', '12')}, packetId=1], host=localhost, port=3310, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
可以看到紅色部分,驗證成功。

總結
通過MyCat實現讀寫分離將對我們的業務代碼沒有任何的侵入性,並且在多個從庫的情況下實現了複雜均衡。當然MyCat的作用不止這麼多,在特性中有很多的介紹,後續將慢慢展開。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章