基於代理的數據庫分庫分表框架 Mycat實踐

Profile

文章共 1796字,閱讀大約須要 4分鐘 !mysql


概 述

在現在海量數據充斥的互聯網環境下,分庫分表的意義我想在此處就不用贅述了。而分庫分表目前流行的方案最起碼有兩種:linux

  • 方案一:基於應用層的分片,即應用層代碼直接完成分片邏輯
  • 方案二:基於代理層的分片,即在應用代碼和底層數據庫中間添加一層代理層,而分片的路由規則則由代理層來進行處理

而本文即將要實驗的 MyCAT框架就屬於第二種方案的表明做品。git

注: 本文首發於 My Personal Blog:CodeSheep·程序羊,歡迎光臨 小站github


環境規劃

在本文中,我拿出了三臺 Linux主機投入試驗,各節點的角色分配以下表所示:sql

節點 部署組件 角色
192.168.199.75 MySQL 、 MyCAT master
192.168.199.74 MySQL slave
192.168.199.76 MySQL standby master

若是說上面這張表不足以說明實驗模型,那接下來再給一張圖好了,以下所示:數據庫

實驗模型

我想這樣看來的話,各個節點布了哪些組件,節點間的角色關係應該一目瞭然了吧後端

實驗環境規劃好了之後,接下來進行具體的部署與實驗過程,首先固然是 MyCAT代理的部署框架


MyCAT 部署

關於該部分,網上教程實在太多了,但最好仍是參考官方文檔來吧,下面也簡述一下部署過程學習

  • 下載 MyCAT並解壓安裝

這裏安裝的是 MyCAT 1.5測試

wget https://raw.githubusercontent.com/MyCATApache/Mycat-download/master/1.5-RELEASE/Mycat-server-1.5.1-RELEASE-20161130213509-linux.tar.gz
tar -zxvf Mycat-server-1.5.1-RELEASE-20161130213509-linux.tar.gz
mv mycat /usr/local/
  • 啓動 MyCAT
./mycat start

MyCAT 啓動日誌

  • MyCAT鏈接測試
mysql -utest -ptest -h127.0.0.1 -P8066 -DTESTDB

MyCAT 鏈接成功


MyCAT 配置

官網上對於這一部分的描述是很是詳細的,MyCAT 配置主要涉及三個 XML配置文件:

  • server.xml:MyCAT框架的系統參數/用戶參數配置文件
  • schema.xml: MyCAT框架的邏輯庫表與分片的配置文件
  • rule.xml :MyCAT框架的邏輯庫表分片規則的配置文件

用以下圖形能夠形象地表示出這三個 XML配置文件的配置內容和相互關係:

三個與 MyCAT相關的 xml配置

下面來進入具體的實驗環節 ,這也是圍繞 MyCAT提供的幾大主要功能展開的,主要涉及三個方面

  • 分庫分表
  • 讀寫分離
  • 主備切換

實驗以前,咱們先給出公共的 server.xml文件的配置,這部分後續實驗過程當中並不修改,其也就是定義了系統參數和用戶參數:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
	<system>
	<property name="defaultSqlParser">druidparser</property>
      <!--  <property /> 這塊諸多的property配置在此就不配置了,參照官網按需配置 -->
	</system>
	<user name="test">
		<property name="password">test</property>
		<property name="schemas">TESTDB</property>
	</user>

	<user name="user">
		<property name="password">user</property>
		<property name="schemas">TESTDB</property>
		<property name="readOnly">true</property>
	</user>

</mycat:server>

分庫分表實驗

預期實驗效果:經過 MyCAT代理往一張邏輯表中插入的多條數據,在後端自動地分配在不一樣的物理數據庫表上

咱們按照本文 **第二節【環境規劃】**中給出的實驗模型圖來給出以下的 MyCAT邏輯庫配置文件 schema.xml 和 分庫分表規則配置文件 rule.xml

  • 準備配置文件

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/" >

	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
		<table name="travelrecord" dataNode="dn1,dn2" rule="sharding-by-month" />
	</schema>
	
	<dataNode name="dn1" dataHost="testhost" database="db1" />
	<dataNode name="dn2" dataHost="testhost" database="db2" />
	
	<dataHost name="testhost" maxCon="1000" minCon="10" balance="0"
		writeType="0" dbType="mysql" dbDriver="native" switchType="-1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="localhost:3306" user="root" password="xxxxxx">
                <readHost host="hostS1" url="192.168.199.74:3306" user="root" password="xxxxxx" />
		</writeHost>
		<writeHost host="hostM2" url="192.168.199.76:3306" user="root" password="xxxxxx">
		</writeHost>
	</dataHost>

</mycat:schema>

其中定義了實驗用到的 hostM一、hostS1 和 hostM2

rule.xml

<tableRule name="sharding-by-month">
		<rule>
			<columns>create_date</columns>
			<algorithm>partbymonth</algorithm>
		</rule>
	</tableRule>

	<function name="partbymonth"
		class="org.opencloudb.route.function.PartitionByMonth">
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sBeginDate">2018-11-01</property>
	</function>

這裏配置了 sharding-by-month的分庫分表規則,即按照表中的 create_date字段進行分割,從 2018-11-01日期開始,月份不一樣的數據落到不一樣的物理數據庫表中

  • 在三個物理節點數據庫上分別建立兩個庫 db1和 db2
create database db1;
create database db2;
  • 鏈接 MyCAT
mysql -utest -ptest -h127.0.0.1 -P8066 -DTESTDB
  • 經過 MyCAT來建立數據庫 travelrecord
create table travelrecord (id bigint not null primary key,city varchar(100),create_date DATE);
  • 經過 MyCAT來往travelrecord表中插入兩條數據
insert into travelrecord(id,city,create_date)  values(1,'NanJing','2018-11-3');
insert into travelrecord(id,city,create_date)  values(2,'BeiJing','2018-12-3');

經過 MyCAT往邏輯庫中插入數據

因爲插入的這兩條記錄的 create_date分別是 2018-11-32018-12-3,而咱們配的分庫分表的規則便是根據 2018-11-01這個日期爲起始來進行遞增的,按照前面咱們配的分片規則,理論上這兩條記錄按照 create_date日期字段的不一樣,應該分別插入到 hostM1的 db1和 db2兩個不一樣的數據庫中。

  • 驗證一下數據分片的效果

數據分片的效果

因爲 hostM1hostS1組成了 主-從庫 關係,所以剛插入的兩條數據也應該相應自動同步到 hostS1db1db2兩個數據庫中,不妨也來驗證一下:

主從數據庫同步也是OK的


讀寫分離實驗

**預期實驗效果:**開啓了 MyCAT的讀寫分離機制後,讀寫數據操做各行其道,互不干擾

此節實驗用到的配置文件 schema.xmlrule.xml基本和上面的【分庫分表】實驗沒什麼不一樣,只是咱們須要關注一下 schema.xml配置文件中 <dataHost />標籤裏的 balance字段,它是與讀寫分離息息相關的配置:

所以咱們就須要弄清楚 <dataHost /> 標籤中 balance參數的含義:

  • balance="0":不開啓讀寫分離機制,即讀請求僅分發到 writeHost上
  • balance="1":讀請求隨機分發到當前 writeHost對應的 readHost和 standby writeHost上
  • balance="2":讀請求隨機分發到當前 dataHost內全部的 writeHost / readHost上
  • balance="3":讀請求隨機分發到當前 writeHost對應的 readHost上

咱們驗證一下 balance="1"的狀況,即開啓讀寫分離機制,且讀請求隨機分發到當前 writeHost對應的 readHost和 standby writeHost上,而對於本文來說,也即:hostS1 和 hostM2 上

咱們來作兩次數據表的 SELECT讀操做:

mysql> select * from travelrecord limit 6;
+----+----------+-------------+
| id | city     | create_date |
+----+----------+-------------+
|  3 | TianJing | 2018-11-04  |
|  5 | ShenYang | 2018-11-05  |
|  4 | Wuhan    | 2018-12-04  |
|  6 | Harbin   | 2018-12-05  |
+----+----------+-------------+
4 rows in set (0.08 sec)

mysql> select * from travelrecord limit 6;
+----+---------+-------------+
| id | city    | create_date |
+----+---------+-------------+
|  2 | BeiJing | 2018-12-03  |
|  8 | WuXi    | 2018-12-06  |
|  1 | NanJing | 2018-11-03  |
|  7 | SuZhou  | 2018-11-06  |
+----+---------+-------------+
4 rows in set (0.01 sec)

而後咱們取出 mycat.log日誌查看一下具體詳情,咱們發現第一次 select讀操做分發到了 hostM2上:

第一次 select讀操做分發到了 hostM2上

而第二次 select讀操做分發到了 hostS1上:

第二次 select讀操做分發到了 hostS1上


主備切換實驗

**預期實驗效果:**開啓 MyCAT的主備機制後,當主庫宕機時,自動切換到備用機進行操做

關於主備切換,則須要弄清楚 <dataHost /> 標籤中 switchType參數的含義:

  • switchType="-1":不自動切換主備數據庫
  • switchType="1":自動切換主備數據庫
  • switchType="2":基於MySQL主從複製的狀態來決定是否切換,需修改heartbeat語句:show slave status
  • switchType="3":基於Galera(集羣多節點複製)的切換機制,需修改heartbeat語句:show status like 'wsrep%'

此處驗證一下 Mycat的主備自動切換效果。爲此首先咱們將 switchType="-1" 設置爲 switchType="1",並重啓 MyCat服務:

<dataHost name="testhost" maxCon="1000" minCon="10" balance="0"
        writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">

在本實驗環境中,在 hostM1hostM2均正常時,默認寫數據時是寫到 hostM1

  • 接下來手動中止 hostM1 上的 MySQL數據庫來模擬 hostM1 宕機:
systemctl stop mysqld.service

接下來再經過 MyCat插入以下兩條數據:

insert into travelrecord(id,city,create_date)  values(3,'TianJing','2018-11-4');
insert into travelrecord(id,city,create_date)  values(4,'Wuhan','2018-12-4');

效果以下:

hostM1宕機後,備用hostM2升級爲主寫節點

  • 此時,咱們恢復 hostM1,但接下來的數據寫入依然進入 hostM2
insert into travelrecord(id,city,create_date)  values(5,'ShenYang','2018-11-5');
insert into travelrecord(id,city,create_date)  values(6,'Harbin','2018-12-5');

雖然hostM1恢復,但依然不是主寫節點

  • 接下來手動讓 hostM2宕機,看 hostM1 是否能升級爲主寫節點

再插入兩條數據:

insert into travelrecord(id,city,create_date)  values(7,'SuZhou','2018-11-6');
insert into travelrecord(id,city,create_date)  values(8,'WuXi','2018-12-6');

hostM2宕機後,hostM1再次升級爲主寫節點

很明顯,答案是確定的


後 記

因爲能力有限,如有錯誤或者不當之處,還請你們批評指正,一塊兒學習交流!

相關文章
相關標籤/搜索