很多開發框架在框架底層就引入了讀寫分離的機制,面對一些沒有底層支持讀寫分離的框架,如何實現讀寫分離呢?
Mycat
一個開源的高性能的數據庫中間件產品,支持讀寫分離,支持MySQL主從,數據切分以及galera cluster集羣。
它是一個開源的分佈式數據庫系統,是一個實現了 MySQL 協議的的
Server,前端用戶可以把它看作是一個數據庫代理,用 MySQL 客戶端工具和命令行訪問,而其後端可以用
MySQL 原生(Native)協議與多個 MySQL 服務器通信,也可以用 JDBC 協議與大多數主流數據庫服務器通信,
其核心功能是分表分庫,即將一個大表水平分割爲 N 個小表,存儲在後端 MySQL 服務器裏或者其他數據庫裏。
安裝指南
- 安裝JDK (略)
- 安裝MySQL (略)
- 安裝MyCAT
http://dl.mycat.io/1.6-RELEASE/ 目前最新的穩定版本爲1.6
下載指定系統的壓縮包,解壓以後即可使用。免安裝。
使用指南
配置
- server.xml 系統配置文件
<user name="root">
<property name="password">123456</property>
<property name="schemas">dsy</property>
<!-- 表級 DML 權限設置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
user標籤用來添加用戶,管理用戶權限。
- schema.xml 管理邏輯庫和邏輯表的配置文件
<schema name="dsy" checkSQLschema="false" sqlMaxLimit="100">
<!-- auto sharding by id (long) -->
<table name="xn_user_info" dataNode="dn1"/>
</schema>
解釋:schema標籤定義邏輯庫的名字,table定義邏輯表。dataNode屬性表示數據節點也就是數據分片。如果數據沒有分片,通常只有一個就行了。
<dataNode name="dn1" dataHost="localhost1" database="dsy" />
解釋:創建一個名字叫做dn1的數據節點,該節點使用名字爲localhost1數據庫實例上的dsy這個庫組成數據分片。
<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:3306" user="root"
password="root">
<!-- can have multi read hosts -->
<!-- <readHost host="hostS2" url="localhost:3306" user="root" password="root" /> -->
<!-- <readHost host="hostS2" url="192.168.0.164:3306" user="root" password="root" /> -->
</writeHost>
<writeHost host="hostS1" url="192.168.0.164:3306" user="root"
password="root" />
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
解釋:創建一個名爲localhost1的數據庫實例。連接池最大鏈接數爲1000。初始化的連接池數爲10。dbType標識使用mysql的二進制協議。 dbDriver使用native表示可以使用mysql和mariadb,可選值還有JDBC驅動。switchType=1表示自動切換。如果switchType設置爲2並且slaveThreshold=”100,維持心跳的語句改爲show slave status,意味着開啓MySQL主從複製狀態綁定的讀寫分離與切換機制。
heartbeat是採用select user這條語句來維持心跳。
writehost是用來定義寫實例。在一個 dataHost 內可以定義多個 writeHost 和 readHost。但是,如果 writeHost 指定的後端數據庫宕機,那麼這個 writeHost 綁定的所有 readHost 都將不可用。另一方面,由於這個 writeHost 宕機系統會自動的檢測到,並切換到備用的 writeHost 上去。
balance | 解釋 |
---|---|
0 | 不開啓讀寫分離機制,所有讀操作都發送到當前可用的 writeHost 上。 |
1 | 全部的 readHost 與 stand by writeHost 參與 select 語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,並且 M1 與 M2 互爲主備),正常情況下,M2,S1,S2 都參與 select 語句的負載均衡。 |
2 | 所有讀操作都隨機的在 writeHost、readhost 上分發。 |
3 | 所有讀請求隨機的分發到 wiriterHost 對應的 readhost 執行,writerHost 不負擔讀壓力,注意 balance=3 只在 1.4 及其以後版本有,1.3 沒有。 |
writeType | 負載均衡類型解釋 |
---|---|
0 | 所有寫操作發送到配置的第一個 writeHost,第一個掛了切到還生存的第二個 writeHost,重新啓動後已切換後的爲準,切換記錄在配置文件中:dnindex.properties . |
1 | 所有寫操作都隨機的發送到配置的 writeHost,1.5 以後廢棄不推薦。 |
switchType | 切換解釋 |
---|---|
-1 | 表示不自動切換 |
1 | 表示自動切換 |
2 | 基於MySQL主從同步的狀態決定是否切換,心跳語句爲 show slave status |
3 | 基於MySQL galary cluster的切換機制(適合集羣)(1.4.1),心跳語句爲 show status like ‘wsrep%’。 |
讀寫分離配置
上述dataHost配置裏,兩個平級的writeHost節點。是一種方案。
或者在第一個writeHost裏配置一個readHost節點來做讀寫分離。爲第二種方案。
第二種當寫掛了的時候,讀也同事不可用。但是第一種可以繼續使用。建議使用第一種配置。也就是上面的代碼裏寫的那樣。
事務內部的一切操作都會走寫節點,所以讀操作不要加事務。
啓動服務
進入 MYCAT/bin 目錄 執行 ./mycat start
連接mycat
和mysql命令一致 mysql -uroot -p123456 -h127.0.0.1 -P8066 -Ddsy
如果看到以下字樣說明正常運行了。
Your MySQL connection id is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
配置MySQL主從同步
現有主機A:192.168.0.107
主機B:192.168.0.164
做主從同步。A爲master節點B爲slave節點。
1. A,B主機上都開啓binlog功能。
配置文件在/etc/my.cnf。取消log-bin=mysql-bin前面的註釋。
1. 在A主機上創建一個slave用戶,只賦給他REPLICATION SLAVE 權限即可。
1. 在A主機上執行以下SQL語句
FLUSH LOGS
SHOW MASTER STATUS
確保在執行FLUSH LOGS時刻,AB兩個庫的數據完全一致。
執行完SHOW MASTER STATUS以後記錄下binlog文件和pos位置。
1. 在B主機上將master節點指向A主機
CHANGE MASTER TO MASTER_HOST = '192.168.0.107', MASTER_USER = 'slave', MASTER_PASSWORD = 'slave', MASTER_PORT = 3306, MASTER_LOG_FILE = 'mysql-bin.000002' MASTER_LOG_POS = 105 ;
- 啓動主從同步
START SLAVE
- 查看主從同步狀態
SHOW SLAVE STATUS
如果看到Slave_IO_Running和Slave_SQL_Running都是Yes
這說明mysql主從同步配置完畢
踩坑指南
儘量保證AB主機上的mysql版本一致。
如果無法保證,儘量保證mysqlbinlog版本一致。
如果連mysqlbinlog版本都無法保證一致,最起碼主節點的mysqlbinlog不能高於從主機的mysqlbinlog。
我在測試的時候主節點的mysqlbinlog是V4.4的,從節點的mysqlbinlog是V3.3的。簡直是噩夢。
老版本的mysqlbinlog不能正常讀取新版本下產生的binlog日誌文件。