MySQL多數據源筆記4-Mycat中間件實戰


Mycat 是數據庫中間件,就是介於數據庫與應用之間,進行數據處理與交互的中間服 務。由於前面講的對數據進行分片處理之后,從原有的一個庫,被切分為多個分片數據庫,所有的分片數據庫集 群構成了整個完整的數據庫存儲。

如下圖:

如上圖所表示,數據被分到多個分片數據庫后,應用如果需要讀取數據,就要需要處理多個數據源的數據。

如果沒有數據庫中間件,那么應用將直接面對分片集群,數據源切換、事務處理、數據聚合都需要應用直接處 理,原本該是專注於業務的應用,將會花大量的工作來處理分片后的問題,最重要的是每個應用處理將是完全的 重復造輪子。

所以有了數據庫中間件,應用只需要集中與業務處理,大量的通用的數據聚合,事務,數據源切換都由中間 件來處理,中間件的性能與處理能力將直接決定應用的讀寫性能,所以一款好的數據庫中間件至關重要。

 

第一部MyCat的環境搭建。

首先去官網下載MyCat,官網地址為:dl.mycat.io

注意必須下載發行版,也就是說帶有RELEASE字眼的就是發行版,BETA是測試版。選擇windows版本來學習即可。

 

我們主要關注的是MyCat的conf目錄如下圖:

 

 我們打開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">
        <!-- auto sharding by id (long) -->
        <table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

        <!-- global table is auto cloned to all defined data nodes ,so can join
            with any table whose sharding node is in the same data node -->
        <table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
        <table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />
        <!-- random sharding using mod sharind rule -->
        <table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"
               rule="mod-long" />
        <!-- <table name="dual" primaryKey="ID" dataNode="dnx,dnoracle2" type="global"
            needAddLimit="false"/> <table name="worker" primaryKey="ID" dataNode="jdbc_dn1,jdbc_dn2,jdbc_dn3"
            rule="mod-long" /> -->
        <table name="employee" primaryKey="ID" dataNode="dn1,dn2"
               rule="sharding-by-intfile" />
        <table name="customer" primaryKey="ID" dataNode="dn1,dn2"
               rule="sharding-by-intfile">
            <childTable name="orders" primaryKey="ID" joinKey="customer_id"
                        parentKey="id">
                <childTable name="order_items" joinKey="order_id"
                            parentKey="id" />
            </childTable>
            <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
                        parentKey="id" />
        </table>
        <!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
            /> -->
    </schema>
    <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"
        /> -->
    <dataNode name="dn1" dataHost="localhost1" database="db1" />
    <dataNode name="dn2" dataHost="localhost1" database="db2" />
    <dataNode name="dn3" dataHost="localhost1" database="db3" />
    <!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
     <dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" />
    <dataNode    name="jdbc_dn2" dataHost="jdbchost" database="db2" />
    <dataNode name="jdbc_dn3"     dataHost="jdbchost" 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="123456">
            <!-- can have multi read hosts -->
            <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
        </writeHost>
        <writeHost host="hostS1" url="localhost:3316" user="root"
                   password="123456" />
        <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
    </dataHost>
    <!--
        <dataHost name="sequoiadb1" maxCon="1000" minCon="1" balance="0" dbType="sequoiadb" dbDriver="jdbc">
        <heartbeat>         </heartbeat>
         <writeHost host="hostM1" url="sequoiadb://1426587161.dbaas.sequoialab.net:11920/SAMPLE" user="jifeng"     password="jifeng"></writeHost>
         </dataHost>

      <dataHost name="oracle1" maxCon="1000" minCon="1" balance="0" writeType="0"     dbType="oracle" dbDriver="jdbc"> <heartbeat>select 1 from dual</heartbeat>
        <connectionInitSql>alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'</connectionInitSql>
        <writeHost host="hostM1" url="jdbc:oracle:thin:@127.0.0.1:1521:nange" user="base"     password="123456" > </writeHost> </dataHost>

        <dataHost name="jdbchost" maxCon="1000"     minCon="1" balance="0" writeType="0" dbType="mongodb" dbDriver="jdbc">
        <heartbeat>select     user()</heartbeat>
        <writeHost host="hostM" url="mongodb://192.168.0.99/test" user="admin" password="123456" ></writeHost> </dataHost>

        <dataHost name="sparksql" maxCon="1000" minCon="1" balance="0" dbType="spark" dbDriver="jdbc">
        <heartbeat> </heartbeat>
         <writeHost host="hostM1" url="jdbc:hive2://feng01:10000" user="jifeng"     password="jifeng"></writeHost> </dataHost> -->

    <!-- <dataHost name="jdbchost" maxCon="1000" minCon="10" balance="0" dbType="mysql"
        dbDriver="jdbc"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1"
        url="jdbc:mysql://localhost:3306" user="root" password="123456"> </writeHost>
        </dataHost> -->
</mycat:schema>

 

schema 標簽用於定義 MyCat 實例中的邏輯庫,MyCat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配 置。可以使用 schema 標簽來划分這些不同的邏輯庫。 如果不配置 schema 標簽,所有的表配置,會屬於同一個默認的邏輯庫。

對於我們開發人員來說,我們知道連接到mycat的邏輯庫,后面拖着多少個MySQL我們不管的,我們只需要連接到MyCat這個邏輯庫,對於后面的分庫分表,MyCat給我們屏蔽了分庫分表的復雜性。

 

table 標簽定義了 MyCat 中的邏輯表,所有需要拆分的表都需要在這個標簽中定義。

    table標簽里面的子標簽childTabel表示這個表跟父table分在一起,不會被拆散,也就是前面所說的分庫分表之前,要考慮好表的關聯,不然否則就面臨跨庫Join連接問題。

    如下代碼:

    

<table name="customer" primaryKey="ID" dataNode="dn1,dn2"
               rule="sharding-by-intfile">
            <childTable name="orders" primaryKey="ID" joinKey="customer_id"
                        parentKey="id">
                <childTable name="order_items" joinKey="order_id"
                            parentKey="id" />
            </childTable>
            <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
                        parentKey="id" />
        </table>

 

    table中的type屬性的global表示該表為全局表。即前面所提到每一個節點可以讀到這個表,這對是否在分庫分表中的join查詢很關鍵。而且這屬性表示不會進行分片,即全局表使用,每個節點都有。代碼如下:

    

<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />

 

  

    table中的dataNode屬性表示你要分片,要分到那幾個節點上去,rule代表着分庫分表的規則。他的分片分表規則在rule.xml文件中,你可以在Table標簽的rule屬性設置復合

    自己的分片分表規則,都在rule.xml中對應着如下圖:

    

 

      

      

 <dataNode>標簽,標簽中的name屬性表示節點的名字。dataHost屬性表示對應MySQL的數據庫連接,database屬性表示Mysql數據庫名,代碼如下:

  

<dataNode name="dn1" dataHost="localhost1" database="db1" />

 

<dataHost>標簽節點表示對應MySQL的數據庫連接對應配置,什么最大連接數,最小連接數之類的屬性。

<dataHost>標簽中的子標簽<hearbeat>表示存活檢測,

<dataHost>標簽中的子標簽<writeHost>和<readHost>表示MySQL中的讀寫分離,而<writeHost>子標簽中還有<readHost>子標簽,表示寫操作的數據庫還要承擔一部分讀庫的壓力。

代碼如下:

<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="123456">
            <!-- can have multi read hosts -->
            <readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
        </writeHost>
        <writeHost host="hostS1" url="localhost:3316" user="root"
                   password="123456" />
        <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
    </dataHost>

 

 

下面進行讀寫分離的演示:

  第一步先注釋schma里面的配置如下圖:

 

接着在修改<dataNode>,<dataHost>節點信息,詳細信息在圖中說明。如下圖:

 

   

 接着再還要修改mycat中server.xml文件,我這里沒有使用zookeeper所以要把zookeeper協調切換關閉。因為我們只是在本地玩,如下圖:

接着在繼續修改server.xml文件。如下圖:

接着就是啟動了,啟動之前要進行環境變量設置如下:

 

 接着就是設置一起啟動參數了,在startup_newrap.bat文件中修改如下圖:

 

 接着就是啟動了,如下:

 

接着就是用圖形化工具連接MyCat了。如下圖:

 

接着自己在圖形化界面中修改數據庫,這里就不演示了。如下:

 

 

接着mycat進行分庫分表演示:

 

注意一定要在每一個mysql中建立好tabel標簽對應的travelrecord表,而表中必須要有id這屬性,

如下圖:

 

 

 注意一定要在每一個mysql中建立好tabel標簽對應的travelrecord表,而表中必須要有id這屬性,因為上面的分庫分表策略是根據id分的,在rule.xml中找到分表策略如下:

 

 在根據rang-long在rule.xml找到對應的function,如下圖:

在找到autoparitition-long.txt文件,看到如下分庫分表了,如下圖:

然后在分別對應修改dataNode和dataHost標簽,如下圖:

 

 

 

最后進行分庫分表測試

比如490M=4900000分到第0個節點,在mycat總設置,如下圖:

接着去查看第0個節點會有一條數據分到這里,其他節點沒有。

 如果使用上面的分庫分表策略不能超過范autoparitition-long.txt里面配置的范圍的。

其他的分配策略,還可以用CRC32slot策略類似於redis集群中的Slot,如下:

 

 

 還可以用rang-mod求模來分,如下:

然后找partition-range-mod.txt,可以具體,如下:

其他就不演示了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM