mycat mysql分佈式中間件
1、MyCAT概述
1.1 背景
隨着傳統的數據庫技術日趨成熟、計算機網絡技術的飛速發展和應用範圍的擴充,數據庫應用已經普遍建立於計算機網絡之上。這時集中式數據庫系統表現出它的不足:
(1)集中式處理,勢必造成性能瓶頸;
(2)應用程序集中在一臺計算機上運行,一旦該計算機發生故障,則整個系統受到影響,可靠性不高;
(3)集中式處理引起系統的規模和配置都不夠靈活,系統的可擴充性差。
在這種形勢下,集中式數據庫將向分佈式數據庫發展。
1.2 發展歷程
MyCAT的誕生,要從其前身Amoeba和Cobar說起。
Amoeba(變形蟲)項目,該開源框架於2008年開始發佈一款 Amoeba for MySQL軟件。這個軟件致力於MySQL的分佈式數據庫前端代理層,它主要在應用層訪問MySQL的時候充當SQL路由功能,專注於分佈式數據庫代理層(Database Proxy)開發。座落與 Client、DB Server(s)之間,對客戶端透明。具有負載均衡、高可用性、SQL過濾、讀寫分離、可路由相關的到目標數據庫、可併發請求多臺數據庫合併結果。 通過Amoeba你能夠完成多數據源的高可用、負載均衡、數據切片的功能,目前Amoeba已在很多企業的生產線上面使用。
阿里巴巴於2012年6月19日,正式對外開源的數據庫中間件Cobar,前身是早已經開源的Amoeba,不過其作者陳思儒離職去盛大之後,阿里巴巴內部考慮到Amoeba的穩定性、性能和功能支持,以及其他因素,重新設立了一個項目組並且更換名稱爲Cobar。Cobar 是由 Alibaba 開源的 MySQL 分佈式處理中間件,它可以在分佈式的環境下看上去像傳統數據庫一樣提供海量數據服務。
Cobar自誕生之日起, 就受到廣大程序員的追捧,但是自2013年後,幾乎沒有後續更新。在此情況下,MyCAT應運而生,它基於阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能,以及衆多成熟的使用案例使得MyCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,MyCAT能看到更遠。目前MyCAT的最新發布版本爲1.3.0.2版本。
1.3 介紹
1.3.1 MyCat的下載方式
可以通過Git或官網下載,地址見首頁。
1.3.2 什麼是MyCat?
簡單的說,MyCAT就是:
- 一個新穎的數據庫中間件產品;
- 一個徹底開源的、面向企業應用開發的“大數據庫集羣”;
- 支持事務、ACID、可以替代MySQL的加強版數據庫;
- 一個可以視爲“MySQL”集羣的企業級數據庫,用來替代昂貴的Oracle集羣;
- 一個融合內存緩存技術、Nosql技術、HDFS大數據的新型SQL Server;
- 結合傳統數據庫和新型分佈式數據倉庫的新一代企業級數據庫產品。
1.3.3 MyCat的目標
MyCAT的目標是:低成本的將現有的單機數據庫和應用平滑遷移到“雲”端,解決數據存儲和業務規模迅速增長情況下的數據瓶頸問題。
1.3.4 MyCat的關鍵特性
· 支持 SQL 92標準
支持Mysql集羣,可以作爲Proxy使用
支持JDBC連接ORACLE、DB2、SQL Server,將其模擬爲MySQL Server使用
支持NoSQL數據庫
支持galera for mysql集羣,percona-cluster或者mariadb cluster,提供高可用性數據分片集羣
自動故障切換,高可用性
支持讀寫分離,支持Mysql雙主多從,以及一主多從的模式
支持全局表,數據自動分片到多個節點,用於高效表關聯查詢
支持獨有的基於E-R 關係的分片策略,實現了高效的表關聯查詢
支持一致性Hash分片,有效解決分片擴容難題
多平臺支持,部署和實施簡單
支持Catelet開發,類似數據庫存儲過程,用於跨分片複雜SQL的人工智能編碼實現,143行Demo完成跨分片的兩個表的JION查詢。
支持NIO與AIO兩種網絡通信機制,Windows下建議AIO,Linux下目前建議NIO
支持Mysql存儲過程調用
以插件方式支持SQL攔截和改寫
支持自增長主鍵、支持Oracle的Sequence機制
1.3.5 MyCat的優勢
· 基於阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能,以及衆多成熟的使用案例使得MyCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,能看到更遠。
· 廣泛吸取業界優秀的開源項目和創新思路,將其融入到MyCAT的基因中,使得MyCAT在很多方面都領先於目前其他一些同類的開源項目,甚至超越某些商業產品。
· MyCAT背後有一隻強大的技術團隊,其參與者都是5年以上資深軟件工程師、架構師、DBA等,優秀的技術團隊保證了MyCAT的產品質量。
· MyCAT並不依託於任何一個商業公司,因此不像某些開源項目,將一些重要的特性封閉在其商業產品中,使得開源項目成了一個擺設。
1.3.6 MyCat的長期路線
- 在支持Mysql的基礎上,後端增加更多的開源數據庫和商業數據庫的支持,包括原生支持PosteSQL、FireBird等開源數據庫,以及通過JDBC等方式間接支持其他非開源的數據庫如Oracle、DB2、SQL Server等
- 實現更爲智能的自我調節特性,如自動統計分析SQL,自動創建和調整索引,根據數據表的讀寫頻率,自動優化緩存和備份策略等
- 實現更全面的監控管理功能
- 與HDFS集成,提供SQL命令,將數據庫裝入HDFS中並能夠快速分析
- 集成優秀的開源報表工具,使之具備一定的數據分析的能力
1.4 總體架構
MyCAT的架構如下圖所示:
MyCAT使用MySQL的通訊協議模擬成一個MySQL服務器,並建立了完整的Schema(數據庫)、Table (數據表)、User(用戶)的邏輯模型,並將這套邏輯模型映射到後端的存儲節點DataNode(MySQL Instance)上的真實物理庫中,這樣一來,所有能使用MySQL的客戶端以及編程語言都能將MyCAT當成是MySQLServer來使用,不必開發新的客戶端協議。
當MyCAT收到一個客戶端發送的SQL請求時,會先對SQL進行語法分析和檢查,分析的結果用於SQL路由,SQL路由策略支持傳統的基於表格的分片字段方式進行分片,也支持獨有的基於數據庫E-R關係的分片策略,對於路由到多個數據節點(DataNode)的SQL,則會對收到的數據集進行“歸併”然後輸出到客戶端。
SQL執行的過程,簡單的說,就是把SQL通過網絡協議發送給後端的真正的數據庫上進行執行,對於MySQL Server來說,是通過MySQL網絡協議發送報文,並解析返回的結果,若SQL不涉及到多個分片節點,則直接返回結果,寫入客戶端的SOCKET流中,這個過程是非阻塞模式(NIO)。
DataNode是MyCAT的邏輯數據節點,映射到後端的某一個物理數據庫的一個Database,爲了做到系統高可用,每個DataNode可以配置多個引用地址(DataSource),當主DataSource被檢測爲不可用時,系統會自動切換到下一個可用的DataSource上,這裏的DataSource即可認爲是Mysql的主從服務器的地址。
1.5 邏輯庫
與任何一個傳統的關係型數據庫一樣,MyCAT也提供了“數據庫”的定義,並有用戶授權的功能,下面是MyCAT邏輯庫相關的一些概念:
- schema:邏輯庫,與MySQL中的Database(數據庫)對應,一個邏輯庫中定義了所包括的Table。
- table:表,即物理數據庫中存儲的某一張表,與傳統數據庫不同,這裏的表格需要聲明其所存儲的邏輯數據節點DataNode,這是通過表格的分片規則定義來實現的,table可以定義其所屬的“子表(childTable)”,子表的分片依賴於與“父表”的具體分片地址,簡單的說,就是屬於父表裏某一條記錄A的子表的所有記錄都與A存儲在同一個分片上。
- 分片規則:是一個字段與函數的捆綁定義,根據這個字段的取值來返回所在存儲的分片(DataNode)的序號,每個表格可以定義一個分片規則,分片規則可以靈活擴展,默認提供了基於數字的分片規則,字符串的分片規則等。
- dataNode: MyCAT的邏輯數據節點,是存放table的具體物理節點,也稱之爲分片節點,通過DataSource來關聯到後端某個具體數據庫上,一般來說,爲了高可用性,每個DataNode都設置兩個DataSource,一主一從,當主節點宕機,系統自動切換到從節點。
- dataHost:定義某個物理庫的訪問地址,用於捆綁到dataNode上。
MyCAT目前通過配置文件的方式來定義邏輯庫和相關配置:
· MYCAT_HOME/conf/schema.xml中定義邏輯庫,表、分片節點等內容;
· MYCAT_HOME/conf/rule.xml中定義分片規則;
· MYCAT_HOME/conf/server.xml中定義用戶以及系統相關變量,如端口等。下圖給出了MyCAT 一個可能的邏輯庫到物理庫(MySQL的完整映射關係),可以看出其強大的分片能力以及靈活的Mysql集羣整合能力。
2、基本使用教程
2.1 下載和安裝
MyCAT使用Java開發,因爲用到了JDK 7的部分功能,所以在使用前請確保安裝了JDK 7.0,並設置了正確的Java環境變量(可在命令行窗口輸入:“java –version”獲知是否安裝成功,以及獲取JDK的版本)。
安裝完成後,需要添加MYCAT_HOME環境變量,值對應MyCAT安裝的根目錄。
目錄說明見下表所示:
--bin 啓動目錄
--conf 配置文件存放配置文件:
--server.xml:是Mycat服務器參數調整和用戶授權的配置文件。
--schema.xml:是邏輯庫定義和表以及分片定義的配置文件。
--rule.xml: 是分片規則的配置文件,分片規則的具體一些參數信息單獨存放爲文件,也在這個目錄下,配置文件修改需要重啓MyCAT。
--log4j.xml: 日誌存放在logs/log中,每天一個文件,日誌的配置是在conf/log4j.xml中,根據自己的需要可以調整輸出級別爲debug
debug級別下,會輸出更多的信息,方便排查問題。
--autopartition-long.txt,partition-hash-int.txt,sequence_conf.properties,
sequence_db_conf.properties 分片相關的id分片規則配置文件
--lib MyCAT自身的jar包或依賴的jar包的存放目錄。
--logs MyCAT日誌的存放目錄。日誌存放在logs/log中,每天一個文件
2.2 啓動和停止
啓動前,一般需要修改JVM配置參數,打開conf/wrapper.conf文件,如下行的內容爲2G和2048,可根據本機配置情況修改爲512M或其它值。
wrapper.java.additional.6=-Dcom.sun.management.jmxremote
wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984
wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false
# Initial Java Heap Size (in MB)
#wrapper.java.initmemory=3
wrapper.java.initmemory=512
# Maximum Java Heap Size (in MB)
#wrapper.java.maxmemory=64
wrapper.java.maxmemory=512
在命令行窗口中進入MyCAT安裝解壓文件下的bin目錄,輸入如下命令可安裝(可選)、啓動和停止MyCAT,參考結果如下所示:
./mycat start 啓動
./mycat stop 停止
./mycat console 前臺運行
./mycat install 添加到系統自動啓動(暫未實現)
./mycat remove 取消隨系統自動啓動(暫未實現)
./mycat restart 重啓服務
./mycat pause 暫停
./mycat status 查看啓動狀態
win下:直接運行startup_nowrap.bat,如果出現閃退,在cmd 命令行運行,查看出錯原因。
2.3 簡單使用教程
2.3.1 安裝MySQL以及客戶端
安裝MySQL服務器和MySQL客戶端,筆者使用的MySQL服務器是免安裝版本:mysql-noinstall-5.1.73-winx64,MySQL客戶端是:Navicat for MySQL,免安裝版本安裝方法請參考:http://blog.csdn.net/q98842674/article/details/12094777,不再贅述。
2.3.2 創建數據庫和表
創建user、和pay 兩個個數據庫,並分別建立表結構。
2.3.3 垂直切分
2.3.3.1 垂直切分定義
數據的垂直切分,也可以稱爲縱向切分。將數據庫想象成由很多個一大塊一大塊的“數據塊”(表)組成,垂直地將這些“數據塊”切開,然後把它們分散到多臺數據庫主機上面。這樣的切分方法就是垂直(縱向)的數據切分。
一個架構設計較好的應用系統,其總體功能肯定是由很多個功能模塊所組成的,而每一個功能模塊所需要的數據對應到數據庫中就是一個或多個表。而在架構設計中,各個功能模塊相互之間的交互點越統一、越少,系統的耦合度就越低,系統各個模塊的維護性及擴展性也就越好。這樣的系統,實現數據的垂直切分也就越容易。
2.3.3.2 優缺點
垂直切分優點:
(1)數據庫的拆分簡單明瞭,拆分規則明確;
(2)應用程序模塊清晰明確,整合容易;
(3)數據維護方便易行,容易定位。
垂直切分缺點:
(1)部分表關聯無法在數據庫級別完成,要在程序中完成;
(2)對於訪問極其頻繁且數據量超大的表仍然存在性能瓶頸,不一定能滿足要求;
(3)事務處理相對複雜;
(4)切分達到一定程度之後,擴展性會受到限制;
(5)過度切分可能會帶來系統過於複雜而難以維護。
2.3.3.3 垂直切分實現
在如下的實例中,需要將
編輯MYCAT_HOME/conf/schema.xml文件,修改dataHost和schema對應的連接信息,user,pay 垂直切分後的配置如下所示:
<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">
<schema name="user" checkSQLschema="false" sqlMaxLimit="100" dataNode="user" />
<schema name="pay" checkSQLschema="false" sqlMaxLimit="100" dataNode="pay" />
<dataNode name="user" dataHost="host" database="user" />
<dataNode name="pay" dataHost="host" database="pay" />
<dataHost name="host" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select 1</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="root" />
<writeHost host="hostM2" url="192.168.0.3:3306" user="root" password="root" />
</dataHost>
</mycat:schema>
注意:writeHost/readHost中的location,user,password的值需要根據實際的MySQL的連接信息進行修改。
查看conf/server.xml文件,該文件是Mycat服務器參數調整和用戶授權的配置文件,默認的MyCat的數據庫連接的用戶名/密碼爲mycat/mycat,文件內容參考如下:<?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>
</system>
<user name="mycat">
<property name="password">mycat</property>
<property name="schemas">user,pay</property>
</user>
</mycat:server>
上述文件中的schemas屬性需要配置對應的schema(在schema.xml)中進行配置。
重啓MyCAT,使用MySQL客戶端連接MyCAT,需要注意的是,默認數據端口爲8066,管理端口爲9066,在MySQL客戶端連接MyCAT時,注意填寫端口爲8066,用戶名/密碼根據server.xml中的配置進行填寫。
連接後可查看後端連接的三個數據庫,如下圖所示:
2.3.4 水平分庫
2.3.4.1 水平切分定義
水平切分所指的是通過一系列的切分規則將數據水平分佈到不同的DB或table中,在通過相應的DB路由 或者table路由規則找到需要查詢的具體的DB或者table以進行Query操作,比如根據用戶ID將用戶表切分到多臺數據庫上。
將某個訪問極其頻繁的表再按照某個字段的某種規則來分散到多個表之中,每個表中包含一部分數據。
例如,所有數據都是和用戶關聯的,那麼我們就可以根據用戶來進行水平拆分,將不同用戶的數據切分到不同的數據庫中。
現在互聯網非常火爆的web 2.0類型的網站,基本上大部分數據都能夠通過會員用戶信息關聯上,可能很多核心表都非常適合通過會員ID來進行數據的水平切分。而像論壇社區討論系統,就更容易切分了,非常容易按照論壇編號來進行數據的水平切分。切分之後基本上不會出現各個庫之間的交互。
2.3.4.2 優缺點
水平切分的優點:
表關聯基本能夠在數據庫端全部完成;
不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;
應用程序端整體架構改動相對較少;
事務處理相對簡單;
只要切分規則能夠定義好,基本上較難遇到擴展性限制。
水平切分的缺點:
切分規則相對更爲複雜,很難抽象出一個能夠滿足整個數據庫的切分規則;
後期數據的維護難度有所增加,人爲手工定位數據更困難;
應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分造成一定的困難。
2.3.4.3 水平切分實現
在一般的應用系統中,用戶表及其密切相關的關聯表,可根據“用戶表”(eg:t_user)中的“用戶ID”(user_id)進行水平切分,並基於MyCAT的E-R關係分片策略將其密切相關的表(eg:t_user_class_rel)也分到對應的庫中。
(1)創建庫,表結構
在建表語句參考如下:
CREATE DATABASE IF NOT EXISTS `mycat_node1` ;
/**
user 用戶表
*/
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`user_id` int(11) NOT NULL COMMENT '用戶ID',
`receive_address` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '收貨地址',
`create_time` datetime NOT NULL,
`province_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='用戶信息表';
/**
`t_area` 全局表
*/
CREATE TABLE `t_area` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`caller` varchar(16) CHARACTER SET utf8 DEFAULT NULL COMMENT '調用方系統表示',
`province_code` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '省份編碼',
`area_code` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '區域編碼',
`area_name` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '區域名稱',
`parent_area_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '父區域編碼',
`create_time` datetime NOT NULL COMMENT '創建時間',
`modify_time` datetime DEFAULT NULL COMMENT '修改時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3792 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/**
user 節點測試表
*/
DROP TABLE IF EXISTS `t_node`;
CREATE TABLE `t_node` (
`vid` int(11) NOT NULL COMMENT 'ID',
`user_id` int(11) NOT NULL COMMENT '用戶ID',
`note` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'note',
`create_time` datetime NOT NULL,
PRIMARY KEY (`vid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='note表';
首先配置schema.xml文件,添加mycat_node1數據庫的dataNode設置,並添加t_user和t_area表的schema設置,本次配置了雙主,讀寫分離配置,
同一個表多個分片的配置可以用dataNode="dn$1-100" 通配方式。
修改後的schema.xml文件內容如下所示:
- <?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://org.opencloudb/"><schema name="mycat" checkSQLschema="true" sqlMaxLimit="100"><table name="t_user" primaryKey="user_id" dataNode="dn1,dn2" rule="rule1" /> <table name="t_node" primaryKey="vid" autoIncrement="true" dataNode="dn1,dn2" rule="rule1" /><table name="t_area" type="global" primaryKey="ID" dataNode="dn1,dn2" /></schema><dataNode name="dn1" dataHost="jdbchost" database="mycat_node1" /><dataNode name="dn2" dataHost="jdbchost2" database="mycat_node1" /><dataHost name="jdbchost" maxCon="500" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native"><heartbeat>select 1</heartbeat><writeHost host="maste1" url="192.168.0.1:3306" user="root" password="root"> <!-- <readHost host="readshard" url="192.168.0.2:3306" user="root" password="root"/> --></writeHost><writeHost host="maste2" url="192.168.0.3:3306" user="root" password="root"> <!-- <readHost host="readshard" url="192.168.0.4:3306" user="root" password="root"/> --></writeHost></dataHost><!-- --><dataHost name="jdbchost2" maxCon="500" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native"><heartbeat>select 1</heartbeat><writeHost host="maste1" url="192.168.0.5:3306" user="root" password="root"> <!-- <readHost host="readshard" url="192.168.0.6:3306" user="root" password="root"/> --></writeHost><writeHost host="maste2" url="192.168.0.6:3307" user="root" password="root"> <!-- <readHost host="readshard" url="192.168.0.8:3306" user="root" password="root"/> --></writeHost></writeHost></dataHost></mycat:schema>
(3)配置rule.xml文件
在schema.xml的文件內容中可看到t_user表指定的分片規則是rule1,需要在conf/rule.xml文件中設置rule1的規則爲根據user_id進行分片,並按照類“org.opencloudb.route.function.PartitionByLong”的規則進行分片。
該文件的參考內容如下所示:
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://org.opencloudb/">
<tableRule name="rule1">
<rule>
<columns>user_id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
<property name="partitionCount">2</property>
<property name="partitionLength">512</property>
</function>
</mycat:rule>
(4)配置server.xml文件
在server.xml文件中的schemas屬性中添加test_mycat的schema。修改後的文件如下所示:
<mycat:server xmlns:mycat="http://org.opencloudb/">
<system>
<property name="sequnceHandlerType">0</property>
</system>
<user name="mycat">
<property name="password">mycat</property>
<property name="schemas">mycat</property>
</user>
</mycat:server>
(5)水平切分測試
重啓MyCAT,使用MySQL客戶端連接後,連接後可在mycat數據庫下看到t_user和t_area,t_node表,如下圖所示:
在MySQL客戶端連接的MyCat的test_mycat數據庫的t_user表運行如下插入語句,插入2000條數據:
INSERT INTO `t_user` VALUES ('2', '廣州市越秀區廣州大道中599號', '2014-07-17 10:53:17', 'GD');
INSERT INTO `t_user` VALUES ('3', '廣州市越秀區廣州大道中599號', '2014-07-17 10:53:17', 'GD');
INSERT INTO `t_user` VALUES ('4', '廣州市越秀區廣州大道中599號', '2014-07-17 10:53:17', 'GD');
INSERT INTO `t_user` VALUES ('5', '廣州市越秀區廣州大道中599號', '2014-07-17 10:53:17', 'GD');
……
INSERT INTO `t_user` VALUES (2000, '廣州市越秀區廣州大道中599號', '2014-07-17 10:54:37', 'GD');
2.3.5 讀寫分離
2.3.5.1 讀寫分離定義
爲了確保數據庫產品的穩定性,很多數據庫擁有雙機熱備功能。也就是,第一臺數據庫服務器,是對外提供增刪改查業務的生產服務器;第二臺數據庫服務器,僅僅接收來自第一臺服務器的備份數據。一般來說,爲了配置方便,以及穩定性,這兩臺數據庫服務器,都用的是相同的配置。
在實際運行中,第一臺數據庫服務器的壓力,遠遠大於第二臺數據庫服務器。因此,很多人希望合理利用第二臺數據庫服務器的空閒資源。
從數據庫的基本業務來看,數據庫的操作無非就是增刪改查這4個操作。但對於“增刪改”這三個操作,如果是雙機熱備的環境中做,一臺機器做了這三個操作的某一個之後,需要立即將這個操作,同步到另一臺服務器上。出於這個原因,第二臺備用的服務器,就只做了查詢操作。進一步,爲了降低第一臺服務器的壓力,乾脆就把查詢操作全部丟給第二臺數據庫服務器去做,第一臺數據庫服務器就只做增刪改了。
2.3.5.2 優缺點
優點:合理利用從數據庫服務器的空閒資源。
缺點:本來第二臺數據庫服務器,是用來做熱備的,它就應該在一個壓力非常小的環境下,保證運行的穩定性。而讀寫分離,卻增加了它的壓力,也就增加了不穩定性。因此,讀寫分離,實質上是一個在資金比較缺乏,但又需要保證數據安全的需求下,在雙機熱備方案上,做出的一種折中的擴展方案。
2.3.5.3 讀寫分離實現
MyCAT的讀寫分離機制如下:
- 事務內的SQL,全部走寫節點,除非某個select語句以註釋/*balance*/開頭
- 自動提交的select語句會走讀節點,並在所有可用讀節點中間隨機負載均衡
- 當某個主節點宕機,則其全部讀節點都不再被使用,因爲此時,同步失敗,數據已經不是最新的,MyCAT會採用另外一個主節點所對應的全部讀節點來實現select負載均衡。
- 當所有主節點都失敗,則爲了系統高可用性,自動提交的所有select語句仍將提交到全部存活的讀節點上執行,此時系統的很多頁面還是能出來數據,只是用戶修改或提交會失敗。
例如將本機作爲寫庫,10.18.96.133作爲讀庫,MyCAT的讀寫分離的配置如下:
writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3306" user="root" password="">
<readHost host="hostM2" url="10.18.96.133:3306" user="test" password="test" />
</writeHost>
</dataHost>
dataHost的balance屬性設置爲:
- 0,不開啓讀寫分離機制
- 1,全部的readHost與stand by writeHost參與select語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,並且M1與 M2互爲主備),正常情況下,M2,S1,S2都參與select語句的負載均衡。
- 2,所有的readHost與writeHost都參與select語句的負載均衡,也就是說,當系統的寫操作壓力不大的情況下,所有主機都可以承擔負載均衡。
一個dataHost元素,表明進行了數據同步的一組數據庫,DBA需要保證這一組數據庫服務器是進行了數據同步複製的。writeHost相當於Master DB Server,而其下的readHost則是與從數據庫同步的Slave DB Server。當dataHost配置了多個writeHost的時候,任何一個writeHost宕機,Mycat 都會自動檢測出來,並嘗試切換到下一個可用的writeHost。
在沒有配置數據同步複製的情況下,重啓後進行測試,可使用MySQL客戶端直接連接讀庫,插入幾條數據後,使用MySQL客戶端連接MyCat,運行select語句驗證是否在讀庫上執行。
多主,多讀寫分離參考:
其中分爲dn1,dn2兩個分片,每個分片有兩個寫入,寫入之間開啓mysql開啓2進制複製,mycat會從當前可用的寫入host隨機獲取一個寫入,mycat在任何時候 只會單點寫入。如果要開啓讀寫分離在放開註釋read配置,balance=1或2。
writeType=1 代表所有節點都是寫入寫入,慎重開啓,多節點寫入順序爲默認寫入根據配置順序,第一個掛掉切換另一個。
2.3.6 全局表
2.3.6.1 全局表定義
一個真實的業務系統中,往往存在大量的類似字典表的表格,它們與業務表之間可能有關係,這種關係,可以理解爲“標籤”,而不應理解爲通常的“主從關係”,這些表基本上很少變動,可以根據主鍵ID進行緩存,下面這張圖說明了一個典型的“標籤關係”圖:
在分片的情況下,當業務表因爲規模而進行分片以後,業務表與這些附屬的字典表之間的關聯,就成了比較棘手的問題,考慮到字典表具有以下幾個特性:
- 變動不頻繁;
- 數據量總體變化不大;
- 數據規模不大,很少有超過數十萬條記錄。
鑑於此,MyCAT定義了一種特殊的表,稱之爲“全局表”,全局表具有以下特性:
- 全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的數據一致性
- 全局表的查詢操作,只從一個節點獲取
- 全局表可以跟任何一個表進行JOIN操作
將字典表或者符合字典表特性的一些表定義爲全局表,則從另外一個方面,很好的解決了數據JOIN的難題。通過全局表+基於E-R關係的分片策略,MyCAT可以滿足80%以上的企業應用開發。
2.3.6.2 全局表實現
(1)創建表結構
在各個庫分別創建全局表(例如:t_area)的表結構,表結構保持一致,例如:
CREATE TABLE `t_area` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`caller` varchar(16) CHARACTER SET utf8 DEFAULT NULL COMMENT '調用方系統表示',
`province_code` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '省份編碼',
`area_code` varchar(10) CHARACTER SET utf8 NOT NULL COMMENT '區域編碼',
`area_name` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '區域名稱',
`parent_area_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '父區域編碼',
`create_time` datetime NOT NULL COMMENT '創建時間',
`modify_time` datetime DEFAULT NULL COMMENT '修改時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3792 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
(2)配置schema.xml
全局表配置比較簡單,不用寫Rule規則,在schema.xml中修改test_schema,添加t_area的table子元素,參考如下配置即可:
<!-- auto sharding by id (long) -->
<table name="t_user" dataNode="dn1,dn2" rule="rule1">
<childTable name="t_user_class_rel" primaryKey="id" joinKey="user_id" parentKey="user_id" />
</table>
<table name="t_area" primaryKey="id" type="global" dataNode="dn1,dn2" />
</schema>
(3)全局表測試
運行如下insert語句,往test_mycat的t_area表插入10條數據,如下所示:
INSERT INTO `t_area` VALUES ('101', 'test', 'BJ', '110000', '北京市', '1', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('102', 'test', 'BJ', '110100', '市轄區', '110000', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('103', 'test', 'BJ', '110101', '東城區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('104', 'test', 'BJ', '110102', '西城區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('105', 'test', 'BJ', '110103', '崇文區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('106', 'test', 'BJ', '110104', '宣武區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('107', 'test', 'BJ', '110105', '朝陽區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('108', 'test', 'BJ', '110106', '豐臺區', '110100', '2012-09-25 08:30:23', null);
INSERT INTO `t_area` VALUES ('109', 'test', 'BJ', '110107', '石景山區', '110100', '2012-09-25 08:30:23', null);
插入後去dn1,dn2分片中查找,可看到這2個分片中的t_area表都被插入10條數據。執行select語句能返回t_area表的對應記錄,執行update和delete語句能對應對全局表相關的分片中的記錄進行更新和刪除操作。
3、參考文檔
《MyCat inAction中文版》