學會數據庫讀寫分離、分表分庫——用Mycat,這一篇就夠了!

系統開發中,數據庫是非常重要的一個點。除了程序的本身的優化,如:SQL語句優化、代碼優化,數據庫的處理本身優化也是非常重要的。主從、熱備、分表分庫等都是系統發展遲早會遇到的技術問題問題。Mycat是一個廣受好評的數據庫中間件,已經在很多產品上進行使用了。希望通過這篇文章的介紹,能學會Mycat的使用。

安裝

Mycat官網:http://www.mycat.io/
可以了解下Mycat的背景和應用情況,這樣使用起來比較有信心。

Mycat下載地址:http://dl.mycat.io/
官網有個文檔,屬于詳細的介紹,初次入門,看起來比較花時間。

下載:
建議大家選擇 1.6-RELEASE 版本,畢竟是比較穩定的版本。

安裝:
根據不同的系統選擇不同的版本。包括linux、windows、mac,作者考慮還是非常周全的,當然,也有源碼版的。(ps:源碼版的下載后,只要配置正確,就可以正常運行調試,這個贊一下。)

Mycat的安裝其實只要解壓下載的目錄就可以了,非常簡單。
安裝完成后,目錄如下:

目錄 說明
bin mycat命令,啟動、重啟、停止等
catlet catlet為Mycat的一個擴展功能
conf Mycat 配置信息,重點關注
lib Mycat引用的jar包,Mycat是java開發的
logs 日志文件,包括Mycat啟動的日志和運行的日志。

配置

Mycat的配置文件都在conf目錄里面,這里介紹幾個常用的文件:

文件 說明
server.xml Mycat的配置文件,設置賬號、參數等
schema.xml Mycat對應的物理數據庫和數據庫表的配置
rule.xml Mycat分片(分庫分表)規則

Mycat的架構其實很好理解,Mycat是代理,Mycat后面就是物理數據庫。和Web服務器的Nginx類似。對于使用者來說,訪問的都是Mycat,不會接觸到后端的數據庫。
我們現在做一個主從、讀寫分離,簡單分表的示例。結構如下圖:

服務器 IP 說明
Mycat 192.168.0.2 mycat服務器,連接數據庫時,連接此服務器
database1 192.168.0.3 物理數據庫1,真正存儲數據的數據庫
database2 192.168.0.4 物理數據庫2,真正存儲數據的數據庫

Mycat作為主數據庫中間件,肯定是與代碼弱關聯的,所以代碼是不用修改的,使用Mycat后,連接數據庫是不變的,默認端口是8066。連接方式和普通數據庫一樣,如:jdbc:mysql://192.168.0.2:8066/

server.xml

示例

<user name="test">
        <property name="password">test</property>  
        <property name="schemas">lunch</property>  
        <property name="readOnly">false</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 用戶配置節點
--name 登錄的用戶名,也就是連接Mycat的用戶名
--password 登錄的密碼,也就是連接Mycat的密碼
--schemas 數據庫名,這里會和schema.xml中的配置關聯,多個用逗號分開,例如需要這個用戶需要管理兩個數據庫db1,db2,則配置db1,dbs
--privileges 配置用戶針對表的增刪改查的權限,具體見文檔吧

我這里配置了一個賬號test 密碼也是test,針對數據庫lunch,讀寫權限都有,沒有針對表做任何特殊的權限。

schema.xml
schema.xml是最主要的配置項,首先看我的配置文件。

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

<!-- 數據庫配置,與server.xml中的數據庫對應 -->
    <schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
        <table name="lunchmenu" dataNode="dn1"  />
        <table name="restaurant" dataNode="dn1"  />
        <table name="userlunch" dataNode="dn1"  />
        <table name="users" dataNode="dn1"  />
        <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

        
    </schema>

<!-- 分片配置 -->
    <dataNode name="dn1" dataHost="test1" database="lunch" />
    <dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理數據庫配置 -->
    <dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user();</heartbeat>
        <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
        </writeHost>
    </dataHost>

    <dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user();</heartbeat>
        <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
        </writeHost>
    </dataHost>

</mycat:schema>
參數 說明
schema 數據庫設置,此數據庫為邏輯數據庫,name與server.xml中schema對應
dataNode 分片信息,也就是分庫相關配置
dataHost 物理數據庫,真正存儲數據的數據庫

每個節點的屬性逐一說明:

schema:

屬性 說明
name 邏輯數據庫名,與server.xml中的schema對應
checkSQLschema 數據庫前綴相關設置,建議看文檔,這里暫時設為folse
sqlMaxLimit select 時默認的limit,避免查詢全表

table:

屬性 說明
name 表名,物理數據庫中表名
dataNode 表存儲到哪些節點,多個節點用逗號分隔。節點為下文dataNode設置的name
primaryKey 主鍵字段名,自動生成主鍵時需要設置
autoIncrement 是否自增
rule 分片規則名,具體規則下文rule詳細介紹

dataNode

屬性 說明
name 節點名,與table中dataNode對應
datahost 物理數據庫名,與datahost中name對應
database 物理數據庫中數據庫名

dataHost

屬性 說明
name 物理數據庫名,與dataNode中dataHost對應
balance 均衡負載的方式
writeType 寫入方式
dbType 數據庫類型
heartbeat 心跳檢測語句,注意語句結尾的分號要加。

應用場景

數據庫分表分庫

配置如下:

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

<!-- 數據庫配置,與server.xml中的數據庫對應 -->
    <schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
        <table name="lunchmenu" dataNode="dn1"  />
        <table name="restaurant" dataNode="dn1"  />
        <table name="userlunch" dataNode="dn1"  />
        <table name="users" dataNode="dn1"  />
        <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2"  rule="mod-long" />

        
    </schema>

<!-- 分片配置 -->
    <dataNode name="dn1" dataHost="test1" database="lunch" />
    <dataNode name="dn2" dataHost="test2" database="lunch" />

<!-- 物理數據庫配置 -->
    <dataHost name="test1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user();</heartbeat>
        <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
        </writeHost>
    </dataHost>

    <dataHost name="test2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user();</heartbeat>
        <writeHost host="hostS1" url="192.168.0.3:3306" user="root" password="123456">  
        </writeHost>
    </dataHost>

</mycat:schema>

我在192.168.0.2、192.168.0.3均有數據庫lunch。
lunchmenu、restaurant、userlunch、users這些表都只寫入節點dn1,也就是192.168.0.2這個服務,而dictionary寫入了dn1、dn2兩個節點,也就是192.168.0.2、192.168.0.3這兩臺服務器。分片的規則為:mod-long。
主要關注rule屬性,rule屬性的內容來源于rule.xml這個文件,Mycat支持10種分表分庫的規則,基本能滿足你所需要的要求,這個必須贊一個,其他數據庫中間件好像都沒有這么多。
table中的rule屬性對應的就是rule.xml文件中tableRule的name,具體有哪些分表和分庫的實現,建議還是看下文檔。我這里選擇的mod-long就是將數據平均拆分。因為我后端是兩臺物理庫,所以rule.xml中mod-long對應的function count為2,見下面部分代碼:

<tableRule name="mod-long">
        <rule>
            <columns>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>

數據庫讀寫分離

配置如下:

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

<!-- 數據庫配置,與server.xml中的數據庫對應 -->
    <schema name="lunch" checkSQLschema="false" sqlMaxLimit="100">
        <table name="lunchmenu" dataNode="dn1"  />
        <table name="restaurant" dataNode="dn1"  />
        <table name="userlunch" dataNode="dn1"  />
        <table name="users" dataNode="dn1"  />
        <table name="dictionary" primaryKey="id" autoIncrement="true" dataNode="dn1"  />

        
    </schema>

<!-- 分片配置 -->
    <dataNode name="dn1" dataHost="test1" database="lunch" />


<!-- 物理數據庫配置 -->
    <dataHost name="test1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user();</heartbeat>
        <writeHost host="hostM1" url="192.168.0.2:3306" user="root" password="123456">  
        <readHost host="hostM1" url="192.168.0.3:3306" user="root" password="123456">   
        </readHost>
        </writeHost>
    </dataHost>


</mycat:schema>

這樣的配置與前一個示例配置改動如下:
刪除了table分配的規則,以及datanode只有一個
datahost也只有一臺,但是writehost總添加了readhost,balance改為1,表示讀寫分離。
以上配置達到的效果就是102.168.0.2為主庫,192.168.0.3為從庫。

注意:Mycat主從分離只是在讀的時候做了處理,寫入數據的時候,只會寫入到writehost,需要通過mycat的主從復制將數據復制到readhost,這個問題當時候我糾結了好久,數據寫入writehost后,readhost一直沒有數據,以為是自己配置的問題,后面才發現Mycat就沒有實現主從復制的功能,畢竟數據庫本身自帶的這個功能才是最高效穩定的。

至于其他的場景,如同時主從和分表分庫也是支持的了,只要了解這個實現以后再去修改配置,都是可以實現的。而熱備及故障專業官方推薦使用haproxy配合一起使用,大家可以試試。

使用

Mycat的啟動也很簡單,啟動命令在Bin目錄:

##啟動
mycat start

##停止
mycat stop

##重啟
mycat restart

如果在啟動時發現異常,在logs目錄中查看日志。

  • wrapper.log 為程序啟動的日志,啟動時的問題看這個
  • mycat.log 為腳本執行時的日志,SQL腳本執行報錯后的具體錯誤內容,查看這個文件。mycat.log是最新的錯誤日志,歷史日志會根據時間生成目錄保存。

mycat啟動后,執行命令不成功,可能實際上配置有錯誤,導致后面的命令沒有很好的執行。

Mycat帶來的最大好處就是使用是完全不用修改原有代碼的,在mycat通過命令啟動后,你只需要將數據庫連接切換到Mycat的地址就可以了。如下面就可以進行連接了:

 mysql -h192.168.0.1 -P8806 -uroot -p123456

連接成功后可以執行sql腳本了。
所以,可以直接通過sql管理工具(如:navicat、datagrip)連接,執行腳本。我一直用datagrip來進行日常簡單的管理,這個很方便。

Mycat還有一個管理的連接,端口號是9906.

 mysql -h192.168.0.1 -P9906 -uroot -p123456

連接后可以根據管理命令查看Mycat的運行情況,當然,喜歡UI管理方式的人,可以安裝一個Mycat-Web來進行管理,有興趣自行搜索。

簡而言之,開發中使用Mycat和直接使用Mysql機會沒有差別。

常見問題

使用Mycat后總會遇到一些坑,我將自己遇到的一些問題在這里列一下,希望能與大家有共鳴:

  • Mycat是不是配置以后,就能完全解決分表分庫和讀寫分離問題?
    Mycat配合數據庫本身的復制功能,可以解決讀寫分離的問題,但是針對分表分庫的問題,不是完美的解決。或者說,至今為止,業界沒有完美的解決方案。
    分表分庫寫入能完美解決,但是,不能完美解決主要是聯表查詢的問題,Mycat支持兩個表聯表的查詢,多余兩個表的查詢不支持。 其實,很多數據庫中間件關于分表分庫后查詢的問題,都是需要自己實現的,而且節本都不支持聯表查詢,Mycat已經算做地非常先進了。
    分表分庫的后聯表查詢問題,大家通過合理數據庫設計來避免。

  • Mycat支持哪些數據庫,其他平臺如 .net、PHP能用嗎?
    官方說了,支持的數據庫包括MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流數據庫,很贊。
    盡量用Mysql,我試過SQL Server,會有些小問題,因為部分語法有點差異。

  • Mycat 非JAVA平臺如 .net、PHP能用嗎?
    可以用。這一點MyCat做的也很棒。

參考

《Mycat權威指南》: http://www.mycat.io/document/Mycat_V1.6.0.pdf
官網 :http://www.mycat.io/

如果想熟練使用Mycat,建議要仔細看看官方推薦的文檔,可能需要花點時間。本文只是簡單的介紹下Mycat的配置,希望能快速讓大家對Mycat有個認識,官方的文檔理解起來也很容易,只是需要的時間更多,本文為說明的參數,請參考官方文檔。


歡迎大家關注我的公眾號交流、學習、第一時間獲取最新的文章。
微信號:itmifen

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容