使用Mycat實現數據庫讀寫分離

本文作者:藍雄威,叩丁狼高級講師。原創文章,轉載請注明出處。

01前言

在上一篇文章中,我們基于CentOS7實現了MySQL的主從復制,我們需要把DML操作放在MySQL的主節點執行,需要把DQL操作放在MySQL的從節點執行.那在應用程序中我們怎么控制這個邏輯呢?
下面是一種可行的方案:
1.在項目中配置兩個數據源(一主一從),分別是A(主)和B(從)。
2.在程序中判斷是不是select操作,如果是就把數據源更換成B,如果不是select操作就更換成A,這樣就可以實現程序中的讀寫分離了.
3.關于步驟2的更換數據源,Spring中是提供了AbstarctRoutingDataSource這個類在程序中實現數據源的切換的.
這種方案可行是可行,但是在應用程序端需要寫挺多代碼的,而且這些屬于非業務層面的東西,寫在項目中對項目來說是代碼侵入了.
所以對于讀寫分離我們可以使用Mycat數據庫中間件來完成.

02MyCat介紹

關于MyCat的詳細簡介,同學們可以去Mycat官網.下載Mycat權威指南.pdf來看,文章中的前世今生寫得幽默有趣,挺有意思的,從描述來看都感覺看的不是本技術書,而是本小說哈.在這里我簡單的介紹一下Mycat:

2008年阿里開源了一款數據庫中間件Amoeba,隨著業務的增長,這塊產品不能支持目前已有的業務.阿里又開源了Cobar這款中間件,這款產品在阿里內部得到了很廣泛的應用.(應用在了3000多臺服務器,每天超過10億次的數據庫訪問),當時一開源就得到了開發者和運維人員的追捧. 開源之后,阿里就沒有對這款產品維護了,這款產品在生產環境中還是存在挺多問題的.在這樣的場景下MyCat誕生了,2013年MyCat社區在Cobar的基礎上進行了很大的改造和升級.

03Mycat優勢

優勢這個我就從官網上給同學們摘抄下來了:

基于阿里開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能以及眾多成熟的使用案例使得MYCAT一開始就擁有一個很好的起點,站在巨人的肩膀上,我們能看到更遠。業界優秀的開源項目和創新思路被廣泛融入到MYCAT的基因中,使得MYCAT在很多方面都領先于目前其他一些同類的開源項目,甚至超越某些商業產品。

MYCAT背后有一支強大的技術團隊,其參與者都是5年以上軟件工程師、架構師、DBA等,優秀的技術團隊保證了MYCAT的產品質量。

MYCAT并不依托于任何一個商業公司,因此不像某些開源項目,將一些重要的特性封閉在其商業產品中,使得開源項目成了一個擺設。

目前也有挺多公司在生產環境上使用Mycat的,使用案例,所以來說還是一款很不錯,很穩定的產品.

04主要作用

主要作為分布式數據庫系統的中間層
1.可以實現數據庫的讀寫分離
2.支持負載均衡
3.支持后端MySQL高可用
4.數據庫的垂直拆分
5.數據庫水平拆分
關于Mycat如何實現數據庫的分庫分表,我在之前的簡書中已經寫了案例,數據庫中間件Mycat+SpringBoot完成分庫分表.

05Mycat的基本概念

Mycat概念

從上圖可以看到,我們應用程序不是直接連接真實數據庫的的,而是連接Mycat的.所以在Mycat的配置文件中我們就需要去定義邏輯庫邏輯表真實庫真實表的映射關系

06安裝JDK環境變量

0.我們Mycat的安裝是基于CentOS7環境來安裝的,所以同學們先把基礎環境搭建好哈.
1.Mycat是基于Java開發的一款中間件產品,所以要使用Mycat前需要把JDK的環境裝上.JDK1.8安裝包.
2.下載好jdk1.8安裝包后,通過工具上傳到服務器上.我們通常會把文件上傳到/usr/local/software目錄下

image

3.然后使用解壓命令解壓到/usr/local目錄下

tar -zxvf jdk-8u161-linux-x64.tar.gz -C /usr/local
image

但是名字有些長,不方便我們設置環境變量,所以我們可以對這個文件夾重命名

mv jdk1.8.0_161/ jdk1.8
image

4.jdk解壓好之后,我們就可以來配置環境變量了.

vi /etc/profile

編輯界面如下:


image

需要在這個文件中添加這兩行配置:

export JAVA_HOME=/usr/local/jdk1.8
export PATH=.:$JAVA_HOME/bin:$PATH

編輯后如下圖所示:


image

然后保存退出即可.
然后需要通過這個命令來重新加載配置文件:

source /etc/profile

設置好之后,通過這個命令查看環境變量是否配置好了.

java -version

如果看到下面這個內容,說明已經配置好了.


image.png

07安裝Mycat

我們這次使用的是Mycat-server-1.6.7版本,下載好之后上傳到服務器上.

image

然后使用命令進行解壓

tar -zxvf Mycat-server-1.6.7.1-release-20190627191042-linux.tar.gz -C /usr/local/
image

這樣我們就已經裝好Mycat了,下一步就需要去配置Mycat的配置文件了.

08配置讀寫分離

我們可以先看看Mycat的文件目錄結構

image

bin目錄:存放Mycat運行的腳本
conf目錄:存放Mycat的配置文件
logs目錄:存放Mycat啟動及運行的日志文件
我們現在需要進入到conf目錄,修改配置文件.
image

目前來說,我們只需要關心server.xmlschema.xmlrule.xml這三個文件.
server.xml:主要配置Mycat的啟動參數,連接密碼,白名單,黑名單,訪問權限控制等參數,我們暫時不修改,用默認的就可以了.
schema.xml:主要配置邏輯庫、邏輯表和真實庫、真實表之間的映射關系.
rule.xml:主要配置分庫分表時的分片規則,此次試驗中我們并不需要修改到.
目前我們的環境是這樣的:

主機IP 角色
192.168.142.128 MySQL主節點
192.168.142.129 MySQL從節點
192.168.142.130 MyCat服務器

然后我們需要修改schema.xml文件,修改內容如下(建議直接復制我的,然后把Ip換一下就好了.):

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
    <table name="t_order" dataNode="dn01"/> 
    </schema>
    <dataNode name="dn01" dataHost="dh01" database="hello" />  
    <dataHost name="dh01" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">  
            <heartbeat>select user()</heartbeat>  
            <writeHost host="192.168.142.128" url="192.168.142.128:3306" user="root" password="WolfCode_2017">
                <readHost host="192.168.142.129" url="192.168.142.129:3306" user="root" password="WolfCode_2017"></readHost>
            </writeHost>
            <writeHost host="192.168.142.129" url="192.168.142.129:3306" user="root" password="WolfCode_2017"></writeHost>
    </dataHost> 
</mycat:schema>

一、schema 解釋

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">

name屬性:表示的是邏輯庫的名字,是應用程序連接的時候的數據庫名稱.
checkSQLschema屬性:當該值設置為 true 時,如果我們執行語句select * from TESTDB.travelrecord;則 MyCat 會把語句修改
select * from travelrecord;。即把表示 schema 的字符去掉,避免發送到后端數據庫執行時報(ERROR
1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。

不過,即使設置該值為 true ,如果語句所帶的是并非是 schema 指定的名字,例如:select * from
db1.travelrecord;
那么 MyCat 并不會刪除 db1 這個字段,如果沒有定義該庫的話則會報錯,所以在提供 SQL
語句的最好是不帶這個字段。

sqlMaxLimit屬性:當該值設置為某個數值時。每條執行的 SQL 語句,如果沒有加上 limit 語句,MyCat 也會自動的加上所對應
的值。例如設置值為 100,執行select * from TESTDB.travelrecord;的效果為和執行select * from
TESTDB.travelrecord limit 100;
相同。
設置該值的話,MyCat 默認會把查詢到的信息全部都展示出來,造成過多的輸出。所以,在正常使用中,還
是建議加上一個值,用于減少過多的數據返回。
當然 SQL 語句中也顯式的指定 limit 的大小,不受該屬性的約束。
需要注意的是,如果運行的 schema 為非拆分庫的,那么該屬性不會生效。需要手動添加 limit 語句

二、table標簽解釋

<table name="t_order" dataNode="dn01"/>
Table 標簽定義了 MyCat 中的邏輯表,所有需要拆分的表都需要在這個標簽中定義。
name 屬性:定義邏輯表的表名,這個名字就如同我在數據庫中執行 create table 命令指定的名字一樣,同個 schema 標
簽中定義的名字必須唯一。
dataNode屬性:定義這個邏輯表所屬的 dataNode, 該屬性的值需要和后面 dataNode 標簽中 name 屬性的值相互對應。

三、dataNode標簽解釋

<dataNode name="dn01" dataHost="dh01" database="hello" />
dataNode 標簽定義了 MyCat 中的數據節點,也就是我們通常說所的數據分片。一個 dataNode 標簽就是一個獨立的數據分片。
name 屬性:定義數據節點的名字,這個名字需要是唯一的,我們需要在 table 標簽上應用這個名字,來建立表與分片對
應的關系。
dataHost 屬性:該屬性用于定義該分片屬于哪個數據庫實例的,屬性值是引用 dataHost 標簽上定義的 name 屬性。
database 屬性:該屬性用于定義該分片屬性哪個具體數據庫實例上的具體庫,因為這里使用兩個緯度來定義分片,就是:實例+具體的庫。因為每個庫上建立的表和表結構是一樣的。所以這樣做就可以輕松的對表進行水平拆分。

四、dataHost標簽解釋

<dataHost name="dh01" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
作為 Schema.xml 中最后的一個標簽,該標簽在 mycat 邏輯庫中也是作為最底層的標簽存在,直接定義了具
體的數據庫實例、讀寫分離配置和心跳語句。
name 屬性:唯一標識 dataHost 標簽,供上層的標簽使用
maxCon 屬性:指定每個讀寫實例連接池的最大連接。也就是說,標簽內嵌套的 writeHost、readHost 標簽都會使用這個屬
性的值來實例化出連接池的最大連接數
minCon 屬性:指定每個讀寫實例連接池的最小連接,初始化連接池的大小
balance 屬性:
負載均衡類型,目前的取值有 3 種:

  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",所有讀請求隨機的分發到 wiriterHost 對應的 readhost 執行,writerHost 不負擔讀壓力,
    注意 balance=3 只在 1.4 及其以后版本有,1.3 沒有。

writeType 屬性:
負載均衡類型,目前的取值有 3 種:

  1. writeType="0", 所有寫操作發送到配置的第一個 writeHost,第一個掛了切到還生存的第二個 writeHost,
    重新啟動后已切換后的為準,切換記錄在配置文件中:dnindex.properties .

2.writeType="1",所有寫操作都隨機的發送到配置的 writeHost,1.5 以后廢棄不推薦。switchType 屬

  • -1 表示不自動切換。
  • 1 默認值,自動切換。
  • 2 基于 MySQL 主從同步的狀態決定是否切換。

dbType 屬性:指定后端連接的數據庫類型,目前支持二進制的 mysql 協議,還有其他使用 JDBC 連接的數據庫。例如:
mongodb、oracle、spark 等。
dbDriver 屬性:指定連接后端數據庫使用的 Driver,目前可選的值有 native 和 JDBC。使用 native 的話,因為這個值執行的
是二進制的 mysql 協議,所以可以使用 mysql 和 maridb。其他類型的數據庫則需要使用 JDBC 驅動來支持。
從 1.6 版本開始支持 postgresql 的 native 原始協議。
如果使用 JDBC 的話需要將符合 JDBC 4 標準的驅動 JAR 包放到 MYCAT\lib 目錄下,并檢查驅動 JAR 包中
包括如下目錄結構的文件:META-INF\services\java.sql.Driver。在這個文件內寫上具體的 Driver 類名,例如:
com.mysql.jdbc.Driver。

五、heartbeat標簽解釋

<heartbeat>select user()</heartbeat>
這個標簽內指明用于和后端數據庫進行心跳檢查的語句。例如,MYSQL 可以使用 select user(),Oracle 可以
使用 select 1 from dual 等。

六、writeHost 標簽、readHost 標簽解釋

這兩個標簽都指定后端數據庫的相關配置給 mycat,用于實例化后端連接池。唯一不同的是,writeHost 指定寫實例、readHost 指定讀實例,組著這些讀寫實例來滿足系統的要求。在一個 dataHost 內可以定義多個 writeHost 和 readHost。但是,如果 writeHost 指定的后端數據庫宕機,那么這個 writeHost 綁定的所有 readHost 都將不可用。另一方面,由于這個 writeHost 宕機系統會自動的檢測到,并切換到備用的 writeHost 上去。
host 屬性:用于標識不同實例,一般 writeHost 我們使用M1,readHost 我們用S1。
url 屬性:后端實例連接地址,如果是使用 native 的 dbDriver,則一般為 address:port 這種形式。用 JDBC 或其他的
dbDriver,則需要特殊指定。當使用 JDBC 時則可以這么寫jdbc:mysql://localhost:3306/
user 屬性:后端存儲實例需要的用戶名字。
password 屬性:后端存儲實例需要的密碼。

08啟動Mycat

使用命令

/usr/local/mycat/bin/mycat start

然后觀察wrapper.log文件看是否已經啟動成功.

image

出現這樣的界面說明已經啟動成功.可以通過Navicat客戶端連接Mycat,或者通過應用程序連接也是可以的.


image

如果需要修改默認端口或者默認密碼的話需要修改server.xml文件.在應用程序中連接的時候,和之前連接MySQL一樣的.只是URL地址不一樣而已,代碼還是一樣的.

09其他

目前我們連接Mycat之后,所有的讀操作都是走從節點的,如果有需求需要讀走主節點的話,可以使用Mycat中的注解,強制讓讀操作走主節點.

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

推薦閱讀更多精彩內容