從新學習Mysql數據13:Mysql主從複製,讀寫分離,分表分庫策略與實踐

1、MySQL擴展具體的實現方式前端

隨着業務規模的不斷擴大,須要選擇合適的方案去應對數據規模的增加,以應對逐漸增加的訪問壓力和數據量。java

關於數據庫的擴展主要包括:業務拆分、主從複製、讀寫分離、數據庫分庫與分表等。這篇文章主要講述數據庫分庫與分表node

(1)業務拆分mysql

在 大型網站應用之海量數據和高併發解決方案總結一二 一篇文章中也具體講述了爲何要對業務進行拆分。git

業務起步初始,爲了加快應用上線和快速迭代,不少應用都採用集中式的架構。隨着業務系統的擴大,系統變得愈來愈複雜,愈來愈難以維護,開發效率變得愈來愈低,而且對資源的消耗也變得愈來愈大,經過硬件提升系統性能的方式帶來的成本也愈來愈高。程序員

所以,在選型初期,一個優良的架構設計是後期系統進行擴展的重要保障。github

例如:電商平臺,包含了用戶、商品、評價、訂單等幾大模塊,最簡單的作法就是在一個數據庫中分別建立users、shops、comment、order四張表。面試

這裏寫圖片描述

可是,隨着業務規模的增大,訪問量的增大,咱們不得不對業務進行拆分。每個模塊都使用單獨的數據庫來進行存儲,不一樣的業務訪問不一樣的數據庫,將本來對一個數據庫的依賴拆分爲對4個數據庫的依賴,這樣的話就變成了4個數據庫同時承擔壓力,系統的吞吐量天然就提升了。算法

這裏寫圖片描述

(2)主從複製spring

通常是主寫從讀,一主多從

一、MySQL5.6 數據庫主從(Master/Slave)同步安裝與配置詳解

二、MySQL主從複製的常見拓撲、原理分析以及如何提升主從複製的效率總結

三、使用mysqlreplicate命令快速搭建 Mysql 主從複製

上述三篇文章中,講述瞭如何配置主從數據庫,以及如何實現數據庫的讀寫分離,這裏再也不贅述,有須要的選擇性點擊查看。

這裏寫圖片描述

上圖是網上的一張關於MySQL的Master和Slave之間數據同步的過程圖。

主要講述了MySQL主從複製的原理:數據複製的實際就是Slave從Master獲取Binary log文件,而後再本地鏡像的執行日誌中記錄的操做。因爲主從複製的過程是異步的,所以Slave和Master之間的數據有可能存在延遲的現象,此時只能保證數據最終的一致性。

(3)數據庫分庫與分表

咱們知道每臺機器不管配置多麼好它都有自身的物理上限,因此當咱們應用已經能觸及或遠遠超出單臺機器的某個上限的時候,咱們唯有尋找別的機器的幫助或者繼續升級的咱們的硬件,但常見的方案仍是經過添加更多的機器來共同承擔壓力。

咱們還得考慮當咱們的業務邏輯不斷增加,咱們的機器能不能經過線性增加就能知足需求?所以,使用數據庫的分庫分表,可以立竿見影的提高系統的性能,關於爲何要使用數據庫的分庫分表的其餘緣由這裏再也不贅述,主要講具體的實現策略。請看下邊章節。

2、分表實現策略

關鍵字:用戶ID、表容量

對於大部分數據庫的設計和業務的操做基本都與用戶的ID相關,所以使用用戶ID是最經常使用的分庫的路由策略。用戶的ID能夠做爲貫穿整個系統用的重要字段。所以,使用用戶的ID咱們不只能夠方便咱們的查詢,還能夠將數據平均的分配到不一樣的數據庫中。(固然,還能夠根據類別等進行分表操做,分表的路由策略還有不少方式)

接着上述電商平臺假設,訂單表order存放用戶的訂單數據,sql腳本以下(只是爲了演示,省略部分細節):

CREATE TABLE `order` (
  `order_id` bigint(32) primary key auto_increment,
  `user_id` bigint(32),
   ...
)

當數據比較大的時候,對數據進行分表操做,首先要肯定須要將數據平均分配到多少張表中,也就是:表容量。

這裏假設有100張表進行存儲,則咱們在進行存儲數據的時候,首先對用戶ID進行取模操做,根據 user_id%100 獲取對應的表進行存儲查詢操做,示意圖以下:

這裏寫圖片描述

例如,user_id = 101 那麼,咱們在獲取值的時候的操做,能夠經過下邊的sql語句:

select * from order_1 where user_id= 101

其中,order_1是根據 101%100 計算所得,表示分表以後的第一章order表。

注意:

在實際的開發中,若是你使用MyBatis作持久層的話,MyBatis已經提供了很好得支持數據庫分表的功能,例如上述sql用MyBatis實現的話應該是:

接口定義:

/**
  * 獲取用戶相關的訂單詳細信息
  * @param tableNum 具體某一個表的編號
  * @param userId 用戶ID
  * @return 訂單列表
  */
public List<Order> getOrder(@Param("tableNum") int tableNum,@Param("userId") int userId);

xml配置映射文件:

<select id="getOrder" resultMap="BaseResultMap">
    select * from order_${tableNum}
    where user_id = #{userId}
  </select>

其中${tableNum} 含義是直接讓參數加入到sql中,這是MyBatis支持的特性。

注意:

另外,在實際的開發中,咱們的用戶ID更多的多是經過UUID生成的,這樣的話,咱們能夠首先將UUID進行hash獲取到整數值,而後在進行取模操做。

3、分庫實現策略

數據庫分表可以解決單表數據量很大的時候數據查詢的效率問題,可是沒法給數據庫的併發操做帶來效率上的提升,由於分表的實質仍是在一個數據庫上進行的操做,很容易受數據庫IO性能的限制。

所以,如何將數據庫IO性能的問題平均分配出來,很顯然將數據進行分庫操做能夠很好地解決單臺數據庫的性能問題。

分庫策略與分表策略的實現很類似,最簡單的都是能夠經過取模的方式進行路由。

仍是上例,將用戶ID進行取模操做,這樣的話獲取到具體的某一個數據庫,一樣關鍵字有:

用戶ID、庫容量

路由的示意圖以下:

這裏寫圖片描述

上圖中庫容量爲100。

一樣,若是用戶ID爲UUID請先hash而後在進行取模。

4、分庫與分表實現策略

上述的配置中,數據庫分表能夠解決單表海量數據的查詢性能問題,分庫能夠解決單臺數據庫的併發訪問壓力問題。

有時候,咱們須要同時考慮這兩個問題,所以,咱們既須要對單表進行分表操做,還須要進行分庫操做,以便同時擴展系統的併發處理能力和提高單表的查詢性能,就是咱們使用到的分庫分表。

分庫分表的策略相對於前邊兩種複雜一些,一種常見的路由策略以下:

1、中間變量 = user_id%(庫數量*每一個庫的表數量);
2、庫序號 = 取整(中間變量/每一個庫的表數量);
3、表序號 = 中間變量%每一個庫的表數量;

例如:數據庫有256 個,每個庫中有1024個數據表,用戶的user_id=262145,按照上述的路由策略,可得:

1、中間變量 = 262145%(256*1024)= 1;
2、庫序號 = 取整(1/1024)= 0;
3、表序號 = 1%1024 = 1;

這樣的話,對於user_id=262145,將被路由到第0個數據庫的第1個表中。

示意圖以下:

這裏寫圖片描述

5、分庫分表總結

關於分庫分表策略的選擇有不少種,上文中根據用戶ID應該是比較簡單的一種。其餘方式好比使用號段進行分區或者直接使用hash進行路由等。有興趣的能夠自行查找學習。

關於上文中提到的,若是用戶的ID是經過UUID的方式生成的話,咱們須要單獨的進行一次hash操做,而後在進行取模操做等,其實hash自己就是一種分庫分表的策略,使用hash進行路由策略的時候,咱們須要知道的是,也就是hash路由策略的優缺點,優勢是:數據分佈均勻;缺點是:數據遷移的時候麻煩,不能按照機器性能分攤數據。

上述的分庫和分表操做,查詢性能和併發能力都獲得了提升,可是還有一些須要注意的就是,例如:本來跨表的事物變成了分佈式事物;因爲記錄被切分到不一樣的數據庫和不一樣的數據表中,難以進行多表關聯查詢,而且不能不指定路由字段對數據進行查詢。分庫分表以後,若是咱們須要對系統進行進一步的擴陣容(路由策略變動),將變得很是不方便,須要咱們從新進行數據遷移。


最後須要指出的是,分庫分表目前有不少的中間件可供選擇,最多見的是使用淘寶的中間件Cobar。

GitHub地址:https://github.com/alibaba/cobara

文檔地址爲:https://github.com/alibaba/cobar/wiki

關於淘寶的中間件Cobar本篇內容不具體介紹,會在後邊的學習中在作介紹。

另外Spring也能夠實現數據庫的讀寫分離操做,後邊的文章,會進一步學習。

6、總結

上述中,咱們學到了如何進行數據庫的讀寫分離和分庫分表,那麼,是否是能夠實現一個可擴展、高性能、高併發的網站那?很顯然還不能夠!一個大型的網站使用到的技術遠不止這些,能夠說,這些都是其中的最基礎的一個環節,由於還有不少具體的細節咱們沒有掌握到,好比:數據庫的集羣控制,集羣的負載均衡,災難恢復,故障自動切換,事務管理等等技術。所以,還有不少須要去學習去研究的地方。

總之:

路漫漫其修遠兮,吾將上下而求索。

前方道路美好而光明,2017年新徵程,不泄步!

Mycat實現主從複製,讀寫分離,以及分庫分表的實踐。

Mycat是什麼

一個完全開源的,面向企業應用開發的大數據庫集羣

支持事務、ACID、能夠替代MySQL的增強版數據庫

一個能夠視爲MySQL集羣的企業級數據庫,用來替代昂貴的Oracle集羣

一個融合內存緩存技術、NoSQL技術、HDFS大數據的新型SQL Server

結合傳統數據庫和新型分佈式數據倉庫的新一代企業級數據庫產品

一個新穎的數據庫中間件產品

以上內容來自Mycat官網,簡單來講,Mycat就是一個數據庫中間件,對於咱們開發來講,就像是一個代理,當咱們須要使用到多個數據庫和須要進行分庫分表的時候,咱們只須要在mycat裏面配置好相關規則,程序無需作任何修改,只是須要將本來的數據源連接到mycat而已,固然若是之前有多個數據源,須要將數據源切換爲單個數據源,這樣有個好處就是當咱們的數據量已經很大的時候,須要開始分庫分表或者作讀寫分離的時候,不用修改代碼(只須要改一下數據源的連接地址)

使用Mycat分表分庫實踐

haha,首先這不是一篇入門Mycat的博客但小編感受又很入門的博客!這篇博客主要講解Mycat中數據分片的相關知識,同時小編將會在本機數據庫上進行測試驗證,圖文並茂展現出來。

數據庫分區分表,咋一聽很是地高大上,總有一種高高在上,可望不可即的感受,但小編想說的是,其實,做爲一個開發人員,該來的老是會來,該學的東西你仍是得學,區別只是時間前後順序的問題。

1、分區分表

分區就是把一個數據表的文件和索引分散存儲在不一樣的物理文件中。

mysql支持的分區類型包括Range、List、Hash、Key,其中Range比較經常使用:

RANGE分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

LIST分區:相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。

HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數能夠包含MySQL 中有效的、產生非負整數值的任何表達式。

KEY分區:相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值。

分表是指在邏輯上將一個表拆分紅多個邏輯表,在總體上看是一張表,分表有水平拆分和垂直拆分兩種,舉個例子,將一張大的存儲商戶信息的表按照商戶號的範圍進行分表,將不一樣範圍的記錄分佈到不一樣的表中。

2、Mycat 數據分片的種類

Mycat 的分片其實和分表差很少意思,就是當數據庫過於龐大,尤爲是寫入過於頻繁且很難由一臺主機支撐是,這時數據庫就會面臨瓶頸。咱們將存放在同一個數據庫實例中的數據分散存放到多個數據庫實例(主機)上,進行多臺設備存取以提升性能,在切分數據的同時能夠提升系統的總體性。

數據分片是指將數據全局地劃分爲相關的邏輯片斷,有水平切分、垂直切分、混合切分三種類型,下面主要講下Mycat的水平和垂直切分。有一點很重要,那就是Mycat是分佈式的,所以分出來的數據片分佈到不一樣的物理機上是正常的,靠網絡通訊進行協做。

水平切分

就是按照某個字段的某種規則分散到多個節點庫中,每一個節點中包含一部分數據。能夠將數據水平切分簡單理解爲按照數據行進行切分,就是將表中的某些行切分到一個節點,將另外某些行切分到其餘節點,從分佈式的總體來看它們是一個總體的表。

垂直切分

一個數據庫由不少表構成,每一個表對應不一樣的業務,垂直切分是指按照業務將表進行分類並分不到不一樣的節點上。垂直拆分簡單明瞭,拆分規則明確,應用程序模塊清晰、明確、容易整合,可是某個表的數據量達到必定程度後擴展起來比較困難。

混合切分

爲水平切分和垂直切分的結合。

3、Mycat 垂直切分、水平切分實戰

一、垂直切分

上面說到,垂直切分主要是根據具體業務來進行拆分的,那麼,咱們能夠想象這麼一個場景,假設咱們有一個很是大的電商系統,那麼咱們須要將訂單表、流水錶、用戶表、用戶評論表等分別分不到不一樣的數據庫中來提升吞吐量,架構圖大概以下:

因爲小編是在一臺機器上測試,所以就只有host1這個節點,但不一樣的表仍是依舊對應不一樣的數據庫,只不過是全部數據庫屬於同一個數據庫實例(主機)而已,後期不一樣主機只需增長<dataHost>節點便可。

mycat配置文件以下:

server.xml

<user name="root">
    <property name="password">root</property>
    // 對應四個邏輯庫
    <property name="schemas">order,trade,user,comment</property>
</user>

schema.xml

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

    <!-- 4個邏輯庫,對應4個不一樣的分片節點 -->
    <schema name="order" checkSQLschema="false" sqlMaxLimit="100" dataNode="database1" />
    <schema name="trade" checkSQLschema="false" sqlMaxLimit="100" dataNode="database2" />
    <schema name="user" checkSQLschema="false" sqlMaxLimit="100" dataNode="database3" />
    <schema name="comment" checkSQLschema="false" sqlMaxLimit="100" dataNode="database4" />

    <!-- 四個分片,對應四個不一樣的數據庫 -->
    <dataNode name="database1" dataHost="localhost1" database="database1" />
    <dataNode name="database2" dataHost="localhost1" database="database2" />
    <dataNode name="database3" dataHost="localhost1" database="database3" />
    <dataNode name="database4" dataHost="localhost1" database="database4" />

    <!-- 實際物理主機,只有這一臺 -->
    <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="localhost:3306" user="root"
                password="root">
        </writeHost>
    </dataHost>
</mycat:schema>

登錄本機mysql,建立order,trade,user,comment4個數據庫:

create database database1 character set utf8;
create database database2 character set utf8;
create database database3 character set utf8;
create database database4 character set utf8;

執行bin目錄下的startup_nowrap.bat文件,若是輸出下面內容,則說明已經啓動mycat成功,若是沒有,請檢查order,trade,user,comment4個數據庫是否已經建立。

採用下面語句登錄Mycat服務器:

mysql -uroot -proot -P8066 -h127.0.0.1

comment數據庫中建立Comment表,並插入一條數據

上圖1處新建一個Comment表,2處插入一條記錄,3處查看記錄插入到哪一個數據節點中,即database4

二、水平切分

server.xml

<user name="root">
    <property name="password">root</property>
    <property name="schemas">TESTDB</property>
</user>

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">
        <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
    </schema>

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

    <dataHost name="localhost1" 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="localhost:3306" user="root"
       password="root">
    </writeHost>
    </dataHost>
</mycat:schema>

rule.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
    <tableRule name="auto-sharding-long">
        <rule>
            <columns>id</columns>
            rang-long
        </rule>
    </tableRule>

    <function name="rang-long"
            class="io.mycat.route.function.AutoPartitionByLong">
        <property name="mapFile">autopartition-long.txt</property>
    </function>
</mycat:rule>

conf目錄下的autopartition-long.txt

# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2

上面的配置建立了一個名爲TESTDB的邏輯庫,並指定了須要切分的表<table>標籤,表名爲travelrecord,分區的策略採用rang-long算法,即根據id數據列值的範圍進行切分,具體的規則在autopartition-long.txt文件中定義,即id0-500*10000範圍內的記錄存放在db1travelrecord表中,id500*10000 - 1000*10000範圍內的記錄存放在db2數據庫的travelrecord表中,下面咱們插入兩條數據,驗證是否和分片規則一致。

建立db1,db2,db3數據庫

create database db1 character set utf8;
create database db2 character set utf8;
create database db3 character set utf8;

登錄Mycat服務器

mysql -uroot -proot -P8066 -h127.0.0.1

建立travelrecord表並插入id等於1,id等於5000010兩條記錄

建立數據表後,數據庫結構以下:

插入兩條記錄:

能夠看到,id等於1的記錄被插入到db1中,id等於5000010的記錄被插入到db2中,那麼數據庫是否真的是這樣呢?

確實是這樣的,到此咱們就完成了mycat數據庫的水平切分,這個例子只是演示按照id列值得範圍進行切分,mycat還支持不少的分片算法,如取模、一致性哈希算法、按日期分片算法等等,你們能夠看《分佈式數據庫架構及企業實戰----基於Mycat中間件》這本書深刻學習。

爲何須要讀寫分離

至於爲何須要讀寫分離,在我以前的文章有介紹過了,相信看到這篇文章的人也知道爲何須要讀寫分離了,固然若是你也須要了解一下,那麼歡迎查看我以前的文章SpringBoot Mybatis 讀寫分離配置,順便也能夠了解一下怎麼經過代碼進行讀寫分離的

MySQL主從複製

主從複製是讀寫分離的關鍵,無論經過什麼方式進行讀寫分離,前提就是MySQL有主從複製,當前雙機主從也行,可是關鍵的關鍵,是要能保證2個庫的數據能一致(出掉剛寫入主庫從庫還未能及時反應過來的狀況),若是2個庫的數據不一致,那麼讀寫分離也有沒有任何意義了,具體MySQL怎麼作主從複製能夠查看我以前的文章MySQL主從複製搭建,基於日誌(binlog)

Mycat讀寫分離設置

配置Mycat用戶

Mycat的用戶就跟MySQL用戶是同一個意思,主要配置連接到Mycat的用戶名以及密碼,以及能使用的邏輯庫,用戶信息主要在server.xml中配置的,具體以下

<?xml version="1.0" encoding="UTF-8"?>  
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");  
    - you may not use this file except in compliance with the License. - You 
    may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
    - - Unless required by applicable law or agreed to in writing, software - 
    distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
    License for the specific language governing permissions and - limitations 
    under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">  
<mycat:server xmlns:mycat="http://io.mycat/">  
    <system>
    <property name="defaultSqlParser">druidparser</property>
      <!--  <property name="useCompression">1</property>--> <!--1爲開啓mysql壓縮協議-->
    <!-- <property name="processorBufferChunk">40960</property> -->
    <!-- 
    <property name="processors">1</property> 
    <property name="processorExecutor">32</property> 
     -->
        <!--默認是65535 64K 用於sql解析時最大文本長度 -->
        <!--<property name="maxStringLiteralLength">65535</property>-->
        <!--<property name="sequnceHandlerType">0</property>-->
        <!--<property name="backSocketNoDelay">1</property>-->
        <!--<property name="frontSocketNoDelay">1</property>-->
        <!--<property name="processorExecutor">16</property>-->
        <!-- 
            <property name="mutiNodeLimitType">1</property> 0:開啓小數量級(默認) ;1:開啓億級數據排序
            <property name="mutiNodePatchSize">100</property> 億級數量排序批量
            <property name="processors">32</property> <property name="processorExecutor">32</property> 
            <property name="serverPort">8066</property> <property name="managerPort">9066</property> 
            <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
            <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
    </system>
    <user name="raye">
        <property name="password">rayewang</property>
        <property name="schemas">separate</property>
    </user>

        </host> 
</mycat:server>

其中<user name="raye">定義了一個名爲raye的用戶,標籤user中的<property name="password">rayewang</property>定義了用戶的密碼,<property name="schemas">separate</property>定義了用戶可使用的邏輯庫

配置Mycat邏輯庫

Mycat的配置有不少,不過由於咱們只是使用Mycat的讀寫分類的功能,因此用到的配置並很少,只須要配置一些基本的,固然本文也只是會介紹到讀寫分離相關的配置,其餘配置建議讀者本身查看一下文檔,或者經過其餘方式瞭解,邏輯庫是在schema.xml中配置的

首先介紹Mycat邏輯庫中的一些配置標籤

schema

schema 標籤是用來定義邏輯庫的,schema有四個屬性dataNode,checkSQLschema,sqlMaxLimit,name

dataNode 標籤屬性用於綁定邏輯庫到某個具體的 database 上,1.3 版本若是配置了 dataNode,則不能夠配置分片表,1.4 能夠配置默認分片,只須要配置須要分片的表便可

name是定義當前邏輯庫的名字的,方便server.xml中定義用戶時的引用

checkSQLschema當該值設置爲 true 時,若是咱們執行語句select from separate.users;則 MyCat 會把語句修改 爲select from users;。即把表示 schema 的字符去掉,避免發送到後端數據庫執行時報(ERROR 1146 (42S02): Table ‘separate.users’ doesn’t exist)。 不過,即便設置該值爲 true ,若是語句所帶的是並不是是 schema 指定的名字,例如:select * from db1.users; 那麼 MyCat 並不會刪除 db1 這個字段,若是沒有定義該庫的話則會報錯,因此在提供 SQL語句的最好是不帶這個字段。

sqlMaxLimit當該值設置爲某個數值時。每條執行的 SQL 語句,若是沒有加上 limit 語句,MyCat 也會自動的加上所對應的值。例如設置值爲 100,執行select from users;的效果爲和執行select from users limit 100;相同。設置該值的話,MyCat 默認會把查詢到的信息所有都展現出來,形成過多的輸出。因此,在正常使用中,仍是建議加上一個值,用於減小過多的數據返回。固然 SQL 語句中也顯式的指定 limit 的大小,不受該屬性的約束。須要注意的是,若是運行的 schema 爲非拆分庫的,那麼該屬性不會生效。須要手動添加 limit 語句。

schema標籤中有標籤table用於定義不一樣的表分片信息,不過咱們只是作讀寫分離,並不會用到,因此這裏就很少介紹了

dataNode

dataNodedataNode 標籤訂義了 MyCat 中的數據節點,也就是咱們一般說所的數據分片。一個 dataNode 標籤就是一個獨立的數據分片,dataNode有3個屬性:name,dataHost,database

name定義數據節點的名字,這個名字須要是惟一的,此名字是用於table標籤和schema標籤中引用的

dataHost該屬性用於定義該分片屬於哪一個數據庫實例的,屬性值是引用 dataHost 標籤上定義的 name 屬性

database該屬性用於定義該分片屬性哪一個具體數據庫實例上的具體庫,由於這裏使用兩個緯度來定義分片,就是:實例+具體的庫。由於每一個庫上創建的表和表結構是同樣的。因此這樣作就能夠輕鬆的對錶進行水平拆分

dataHost

dataHost是定義真實的數據庫鏈接的標籤,該標籤在 mycat 邏輯庫中也是做爲最底層的標籤存在,直接定義了具體的數據庫實例、讀寫分離配置和心跳語句,dataHost有7個屬性:name,maxCon,minCon,balance,writeType,dbType,dbDriver,有2個標籤heartbeat,writeHost,其中writeHost標籤中又包含一個readHost標籤

name惟一標識 dataHost 標籤,供dataNode標籤使用

maxCon指定每一個讀寫實例鏈接池的最大鏈接。也就是說,標籤內嵌套的 writeHost、readHost 標籤都會使用這個屬性的值來實例化出鏈接池的最大鏈接數

minCon指定每一個讀寫實例鏈接池的最小鏈接,初始化鏈接池的大小

balance 讀取負載均衡類型

  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 不負擔讀壓力

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

  1. writeType="0", 全部寫操做發送到配置的第一個 writeHost,第一個掛了切到還生存的第二個writeHost,從新啓動後已切換後的爲準,切換記錄在配置文件中:dnindex.properties .
  2. writeType="1",全部寫操做都隨機的發送到配置的 writeHost

dbType 指定後端鏈接的數據庫類型,目前支持二進制的 mysql 協議,還有其餘使用 JDBC 鏈接的數據庫。例如:mongodb、oracle、spark 等

dbDriver指定鏈接後端數據庫使用的 Driver,目前可選的值有 native 和 JDBC。使用 native 的話,由於這個值執行的 是二進制的 mysql 協議,因此可使用 mysql 和 maridb。其餘類型的數據庫則須要使用 JDBC 驅動來支持。從 1.6 版本開始支持 postgresql 的 native 原始協議。 若是使用 JDBC 的話須要將符合 JDBC 4 標準的驅動 JAR 包放到 MYCATlib 目錄下,並檢查驅動 JAR 包中包括以下目錄結構的文件:META-INFservicesjava.sql.Driver。在這個文件內寫上具體的 Driver 類名,例如: com.mysql.jdbc.Driver。

heartbeat這個標籤內指明用於和後端數據庫進行心跳檢查的語句。例如,MYSQL 可使用 select user(),Oracle 可使用 select 1 from dual 等。 這個標籤還有一個 connectionInitSql 屬性,主要是當使用 Oracla 數據庫時,須要執行的初始化 SQL 語句就這個放到這裏面來。例如:alter session set nlsdateformat='yyyy-mm-dd hh24:mi:ss'

writeHostreadHost這兩個標籤都指定後端數據庫的相關配置給 mycat,用於實例化後端鏈接池。惟一不一樣的是,writeHost 指定寫實例、readHost 指定讀實例,組着這些讀寫實例來知足系統的要求。 在一個 dataHost 內能夠定義多個 writeHost 和 readHost。可是,若是 writeHost 指定的後端數據庫宕機,那麼這個 writeHost 綁定的全部 readHost 都將不可用。另外一方面,因爲這個 writeHost 宕機系統會自動的檢測到,並切換到備用的 writeHost 上去,這2個標籤屬性都一致,擁有host,url,password,user,weight,usingDecrypt等屬性

host用於標識不一樣實例,通常 writeHost 咱們使用M1,readHost 咱們用S1

url真實數據庫的實例的連接地址,若是是使用 native 的 dbDriver,則通常爲 address:port 這種形式。用 JDBC 或其餘的dbDriver,則須要特殊指定。當使用 JDBC 時則能夠這麼寫:jdbc:mysql://localhost:3306/

user真實數據庫實例的連接用戶名

password真實數據庫實例的連接密碼

weight權重 配置在 readhost 中做爲讀節點的權重,主要用於多臺讀取的數據庫實例機器配置不一樣的狀況,能夠根據權重調整訪問量

usingDecrypt是否對密碼加密默認 0 否 如須要開啓配置 1,同時使用加密程序對密碼加密

注意,readHost是在writeHost標籤內的,不是單獨的

如下是個人讀寫分離配置文件

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

    <schema name="separate" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"/>
    <dataNode name="dn1" dataHost="localhost1" database="test" />

    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
              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.1.126:3307" user="root"
                   password="123456">
            <!-- can have multi read hosts -->
            <readHost host="hostS2" url="192.168.1.126:3308" user="root" password="123456" />
        </writeHost>

    </dataHost>

</mycat:schema>

前面已經差很少都解釋清楚了,由於我只是用的基本的主從複製,因此個人將dataHostbalance設置成了3

啓動mycat,而後用數據庫鏈接工具鏈接到mycat,能夠測試是否配置成功,最簡單的就是經過修改從庫的數據,這樣方便查看究竟是運行到哪一個庫上面了,另外因爲我是基於docker啓動的mycat,因此若是是直接在系統中運行的mycat的,能夠去看官方文檔,看看到底怎麼啓動mycat

微信公衆號【黃小斜】大廠程序員,互聯網行業新知,終身學習踐行者。關注後回覆「Java」、「Python」、「C++」、「大數據」、「機器學習」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經」、「計算機基礎」、「LeetCode」 等關鍵字能夠獲取對應的免費學習資料。

                     ​​

相關文章
相關標籤/搜索