mycat 讀寫分離+分庫分表+全局表

一、mycat讀寫分離
Mycat的讀寫分離是建立在Mysq的主從複製的基礎上的

#修改配置文件 schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
        </schema>
        <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                             /> -->
        <dataNode name="dn1" dataHost="host1" database="test1" />
        <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.171.135:3306" user="root"
                                   password="123">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="192.168.171.146:3306" user="root" password="123" />
                </writeHost>
        </dataHost>
</mycat:schema>

設置有兩種,如下:
(1) 設置balance="1"與writeType=“0”

Balance參數設置:
修改的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”,所有讀請求隨機的分發到 readhost 執行, writerHost 不負擔讀壓力

WriteType參數設置:

writeType=“0”, 所有寫操作都發送到可用的writeHost上。
writeType=“1”,所有寫操作都隨機的發送到readHost。
writeType=“2”,所有寫操作都隨機的在writeHost、readhost分上發。

“readHost是從屬於writeHost的,即意味着它從那個writeHost獲取同步數據,因此,當它所屬的writeHost宕機 了,則它也不會再參與到讀寫分離中來,即“不工作了”,這是因爲此時,它的數據已經“不可靠”了。基於這個考 慮,目前mycat 1.3和1.4版本中,若想支持MySQL一主一從的標準配置,並且在主節點宕機的情況下,從節點 還能讀取數據,則需要在Mycat裏配置爲兩個writeHost並設置banlance=1。”

(2) 設置switchType=“2” 與slaveThreshold=“100”

switchType 目前有三種選擇:
-1:表示不自動切換
1 :默認值,自動切換
2 :基於MySQL主從同步的狀態決定是否切換
“Mycat心跳檢查語句配置爲 show slave status ,dataHost 上定義兩個新屬性: switchType=“2” 與 slaveThreshold=“100”,此時意味着開啓MySQL主從複製狀態綁定的讀寫分離與切換機制。Mycat心跳機制通過 檢測 show slave status 中的 “Seconds_Behind_Master”, “Slave_IO_Running”, “Slave_SQL_Running” 三個字段來 確定當前主從同步的狀態以及Seconds_Behind_Master主從複製時延。“
二、垂直拆分–分庫
一個數據庫由很多表的構成,每個表對應着不同的業務,垂直切分是指按照業務將表進行分類, 分佈到不同 的 數據庫上面,這樣也就將數據或者說壓力分擔到不同的庫上面, 如何劃分表 分庫的原則: 有緊密關聯關係的 表應該在一個庫裏,相互沒有關聯關係的表可以分到不同的庫裏。

#修改 schema 配置文件
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
         <table name="customer" dataNode="dn2"></table>
        </schema>
        <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
                             /> -->
        <dataNode name="dn1" dataHost="host1" database="test1" />
        <dataNode name="dn2" dataHost="host2" database="test1" />
        <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="192.168.171.135:3306" user="root"
                                   password="123">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="192.168.171.146:3306" user="root" password="123" />
                </writeHost>
        </dataHost>
        <dataHost name="host2" maxCon="1000" minCon="10" balance="0"  
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                 <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                       <writeHost host="hostM2" url="192.168.171.131:3306" user="root" password="123">  
                </writeHost>
         </dataHost>
</mycat:schema>

#登錄到數據庫,創建表
[root@mycatconf]#mysql -umycat -p123456 -h192.168.171.134 -P8066
mysql>CREATE TABLE customer( id INT AUTO_INCREMENT, NAME VARCHAR(200), PRIMARY KEY(id) ); 
mysql>CREATE TABLE orders( id INT AUTO_INCREMENT, order_type INT, customer_id INT, amount DECIMAL(10,2), PRIMARY KEY(id) ); 
mysql>CREATE TABLE orders_detail( id INT AUTO_INCREMENT, detail VARCHAR(2000), order_id INT, PRIMARY KEY(id) ); 
mysql>CREATE TABLE dict_order_type( id INT AUTO_INCREMENT, order_type VARCHAR(200), PRIMARY KEY(id) ); 
#以上四個表如何分庫?客戶表分在一個數據庫,另外三張都需要關聯查詢,分在另外一個數據庫。 
mysql> show tables;
+----+--------------+
|Tables_in_xxq  |
+----+--------------+
|  dict_order_type|
|  orders               |
|  orders_detail    |
|  tab1                    |
+----+---------------+
mysql>show tables;
+----+--------------+
|  customer          |
+----+---------------+

三、水平拆分–分表
相對於垂直拆分,水平拆分不是將表做分類,而是按照某個字段的某種規則來分散到多個庫之中, 每個表中 包 含一部分數據。簡單來說,我們可以將數據的水平切分理解爲是按照數據行的切分,就 是將表中的某些行切分 到一個數據庫,而另外的某些行又切分到其他的數據庫中. 實現分表 選擇要拆分的表 MySQL 單表存儲數據條數是有瓶頸的,單表達到 1000 萬條數據就達到了瓶頸,會 影響查詢效率, 需要進行水平拆分(分表) 進行優化。 例如:例子中的 orders、 orders_detail 都已經達到 600 萬行數據,需要進行分表優化。 分表字段 以 orders 表爲例,可以根據不同自字段進行分表

在這裏插入圖片描述

#修改配置文件 schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 
<mycat:schema xmlns:mycat="http://io.mycat/">        
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">           
<table name="customer" dataNode="dn2"></table>        
<table name="orders" dataNode="dn1,dn2" rule="mod_rule">      # 爲 orders 表設置數據節點爲 dn1、 dn2, 並指定分片規則爲 mod_rule(自定義的名字)

                                    <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" />                
                                    </table>        
                                    </schema>        
                                    <dataNode name="dn1" dataHost="host1" database="test1" />      
                                    <dataNode name="dn2" dataHost="host2" database="test1" />       
                                    <dataHost name="host1" maxCon="1000" minCon="10" balance="1"                           writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">             
                                    <heartbeat>select user()</heartbeat>             
                                    <writeHost host="hostM1" url="192.168.171.135:3306" user="root"                                    password="123">                
                                    <readHost host="hostS1" url="192.168.171.145:3306" user="root" password="123" />               
                                    </writeHost> 

        </dataHost>       
                <dataHost name="host2" maxCon="1000" minCon="10" balance="0" 
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">                
                                                    <heartbeat>select user()</heartbeat>               
                                                    <writeHost host="hostM1" url="192.168.171.132:3306" user="root"                                    password="123">               
                                                    </writeHost> 

        </dataHost> 
                </mycat:schema> 
#修改配置文件 rule.xml
#在 rule 配置文件裏新增分片規則 mod_rule,並指定規則適用字段爲 customer_id, 
#還有選擇分片算法 mod-long(對字段求模運算) , customer_id 對兩個節點求模,根據結果分 片 
#配置算法 mod-long 參數 count 爲 2,兩個節點 

<tableRule name="mod_rule"> 
<rule>
<columns>customer_id</columns> 
<algorithm>mod-long</algorithm>
</rule> 
</tableRule> 
…
<function name="mod-long" class="io.mycat.route.function.PartitionByMod"> 
<!-- how many data nodes --> 
<property name="count">2</property> 
</function> 

在數據節點 dn2 上建 orders 表

mysql>CREATE TABLE orders_detail( id INT AUTO_INCREMENT, detail VARCHAR(2000), order_id INT, PRIMARY KEY(id) ); 

重啓 Mycat,讓配置生效

mysql> insert into orders_detail(id,detail,order_id) values (1,'detail',1); 

mysql> insert into orders_detail(id,detail,order_id) values (2,'detail',2); 

mysql> insert into orders_detail(id,detail,order_id) values (3,'detail',3); 

mysql> insert into orders_detail(id,detail,order_id) values (4,'detail',4); )

mysql> insert into orders_detail(id,detail,order_id) values (5,'detail',5); 

mysql> insert into orders_detail(id,detail,order_id) values (6,'detail',6); 

訪問 Mycat 實現分片

mysql> select o.*,od.detail from orders as   o inner join orders_detail as   od on o.id=od.order_id; 
+----+------------+-------------+-----------+--------+ 
| id | order_type | customer_id | amount    | detail | 
+----+------------+-------------+-----------+--------+ 
|  1 |        101 |         100 | 100100.00 | detail | 
|  2 |        101 |         100 | 100300.00 | detail | 
|  6 |        102 |         100 | 100020.00 | detail | 
|  3 |        101 |         101 | 120000.00 | detail | 
|  4 |        101 |         101 | 103000.00 | detail | 
|  5 |        102 |         101 | 100400.00 | detail | 
+----+------------+-------------+-----------+--------+ 

四、全局表

在分片的情況下,當業務表因爲規模而進行分片以後,業務表與這些附屬的字典表之間的關聯, 就 成了比較 棘手的問題,考慮到字典表具有以下幾個特性:
① 變動不頻繁
② 數據量總體變化不大
③ 數據規模不 大,很少有超過數十萬條記錄

Mycat 定義了一種特殊的表,稱之爲“全局表”,全局表具有以下特性:
① 全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的數據一致性
② 全局表的查詢操作,只從 一個節點獲取
③ 全局表可以跟任何一個表進行 JOIN 操作 將字典表或者符合字典表特性的一些表定義爲全局 表,則從另外一個方面,很好的解決了數據 JOIN 的難題。 通過全局表+基於 E-R 關係的分片策略, Mycat 可 以滿足 80%以上的企業應用開發

#修改 schema.xml 配置文件 
<table name="customer" dataNode="dn2"></table> 
                              <table name="orders" dataNode="dn1,dn2" rule="mod_rule" > 
                                          <childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id" /> 
                                                                                               </table> 
                                        <table name="dict_order_type" dataNode="dn1,dn2" type="global"> 
    </table> 
    #在dn2 創建 dict_order_type 表 
    mysql>CREATE TABLE dict_order_type( id INT AUTO_INCREMENT, order_type VARCHAR(200), PRIMARY KEY(id) );
    #重啓 Mycat 
    #訪問 Mycat 向 dict_order_type 表插入數據 
    mysql> insert into dict_order_type (id,order_type) values (101,'type1'); 

mysql> insert into dict_order_type (id,order_type) values (102,'type2'); 
 mysql> select * from dict_order_type ; 
 +-----+------------+ 
 | id  | order_type | 
 +-----+------------+ 
 | 101 | type1      | 
 | 102 | type2      | 
 +-----+------------+ 
 2 rows in set (0.05 sec) 

常用分片規則
1、 取模 此規則爲對分片字段求摸運算。 也是水平分表最常用規則。 5.1 配置分表中, orders 表採用了此規 則。
2、 分片枚舉 通過在配置文件中配置可能的枚舉 id,自己配置分片,本規則適用於特定的場景,比如有些 業務 需要按照省份或區縣來做保存,而全國省份區縣固定的,這類業務使用本條規則。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章