1. 程式人生 > >Mycat 讀寫分離+分庫分表

Mycat 讀寫分離+分庫分表

BE IT 讀取 分離 取數據 常見 sele -i roo

上次進過GTID復制的學習記錄,已經搭建好了主從復制的服務器,現在利用現有的主從復制環境,加上正在研究的Mycat,實現了主流分布式數據庫的測試




Mycat就不用多介紹了,可以實現很多分布式數據庫的功能,極大的減輕數據庫服務器的壓力,包括讀寫分離以及分庫分表,本測試對這兩種功能都進行了測試,進行相應記錄




本文以Mycat官方給出的例子來進行解釋總結




首先來看分庫分表,分庫分表一般來說都是一起說的,但是實際上分庫跟分表是有區別的,簡單來說有垂直和水平兩種方式,垂直就是將表按字段進行拆分,水平就是將表按照數據分布來做行拆分。具體的肯定還是有區別,本文不再進行闡述,主要介紹按照字段的分布進行數據行的拆分




本身理解來說Mycat實現的應該是分庫,也就是將一個表的行分開存儲到不同的數據庫中,這裏不同的數據庫可以有一下兩種


1)不同的數據庫服務器上的 兩個數據庫(此時db的名字可以相同,也可以不同)


2)相同的數據庫服務器上的兩個數據庫(此時db的名字肯定是不同的)




當然對於實際使用分庫來說肯定是使用不同的數據庫服務器的,而且大多數都是在不同的服務器上使用相同的名字,這樣能夠比較正式的做法




分表的關鍵部分在mycat的配置文件schema.xml中,該文件中定義了數據庫服務器,表的拆分規則等等重要信息
<table name="employee" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile" />
以該配置為例,在mycat的邏輯數據庫中定義employee表,主鍵是ID字段,分表規則是sharding-by-intfile,該規則可以在rule.xml中找到對應的信息,而拆分的數據節點是dn1和dn2,數據節點是mycat的概念,再來看看dn1 和dn2 的配置


<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost2" database="db1" />


當然上面的配置是在將employee表的數據分配到兩個數據庫服務器上分別是localhost1和localhost2


同樣也可以如下配置


<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />


這樣的配置就在localhost1上建立兩個數據庫分別是db1和db2,將數據存在同一個數據庫實例上的兩個數據庫上,同樣屬於分庫分表




本文以正式運維環境進行配置,此處的dataHost是不同的,所以是不同的數據庫服務器,而指向這兩個數據庫服務器的db名字是相同的,均為db1


再看dataHost的配置,這裏就涉及到具體數據庫服務器的配置了


<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="ip1:3003" user="root"
password="123">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="ip2:3009" user="root"
password="123">
</writeHost>
</dataHost>






這裏的配置還沒有加入讀寫分離,所以下面會介紹讀寫分離的配置,上面的配置就具體執行了兩臺的數據庫服務器來做分庫


這樣一個表的分庫就配置好了,Mycat會根據對應的rule規則和具體的sql語句進行路由處理,包括數據分庫存儲和數據分庫獲取等等




下面來看看讀寫分離,說到讀寫分離就必須存在主從復制的環境,需要先配置好主從復制,同樣是在schema.xml中對主服務器和從服務器進行相應的配置即可


<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="ip1:3003" user="root"
password="123">
<readHost host="hostS1" url="ip2:3009" user="root"
password="123"/>
</writeHost>
</dataHost>


此時在writeHost在配置對應的readHost,註意readHost是附屬在writeHost下的,再去設置balance的值,至於balance的取值0,1,2網上有很多資料,分別用來指定哪幾個host能參與到數據庫的讀操作中,上面的配置是單獨的一個寫服務器的讀寫分離實例,這樣會表示寫操作會通過ip1:3003的服務器,而讀操作會通過ip2:3009的服務器,這就是最基本的讀寫分離配置,註意上面的配置只有一個dataHost,就是說明沒有分庫分表的特點




下面來看一下分庫分表+讀寫分離,實際上也就是利用Mycat提供的功能,將兩種特性都寫入schema.xml中,達到同時具有分表+讀寫分離的需求
<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="ip1:3003" user="root"
password="123">
<readHost host="hostS1" url="ip2:3009" user="root"
password="123"/>
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="ip3:3003" user="root"
password="123">
</writeHost>
</dataHost>


顯然總結一下:


1 有多個dataHost,就說明有分庫分表的設置


2 在一個dataHost中有readHost在writeHost下,或者有多個writeHost,而且balance不等於0(0代表沒有讀寫分離),就說明有讀寫分離的設置,


3 在一個dataHost中有多個writeHost,這些writeHost之間必須是主主復制,這樣才能保證及時兩次寫操作分別用不同的writeHost,也能保證兩個Host數據一致的情況






再對分庫分表+讀寫分離的配置進行一點測試記錄,因為這種配置是最常見的,在實際中ip1和ip2是主從關系,假設localhost1對應db1,localhost2對應db2


這樣ip1和ip2中存儲了db1的分片數據,ip3中存儲了db2的分片數據


在寫操作的時候,mycat會將對應數據寫入ip1,通過主從通過到ip2, 另一部分數據寫入ip3


在讀操作的時候,mycat會從ip2和ip3中獲取對應數據合並後返回客戶端(假設是獲取表所有數據),


假設在此時在ip2上新增數據,因為mycat要求寫入的數據必須符合對應表的rule規則,比如rule設置了id字段只能取值10000和10010(mycat的例子),所以通過mycat是無法寫入20000的值的,但是如果此時直接在ip2上寫入20000,再select是可以讀出來這條不合理的數據的,這也證明了mycat的讀寫分離功能




在實際運用中,應該是設置好有部分的數據庫服務器是用來作為分庫分表服務器的,有部分數據庫服務器則是用來作為讀服務器的


也就是說在不同dataHost中的writeHost之間是沒有關系的,只負責保存分配到本地的數據記錄,而不同dataHost之間的readHost之間也是沒有關系的,只負責同步對應writeHost的數據(既然writeHost都沒關系,readHost肯定是沒關系的)


在本文的測試中,由於服務器數量肯定達不到要求,在測試中實際上是這樣的在本地有3003和3009兩個Mysql服務實例,代表兩個數據庫服務器(在IO上存在競爭)



db1 - writeHost (3003) - readHost(3009)


db2 - writeHost(3009)




在這種配置下,3003服務器上只需要有db1的數據庫即可,3009服務器上需要有db2的數據庫(用來作為writeHost),同樣因為需要作為3003服務器的從服務器,所有需要有db1的數據庫


假設寫入的數據為(1,‘Rod‘, 10000), (2, ‘Whu‘, 10010) 根據employee表在sharding_id字段上分片規則,Rod數據會存在db1中,Whu數據會存在db2中


這樣在寫入的時候如下過程:


(1,‘Rod‘, 10000) -Mycat - 3003 db1 -- 主從同步 -- 3009 db1


(2, ‘Whu‘, 10010) -Mycat - 3009 db2


在讀取的時候如下過程:


3009 db1 - (1,‘Rod‘, 10000) - Mycat ,因為配置了讀寫分離,所以會db1 - writeHost (3003) - readHost(3009)配置的readHost去獲取數據


3009 db2 - (2,‘Whu‘, 10010) - Mycat




當然也可以在3009的db1數據庫中加入新的數據,這樣通過mycat去獲取的時候也會包括這條新數據




本文主要是在測試Mycat的讀寫分離和分庫分片後進行的知識點記錄,後續需要更多的使用Mycat工具,運用到實際開發。

Mycat 讀寫分離+分庫分表