MyCat 讀寫分離 資料庫分庫分表 中介軟體 安裝部署,及簡單使用

搜雲庫技術團隊發表於2019-03-01

MyCat是一個開源的分散式資料庫系統,是一個實現了MySQL協議的伺服器,前端使用者可以把它看作是一個資料庫代理,用MySQL客戶端工具和命令列訪問,而其後端可以用MySQL原生協議與多個MySQL伺服器通訊,也可以用JDBC協議與大多數主流資料庫伺服器通訊,其核心功能是分表分庫,即將一個大表水平分割為N個小表,儲存在後端MySQL伺服器裡或者其他資料庫裡。

MyCat發展到目前的版本,已經不是一個單純的MySQL代理了,它的後端可以支援MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流資料庫,也支援MongoDB這種新型NoSQL方式的儲存,未來還會支援更多型別的儲存。而在終端使用者看來,無論是那種儲存方式,在MyCat裡,都是一個傳統的資料庫表,支援標準的SQL語句進行資料的操作,這樣一來,對前端業務系統來說,可以大幅降低開發難度,提升開發速度

網上很有多相關資源,也可以直接訪問Mycat官網。

www.mycat.io/

環境

MySql-Master:192.168.252.121
MySql-Slave:192.168.252.122

Mycat:192.168.252.123
複製程式碼

MySql 主從複製

參考我的另一篇文章-搭建 MySQL 5.7.19 主從複製

在 MySql-Master:192.168.252.121 建庫,測試主從複製是否可用

CREATE DATABASE `db_1`;
CREATE DATABASE `db_2`;
CREATE DATABASE `db_3`;
複製程式碼

Mycat 安裝部署

cd /opt
tar -zxvf Mycat-server-1.6.5-release-20171029183033-linux.tar.gz -C /usr/local/
複製程式碼

更好看目錄結構,下tree(可選)

yum -y install tree
複製程式碼
tree /usr/local/mycat/
複製程式碼
/usr/local/mycat/
├── bin
│   ├── dataMigrate.sh
│   ├── init_zk_data.sh
│   ├── mycat
│   ├── rehash.sh
│   ├── startup_nowrap.sh
│   ├── wrapper-linux-ppc-64
│   ├── wrapper-linux-x86-32
│   └── wrapper-linux-x86-64
├── catlet
├── conf
│   ├── autopartition-long.txt
│   ├── auto-sharding-long.txt
│   ├── auto-sharding-rang-mod.txt
│   ├── cacheservice.properties
│   ├── dbseq.sql
│   ├── ehcache.xml
│   ├── index_to_charset.properties
│   ├── log4j2.xml
│   ├── migrateTables.properties
│   ├── myid.properties
│   ├── partition-hash-int.txt
│   ├── partition-range-mod.txt
│   ├── rule.xml
│   ├── schema.xml
│   ├── sequence_conf.properties
│   ├── sequence_db_conf.properties
│   ├── sequence_distributed_conf.properties
│   ├── sequence_time_conf.properties
│   ├── server.xml
│   ├── sharding-by-enum.txt
│   ├── wrapper.conf
│   ├── zkconf
│   │   ├── autopartition-long.txt
│   │   ├── auto-sharding-long.txt
│   │   ├── auto-sharding-rang-mod.txt
│   │   ├── cacheservice.properties
│   │   ├── ehcache.xml
│   │   ├── index_to_charset.properties
│   │   ├── partition-hash-int.txt
│   │   ├── partition-range-mod.txt
│   │   ├── rule.xml
│   │   ├── schema.xml
│   │   ├── sequence_conf.properties
│   │   ├── sequence_db_conf.properties
│   │   ├── sequence_distributed_conf-mycat_fz_01.properties
│   │   ├── sequence_distributed_conf.properties
│   │   ├── sequence_time_conf-mycat_fz_01.properties
│   │   ├── sequence_time_conf.properties
│   │   ├── server-mycat_fz_01.xml
│   │   ├── server.xml
│   │   └── sharding-by-enum.txt
│   └── zkdownload
│       └── auto-sharding-long.txt
.....
省略更多

7 directories, 95 files
複製程式碼

安裝 JDK

下載Linux環境下的jdk1.8,請去(官網)中下載jdk的安裝檔案

我在百度雲盤分下的連結:pan.baidu.com/s/1jIFZF9s 密碼:u4n4

上傳在 /opt 目錄

解壓

cd /opt
tar zxvf jdk-8u144-linux-x64.tar.gz
mv jdk1.8.0_144/ /lib/jvm
複製程式碼

配置環境變數

vi /etc/profile
複製程式碼
#jdk
export JAVA_HOME=/lib/jvm
export JRE_HOME=${JAVA_HOME}/jre   
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib   
export PATH=${JAVA_HOME}/bin:$PATH 
複製程式碼

使環境變數生效

source /etc/profile
複製程式碼

驗證

[root@localhost ~]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
複製程式碼

環境變數

設定 MYCAT_HOME 的變數

export PATH=${JAVA_HOME}/bin:${MYCAT_HOME}/lib:$PATH
export MYCAT_HOME=/usr/local/mycat/
複製程式碼

使環境變數生效

source /etc/profile
複製程式碼

配置 JDK 路徑

告訴 Mycat 需要使用哪個 JDK

vim wrapper.conf
複製程式碼
#********************************************************************
# Wrapper Properties
#********************************************************************
# Java Application
wrapper.java.command=/lib/jvm/bin/java
wrapper.working.dir=..
複製程式碼

wrapper.conf jvm調優引數,不合理,需改進

# Java Additional Parameters
#wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
wrapper.java.additional.5=-XX:MaxDirectMemorySize=2G
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
wrapper.java.additional.10=-Xmx4G
wrapper.java.additional.11=-Xms1G
複製程式碼

jvm引數調優,以16G記憶體伺服器為例

# Java Additional Parameters
#wrapper.java.additional.1=
wrapper.java.additional.1=-DMYCAT_HOME=.
wrapper.java.additional.2=-server
wrapper.java.additional.3=-XX:MaxPermSize=64M
wrapper.java.additional.4=-XX:+AggressiveOpts
#堆記憶體適度大小,直接對映記憶體儘可能大,兩種一起佔據伺服器的1/2-2/3的記憶體
wrapper.java.additional.5=-XX:MaxDirectMemorySize=6G
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
#無論擴充套件還是縮減新生代空間或老年代空間都需要進行Full GC,而Full GC會降低程式的吞吐量並導致更長的延遲。
wrapper.java.additional.10=-Xmx4G
wrapper.java.additional.11=-Xms4G
複製程式碼

配置 Mycat

配置檔案非常多.如果只是簡單配置在不同的伺服器上進行讀寫分離只需要配置兩個檔案 server.xmlschema.xml

schema.xml 中定義邏輯庫,表、分片節點等內容
rule.xml 中定義分片規則
server.xml 中定義使用者以及系統相關變數,如埠等

server.xml

server.xml 幾乎儲存了所有 mycat 需要的系統配置資訊。其在程式碼內直接的對映類為 System Config 類。

vim server.xml
複製程式碼
<user name="root" defaultAccount="true">
	<property name="password">123456</property>
	<property name="schemas">test_schema</property>
	
	<!-- 表級 DML 許可權設定 -->
	<!--
	<privileges check="false">
		<schema name="test_schema" dml="0110" >
			<table name="tb01" dml="0000"></table>
			<table name="tb02" dml="1111"></table>
		</schema>
	</privileges>
	 -->		 
</user>


<user name="user">
	<property name="password">user</property>
	<property name="schemas">test_schema</property>
	<property name="readOnly">true</property>
</user>

複製程式碼

server.xml 中的標籤本就不多,這個標籤主要用於定義登入 mycat 的使用者和許可權。

例如上面的例子中,我定義了一個使用者,使用者名稱為 root 、密碼也為 123456,可訪問的 schema 也只有 test_schema 一個 邏輯庫。

官方完整的預設配置 server.xml

Mycat 系統配置

<system>
    <property name="nonePasswordLogin">0</property>
    <!-- 0為需要密碼登陸、1為不需要密碼登陸 ,預設為0,設定為1則需要指定預設賬戶-->
    <property name="useHandshakeV10">1</property>
    <property name="useSqlStat">0</property>
    <!-- 1為開啟實時統計、0為關閉 -->
    <property name="useGlobleTableCheck">0</property>
    <!-- 1為開啟全加班一致性檢測、0為關閉 -->
    <property name="sequnceHandlerType">2</property>
    <property name="subqueryRelationshipCheck">false</property>

    <!-- 子查詢中存在關聯查詢的情況下,檢查關聯欄位中是否有分片欄位 .預設 false -->
    <!-- <property name="useCompression">1</property>-->

    <!--1為開啟mysql壓縮協議-->
    <!-- <property name="fakeMySQLVersion">5.6.20</property>-->

    <!--設定模擬的MySQL版本號-->
    <!-- <property name="processorBufferChunk">40960</property> -->

    <!--
    <property name="processors">1</property>
    <property name="processorExecutor">32</property>
     -->

    <!--預設為type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
    <property name="processorBufferPoolType">809600000</property>

    <!--預設是65535 64K 用於sql解析時最大文字長度 -->
    <!--<property name="maxStringLiteralLength">65535</property>-->
    <!--<property name="sequnceHandlerType">1</property>-->
    <!--<property name="backSocketNoDelay">1</property>-->
    <!--<property name="frontSocketNoDelay">1</property>-->
    <!--<property name="processorExecutor">16</property>-->


    <property name="serverPort">8066</property>
    <property name="managerPort">9066</property>
    <!--預設本機-->
    <property name="idleTimeout">3800000</property>
    <property name="bindIp">0.0.0.0</property>
    <property name="frontWriteQueueSize">4096</property>
    <property name="processors">32</property>

    <!--
     分散式事務開關,0為不過濾分散式事務,1為過濾分散式事務
    (如果分散式事務內只涉及全域性表,則不過濾),2為不過濾分散式事務,但是記錄分散式事務日誌
    -->

    <property name="handleDistributedTransactions">0</property>

    <!--off heap for merge/order/group/limit 1開啟   0關閉-->
    <property name="useOffHeapForMerge">1</property>
    <!--單位為m-->
    <property name="memoryPageSize">64k</property>
    <!--單位為k-->
    <property name="spillsFileBufferSize">1k</property>
    <property name="useStreamOutput">0</property>
    <!--單位為m-->
    <property name="systemReserveMemorySize">384m</property>
    <!--是否採用zookeeper協調切換  -->
    <property name="useZKSwitch">false</property>
    <!-- XA Recovery Log日誌路徑 -->
    <!--<property name="XARecoveryLogBaseDir">./</property>-->
    <!-- XA Recovery Log日誌名稱 -->
    <!--<property name="XARecoveryLogBaseName">tmlog</property>-->
</system>
複製程式碼

schema.xml

schema 標籤用於定義 My Cat 例項中的邏輯庫,My Cat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配
置。可以使用 schema 標籤來劃分這些不同的邏輯庫。

vim schema.xml
複製程式碼
<?xml version="1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- 設定表的儲存方式.schema name="test_schema" 與 server.xml中的 test_schema 設定一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
    </schema>

    <!-- 設定dataNode 對應的資料庫,及 mycat 連線的地址dataHost -->
    <dataNode name="dn1" dataHost="dh_test" database="db_1"/>
    <dataNode name="dn2" dataHost="dh_test" database="db_2"/>
    <dataNode name="dn3" dataHost="dh_test" database="db_3"/>

    <!-- mycat 邏輯主機dataHost對應的物理主機.其中也設定對應的mysql登陸資訊 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>
複製程式碼

如上所示的配置就配置了1個邏輯庫,邏輯庫的概念和 MYSQL 資料庫中 Database 的概念相同,我們在查詢這個邏輯庫中表的時候需要切換到該邏輯庫下才可以查詢到所需要的表。

schema 標籤

用於定義 My Cat 例項中的邏輯庫,My Cat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配
置。可以使用 schema 標籤來劃分這些不同的邏輯庫。

data Node 屬性

該屬性用於繫結邏輯庫到某個具體的 database 上,1.3 版本如果配置了 data Node,則不可以配置分片表,
1.4 可以配置預設分片,只需要配置需要分片的表即可

data Host 標籤

作為 Schema.xml 中最後的一個標籤,該標籤在 mycat 邏輯庫中也是作為最底層的標籤存在,直接定義了具體的資料庫例項、讀寫分離配置和心跳語句。現在我們就解析下這個標籤。

name 屬性

唯一標識 data Host 標籤,供上層的標籤使用。

max Con 屬性

指定每個讀寫例項連線池的最大連線。也就是說,標籤內巢狀的 write Host、read Host 標籤都會使用這個屬性的值來例項化出連線池的最大連線數。

min Con 屬性

指定每個讀寫例項連線池的最小連線,初始化連線池的大小。

balance 屬性

負載均衡型別,目前的取值有 3 種:

1.balance=”0″, 不開啟讀寫分離機制,所有讀操作都傳送到當前可用的 write Host 上。
2.balance=”1″,全部的 read Host 與 stand by write Host 參與 select 語句的負載均衡,簡單的說,當雙主雙從模式(M1->S1,M2->S2,並且 M1 與 M2 互為主備),正常情況下,M2,S1,S2 都參與 select 語句的負載
均衡。
3.balance=”2″,所有讀操作都隨機的在 write Host、readhost 上分發。
4.balance=”3″,所有讀請求隨機的分發到 wiriter Host 對應的 readhost 執行,writer Host 不負擔讀壓
力,注意 balance=3 只在 1.4 及其以後版本有,1.3 沒有。

write Type 屬性

負載均衡型別,目前的取值有 3 種:

  1. write Type=”0″, 所有寫操作傳送到配置的第一個 write Host,第一個掛了切到還生存的第二個write Host,重新啟動後已切換後的為準,切換記錄在配置檔案中:dnindex.properties .
  2. write Type=”1″,所有寫操作都隨機的傳送到配置的 write Host,1.5 以後廢棄不推薦。

**switch Type 屬性

-1 表示不自動切換
1 預設值,自動切換
2 基於 My SQL 主從同步的狀態決定是否切換

db Type 屬性

指定後端連線的資料庫型別,目前支援二進位制的 mysql 協議,還有其他使用 JDBC 連線的資料庫。例如:mongodb、oracle、spark 等。

db Driver 屬性

指定連線後端資料庫使用的 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。

switch Type 屬性

-1 表示不自動切換
1 預設值,自動切換
2 基於 My SQL 主從同步的狀態決定是否切換 心跳語句為 show slave status
3 基於 My SQL galary cluster 的切換機制(適合叢集)(1.4.1) 心跳語句為 show status like ‘wsrep%’.

temp Read Host Available 屬性

如果配置了這個屬性 write Host 下面的 read Host 仍舊可用,預設 0 可配置(0、1)

rule.xml

rule.xml 裡面就定義了我們對錶進行拆分所涉及到的規則定義。我們可以靈活的對錶使用不同的分片演算法,或者對錶使用相同的演算法但具體的引數不同。這個檔案裡面主要有 table Rule 和 function 這兩個標籤。在具體使用過程中可以按照需求新增 table Rule 和 function。

vim rule.xml
複製程式碼
<tableRule name="sharding-by-date">
    <rule>
        <columns>create_time</columns>
        <algorithm>sharding-by-date-day</algorithm>
    </rule>
</tableRule>

<function name="sharding-by-date-day" class="io.mycat.route.function.PartitionByDate">
    <property name="dateFormat">yyyy-MM-dd</property>
    <property name="sBeginDate">2017-11-15</property>
    <property name="sEndDate">2017-11-17</property>
    <property name="sPartionDay">1</property>
</function>
複製程式碼

這個標籤定義表規則。
定義的表規則,在 schema.xml:

tableRule name=”sharding-by-date”

<schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
	<table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
</schema>
複製程式碼

啟動 Mycat

/usr/local/mycat/bin
./mycat start
複製程式碼

檢視日誌

啟動 mycat 的日誌

less /usr/local/mycat/logs/wrapper.log
複製程式碼

訪問 mycat 的日誌

less /usr/local/mycat/logs/mycat.log
複製程式碼

使用 Mycat

登入 Mycat 切換到 test_schema 邏輯庫

mysql -uroot -p123456 -h192.168.252.123 -P 8066
複製程式碼

建立庫/表

mysql> use test_schema;
Database changed
mysql> show tables;
+-----------------------+
| Tables in test_schema |
+-----------------------+
| test_one              |
+-----------------------+
1 row in set

mysql> 
複製程式碼

只需要在 Mycat 伺服器執行以下指令碼,就會自動同步到 MySql-Master:192.168.252.121 MySql-Slave:192.168.252.122

mysql> CREATE TABLE `test_one` (
	`id` BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT `id`,
	`name` VARCHAR (50) DEFAULT NULL COMMENT `名稱`,
	`remark` VARCHAR (500) DEFAULT NULL COMMENT `備註`,
	`create_time` datetime DEFAULT NULL COMMENT `建立時間`,
	PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8mb4 COMMENT = `測試`;

Query OK, 0 rows affected
複製程式碼

登入 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066
複製程式碼

RS_CODE 為 1 表示心跳正常,–檢視讀寫分離的機器配置情況

mysql> show @@datanode;
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST      | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1 |     0 | mysql |      0 |    3 | 1000 |      11 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2 |     0 | mysql |      0 |    3 | 1000 |       7 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3 |     0 | mysql |      0 |    4 | 1000 |      26 |          0 |        0 |       0 |            -1 |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
3 rows in set

mysql> show @@heartbeat;
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| NAME   | TYPE  | HOST            | PORT | RS_CODE | RETRY | STATUS | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME    | STOP  |
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| hostM1 | mysql | 192.168.252.121 | 3306 |       1 |     0 | idle   |       0 | 2,3,3        | 2017-11-17 16:54:26 | false |
| hostS2 | mysql | 192.168.252.122 | 3306 |       1 |     0 | idle   |       0 | 2,2,2        | 2017-11-17 16:54:26 | false |
+--------+-------+-----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
2 rows in set

mysql> 
複製程式碼

測試分片

按日期(天)分片

登入 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066
複製程式碼

RS_CODE 為 1 表示心跳正常,–檢視讀寫分離的機器配置情況

mysql> show @@datanode;
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST      | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1 |     0 | mysql |      0 |    3 | 1000 |      11 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2 |     0 | mysql |      0 |    3 | 1000 |       7 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3 |     0 | mysql |      0 |    4 | 1000 |      26 |          0 |        0 |       0 |            -1 |
+------+--------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
3 rows in set
複製程式碼

配置按日期(天)分片,2017-11-15,2017-11-16,2017-11-17 ,一天一個分片,執行完一下的 sql 可以發現資料 ,會按照分片規則進入不同的,分片,資料庫

rule.xml

<tableRule name="sharding-by-date">
	<rule>
		<columns>create_time</columns>
		<algorithm>sharding-by-date-day</algorithm>
	</rule>
</tableRule>

<function name="sharding-by-date-day" class="io.mycat.route.function.PartitionByDate">
    <property name="dateFormat">yyyy-MM-dd</property>
    <property name="sBeginDate">2017-11-15</property>
    <property name="sEndDate">2017-11-17</property>
    <property name="sPartionDay">1</property>
</function>
複製程式碼

name 屬性指定唯一的名字,用於標識不同的表規則。

內嵌的 rule 標籤則指定對物理表中的哪一列進行拆分和使用什麼路由演算法。

columns 內指定要拆分的列名字。

algorithm 使用 function 標籤中的 name 屬性。連線表規則和具體路由演算法。當然,多個表規則可以連線到同一個路由演算法上。table 標籤內使用。讓邏輯表使用這個規則進行分片。

配置說明:

  • columns :標識將要分片的表欄位
  • algorithm :分片函式
  • dateFormat :日期格式
  • sBeginDate :開始日期
  • sEndDate:結束日期
  • sPartionDay :分割槽天數,即預設從開始日期算起,分隔 5 天一個分割槽

schema.xml

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

    <!-- 設定表的儲存方式.schema name="test_schema" 與 server.xml中的 test_schema 設定一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-date"/>
    </schema>

    <!-- 設定dataNode 對應的資料庫,及 mycat 連線的地址dataHost -->
    <dataNode name="dn1" dataHost="dh_test" database="db_1"/>
    <dataNode name="dn2" dataHost="dh_test" database="db_2"/>
    <dataNode name="dn3" dataHost="dh_test" database="db_3"/>

    <!-- mycat 邏輯主機dataHost對應的物理主機.其中也設定對應的mysql登陸資訊 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>
複製程式碼

登入 Mycat 服務端

mysql -uroot -p123456 -h192.168.252.123 -P 8066
複製程式碼
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_1`, `2017-11-15 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_2`, `2017-11-16 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_3`, `2017-11-17 00:00:00`);
複製程式碼

在 MySql-Master 執行 ,檢視分片是否均勻

mysql -uroot -p123456 -h192.168.252.121 -P 3306
複製程式碼
mysql> select min(create_time),max(create_time) from db_1.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-15 00:00:00 | 2017-11-15 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> select min(create_time),max(create_time) from db_2.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-16 00:00:00 | 2017-11-16 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> select min(create_time),max(create_time) from db_3.test_one;
+---------------------+---------------------+
| min(create_time)    | max(create_time)    |
+---------------------+---------------------+
| 2017-11-17 00:00:00 | 2017-11-17 00:00:00 |
+---------------------+---------------------+
1 row in set

mysql> 
複製程式碼

自然月分片

在 MySql-Master:192.168.252.121 建庫,測試主從複製是否可用

CREATE DATABASE `db_1`;
CREATE DATABASE `db_2`;
CREATE DATABASE `db_3`;
CREATE DATABASE `db_4`;
CREATE DATABASE `db_5`;
CREATE DATABASE `db_6`;
CREATE DATABASE `db_7`;
CREATE DATABASE `db_8`;
CREATE DATABASE `db_9`;
CREATE DATABASE `db_10`;
CREATE DATABASE `db_11`;
CREATE DATABASE `db_12`;
複製程式碼

登入 Mycat 管理端

mysql -uroot -p123456 -h192.168.252.123 -P 9066
複製程式碼

檢視分片情況

mysql> show @@datanode;
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| NAME | DATHOST       | INDEX | TYPE  | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
| dn1  | dh_test/db_1  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn10 | dh_test/db_10 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn11 | dh_test/db_11 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn12 | dh_test/db_12 |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn2  | dh_test/db_2  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn3  | dh_test/db_3  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn4  | dh_test/db_4  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn5  | dh_test/db_5  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn6  | dh_test/db_6  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn7  | dh_test/db_7  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn8  | dh_test/db_8  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
| dn9  | dh_test/db_9  |     0 | mysql |      0 |    0 | 1000 |       0 |          0 |        0 |       0 |            -1 |
+------+---------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+
12 rows in set

mysql> 
複製程式碼

rule.xml

按月份列分割槽 ,每個自然月一個分片

<tableRule name="sharding-by-month">
	<rule>
		<columns>create_time</columns>
		<algorithm>partbymonth</algorithm>
	</rule>
</tableRule>

<function name="partbymonth" class="io.mycat.route.function.PartitionByMonth">
	<property name="dateFormat">yyyy-MM-dd</property>
	<property name="sBeginDate">2017-01-01</property>
</function>
複製程式碼

配置說明:

  • columns 分片欄位,字串型別
  • dateFormat : 日期字串格式
  • sBeginDate : 開始日期

schema.xml

<?xml version="1.0" ?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- 設定表的儲存方式.schema name="test_schema" 與 server.xml中的 test_schema 設定一致  -->
    <schema name="test_schema" checkSQLschema="false" sqlMaxLimit="100">
        <table name="test_one" primaryKey="id" dataNode="dn$1-12" rule="sharding-by-month"/>
    </schema>

    <!-- 設定dataNode 對應的資料庫,及 mycat 連線的地址dataHost -->
    <dataNode name="dn1"  dataHost="dh_test" database="db_1"  />
    <dataNode name="dn2"  dataHost="dh_test" database="db_2"  />
    <dataNode name="dn3"  dataHost="dh_test" database="db_3"  />
    <dataNode name="dn4"  dataHost="dh_test" database="db_4"  />
    <dataNode name="dn5"  dataHost="dh_test" database="db_5"  />
    <dataNode name="dn6"  dataHost="dh_test" database="db_6"  />
    <dataNode name="dn7"  dataHost="dh_test" database="db_7"  />
    <dataNode name="dn8"  dataHost="dh_test" database="db_8"  />
    <dataNode name="dn9"  dataHost="dh_test" database="db_9"  />
    <dataNode name="dn10" dataHost="dh_test" database="db_10" />
    <dataNode name="dn11" dataHost="dh_test" database="db_11" />
    <dataNode name="dn12" dataHost="dh_test" database="db_12" />

    <!-- mycat 邏輯主機dataHost對應的物理主機.其中也設定對應的mysql登陸資訊 -->
    <dataHost name="dh_test" maxCon="1000" minCon="10" balance="0" writeType="0"
              dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
        <!--<heartbeat>select user()</heartbeat>-->
        <heartbeat>show slave status</heartbeat>
        <writeHost host="hostM1" url="192.168.252.121:3306" user="root" password="mima">
            <readHost host="hostS2" url="192.168.252.122:3306" user="root" password="mima"/>
        </writeHost>
    </dataHost>

</mycat:schema>

複製程式碼

登入 Mycat 服務端

mysql -uroot -p123456 -h192.168.252.123 -P 8066
複製程式碼

只需要在 Mycat 伺服器執行以下指令碼,就會自動同步到 MySql-Master:192.168.252.121 MySql-Slave:192.168.252.122

mysql> CREATE TABLE `test_one` (
	`id` BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT `id`,
	`name` VARCHAR (50) DEFAULT NULL COMMENT `名稱`,
	`remark` VARCHAR (500) DEFAULT NULL COMMENT `備註`,
	`create_time` datetime DEFAULT NULL COMMENT `建立時間`,
	PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8mb4 COMMENT = `測試`;

Query OK, 0 rows affected
複製程式碼
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_1`,  `2017-01-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_2`,  `2017-02-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_3`,  `2017-03-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_4`,  `2017-04-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_5`,  `2017-05-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_6`,  `2017-06-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_7`,  `2017-07-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_8`,  `2017-08-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_9`,  `2017-09-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_10`, `2017-10-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_11`, `2017-11-10 00:00:00`);
INSERT INTO `test_one` (`name`, `remark`, `create_time`) VALUES ( `測試資料`, `會分片到 db_12`, `2017-12-10 00:00:00`);
複製程式碼

在 MySql-Master 執行 ,檢視分片是否均勻

mysql -uroot -p123456 -h192.168.252.121 -P 3306
複製程式碼
select min(create_time),max(create_time) from db_1.test_one;
select min(create_time),max(create_time) from db_2.test_one;
select min(create_time),max(create_time) from db_3.test_one;
select min(create_time),max(create_time) from db_4.test_one;
select min(create_time),max(create_time) from db_5.test_one;
select min(create_time),max(create_time) from db_6.test_one;
select min(create_time),max(create_time) from db_7.test_one;
select min(create_time),max(create_time) from db_8.test_one;
select min(create_time),max(create_time) from db_9.test_one;
select min(create_time),max(create_time) from db_10.test_one;
select min(create_time),max(create_time) from db_11.test_one;
select min(create_time),max(create_time) from db_12.test_one;
複製程式碼

注意

啟動MyCAT之前,需要先檢查一些配置:

Mysql的主從複製是否正常,這個檢查我在文章開頭,搭建 MySQL 5.7.19 主從複製,文章連結裡面有介紹

java的版本需要是1.7或以上;

Mysql的配置檔案需要加一行lower_case_table_names = 1在[mysqld]欄目中,這個設定為Mysql大小寫不敏感,否則可能會發生表找不到的問題;

在示例的2個資料 MySql-Master 和 MySql-Slave 上,新建3個資料庫 test_one,test_two,test_three, 如不新建,可能提示找不到資料庫ERROR 3009 (HY000): java.lang.IllegalArgumentException: Invalid DataSource:0(這個提示不夠友好,是在執行很長一段時間後才提示);

新增 MYCAT_HOME 環境變數指向解壓的mycat目錄,主要是為了一些bin目錄下的指令碼的使用。

Contact

  • 作者:鵬磊
  • 出處:www.ymq.io/2017/11/15/…
  • Email:admin@souyunku.com
  • 版權歸作者所有,轉載請註明出處
  • Wechat:關注公眾號,”搜雲庫”,專注於開發技術的研究與知識分享
關注公眾號-搜雲庫
搜雲庫

相關文章