我家很管事的貓——mycat初步部署實踐與問題排查

mycat,阿里出品的mysql中間件,提供讀寫分離和分庫分表方案。項目中主要使用的是其讀寫分離功能。html

【如何部署?】前端

本文只採用並測試了雙主從模式,配置看這一篇足矣:mysql

https://www.cnblogs.com/biglittleant/p/7059569.htmlspring

須要注意在配置並啓動mycat以前必定要完成mysql物理節點之間主從複製配置,並保證每一個節點show slave status\G中sql

SLAVE_SQL_RUNNING、SLAVE_IO_RUNNING都爲YES。數據庫

而後啓動mycat,通常不會發生問題。服務器

對dataHost的三個參數進行解讀:mybatis

<dataHost name="mysqlms" maxCon="2000" minCon="20" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">負載均衡

其中,balance指的負載均衡類型。async

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不負擔讀壓力

writeType指寫操做模式。

1. writeType=「0」, 全部寫操做都發送到可用的writeHost上。
2. writeType=「1」,全部寫操做都隨機的發送到readHost。
3. writeType=「2」,全部寫操做都隨機的在writeHost、readhost分上發。

switchType指的是切換的模式。

1. switchType='-1' 表示不自動切換

2. switchType='1' 默認值,表示自動切換

3. switchType='2' 基於MySQL主從同步的狀態決定是否切換,心跳語句爲 show slave status

4. switchType='3'基於MySQL galary cluster的切換機制(適合集羣),心跳語句爲 show status like 'wsrep%'。

目前尚未嘗試過雙主節點同時掛掉的狀況,switchType暫且使用了默認值。這裏有待後續測試。

【日誌級別】
/.../mycat/conf/log4j2.xml
<asyncRoot level="debug"

此時可以看到mycat負載路徑,很實用。

另外附上mysql在配置文件my.cnf中打開bin日誌和普通日誌的方式,尤爲是普通日誌,配合mycat日誌能夠更好地理解讀寫分離實現過程。

普通
general_log=1

general_log_file=/usr/local/log/query.log

SHOW GLOBAL VARIABLES LIKE 'general%';(查看開啓狀態,如未成功查看mysql日誌mysqld.log)

二進制
log_bin=mysql-bin

SHOW GLOBAL VARIABLES LIKE '%log%';(查看開啓狀態,如未成功查看mysql日誌mysqld.log)

【監控】

這裏我試用了mycat-eye,我的感受並非很好用,不少項是空白也不清楚怎麼開啓,但至少能夠很方便的得到物理節點的心跳狀態。

【節點down掉】

寫節點down掉以後其讀節點也會失效,通常狀況下重連以後此主從仍會做爲mycat集羣中承擔讀任務的節點。
mysql的主從同步線程重啓時間較長,估算約30秒,估計還會受期間發生的事務數量影響。
好處是節點down掉以後重連會自動同步(只要雙主從初始配置正常),不用手動修改mysql主從複製配置。

【寫主節點down掉】
mycat在檢測到寫主節點會嘗試將主節點分配給寫從節點。並在dnindex.properties記錄,dataHost name=? 爲0時表示M1,爲1時表示M2。

注意:在down掉的寫主節點從新鏈接或將mycat重啓後此值依然不變。指定寫主節點須要手動修改並重啓mycat。

【偶發bug】
一、【數據不一致】mycat對於即時性高的事務支持是比較穩定的,測試中與代碼執行邏輯相違背的數據不一致狀況極偶發,其中**在寫主節點down掉從新啓動以後必發**。
未及時狀況緣由:在mycat中,部分寫sql發生在讀sql以後。

二、down掉重啓以後可能不會再將讀請求分配給寫從節點及其讀從節點,這裏可能涉及負載均衡策略,還需進一步測試。

【其餘問題排查,mysql自己問題居多】

一、【navicat前端不能直接操做mycat?數據會不一致?】

這個問題比較具備迷惑性,經測試,navicat操做mycat節點時,sql與jdbc鏈接mycat執行的sql無異,都是先發送至mycat由其進行負載分配(可查看日誌mycat.log驗證),update語句在writeType=「0」的狀況下必定由寫主節點完成。

若是不經由mycat而直接在寫節點或讀節點操做,mycat不會造成日誌。

後來查清當時之所造成這樣的認知,是由於其中一個讀節點,因爲服務器上其餘應用的日誌文件迅速佔滿了空間而致使mysql主從同步的線程阻塞,而mycat並未發現異常,繼續爲此節點分配讀任務,致使數據不一致。

解決方法騰出空間便可,無需對該節點mysql進行額外操做。

實際上,當其中一個節點出現磁盤空間已滿這種問題時,在navicat鏈接mycat打開一個表,反覆刷新就會發現數據不一致狀況。

mycat可否發現出問題的讀節點並將其排除,有待進一步研究。

二、【SLAVE_SQL_RUNNING、SLAVE_IO_RUNNING爲NO】

(1)SLAVE_SQL_RUNNING爲NO可單獨嘗試reset master;看可否生效。

(2)SLAVE_IO_RUNNING爲NO

到主庫上show master status查一下主庫當前的gtid(Executed_Gtid_Set),
而後到從庫執行下面命令:
reset master;
stop slave;
set global gtid_purged = 'xxxx'; -- 這裏xxxx是主庫的Executed_Gtid_Set,能夠爲空噢
start slave;

意思是從庫同步時,丟棄現有主庫執行過的gtid。

(3)以上若不能解決,看日誌/var/log/mysqld.log對症下藥。

對於網上的一些change master解決方式,在GTID模式開啓的狀況下,

gtid-mode=on
enforce-gtid-consistency

不用從新指定change master to master_log_file='mysql-bin.xxxxxx',master_log_pos=xxx;

 三、【我用navicat打開某個schema以後刷新,看到的「行」、「自動遞增值」、「修改日期」不同?】

首先,這裏的統計數據是由SHOW TABLE STATUS獲得的。每一個表內的記錄其實是徹底一致的。

(1)「行」:這裏引用CSDN論壇小小小小周的回答:

「部分存儲引擎,如MyISAM,存儲精確的數目。
對於其它存儲引擎,好比InnoDB,本值是一個大約的數,與實際值相差可達40到50%。在這些狀況下,使用SELECT COUNT(*)來得到準確的數目。
對於在INFORMATION_SCHEMA數據庫中的表,Rows值爲NULL」

(2)「自動遞增值」:在,除了主寫節點之外,其餘承擔讀任務的節點increment應該都一致並比主寫節點少1。

(increment能夠經過 SELECT auto_increment FROM information_schema.tables where table_schema="dbName" and table_name="tableName";單獨查看,值和SHOW TABLE STATUS獲得的相同。)

查看my.cnf中的配置,兩個寫節點(或稱M節點)的offset一個爲1另外一個爲2。

auto-increment-offset=x
auto-increment-increment=2

爲了實現雙主從模式的事務控制和切換,increment設置爲2。由此致使主寫節點比當前存在的最大一個id多2,其餘節點(同步本身的主節點)比當前存在的最大一個id多1,注意這裏設置了increment爲2的另外一寫節點一樣比當前存在的最大一個id多1。

另猜想,**在寫主節點down掉從新啓動以後必發**的數據不一致bug可能與此有關,有待進一步測試。

(3)「修改日期」:這個值應該只有微小不一致,由於各節點主從同步時間有微小差異。固然,這裏的信息都不徹底準確。

不當之處懇請各位指教,下篇jenkins。

【190103補充】

經測試,update等DML操做能夠正常加行鎖,而select...for update被mycat視做普通select,也就是說不會把select...for update分配到主寫節點。

可是,在使用mybatis+spring的狀況下,在select方法上加@Transaction註解(若是寫在更外層則不會影響select方法)能夠由主寫節點處理查詢,這時select...for update便可正常加鎖了。

相關文章
相關標籤/搜索