MyCat 是基於阿里開源 Cobar 演進的開源數據庫中間件,支援讀寫分離、分庫分表、多租戶、全局序列號等企業級特性,被視為「MySQL 集群」的輕量級替代方案。本文基於 Docker 環境,從零構建 MyCat 1.5 分片集群,詳細記錄核心概念配置、啟動驗證與分表測試全過程。
| 組件 | 版本/規格 |
|---|---|
| OS | Ubuntu 16.04 |
| JDK | 1.8+ |
| Docker | 1.11.2+ |
| MySQL | 5.7.13 (兩個容器實例) |
| MyCat | 1.5-RELEASE |
| 客戶端 | Navicat for MySQL / mysql-client |
# 節點 1 (dn1) - 映射宿主 3306
docker run --name mysql1 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=bboyjing -d daocloud.io/library/mysql:5.7.13
# 節點 2 (dn2) - 映射宿主 3316
docker run --name mysql2 -p 3316:3306 -e MYSQL_ROOT_PASSWORD=bboyjing -d daocloud.io/library/mysql:5.7.13
# 驗證連通性
mysql -h127.0.0.1 -P3306 -uroot -pbboyjing
mysql -h127.0.0.1 -P3316 -uroot -pbboyjing
# 連入各實例執行
CREATE DATABASE order_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
MyCat 配置文件位於 conf/ 目錄,三大核心文件:
server.xml:系統參數、用戶權限、全局屬性。schema.xml:邏輯庫、邏輯表、分片節點、分片規則、節點主機定義。rule.xml:分片算法函數定義 (如取模、範圍、一致性哈希、枚舉等)。| MyCat 概念 | 對應物理含義 | 配置位置 |
|---|---|---|
| 用戶 | 連接 MyCat 的客戶端賬號 | server.xml <user> |
| 邏輯庫 | 對應 MySQL Database | schema.xml <schema> |
| 邏輯表 | 分片後的邏輯視圖 | schema.xml <table> |
| 分片節點 | 具體 MySQL 實例上的物理庫 | schema.xml <dataNode> |
| 分片規則 | 路由算法 (取模、範圍、哈希...) | rule.xml <tableRule> + <function> |
| 節點主機 | MySQL 實例連接池、讀寫分離、心跳 | schema.xml <dataHost> |
| 全局序列號 | 分片環境下全局唯一 ID 生成 | sequence_*.conf / ZK/數據庫方式 |
<user name="root">
<property name="password">bboyjing</property>
<property name="schemas">OrderDB</property>
<!-- property name="readOnly">true</property -->
</user>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="https://io.mycat/">
<!-- 邏輯庫 -->
<schema name="OrderDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- 邏輯表:分片到 dn1,dn2,規則 mod-long -->
<table name="t_order" dataNode="dn1,dn2" rule="mod-long" primaryKey="id" autoIncrement="true"/>
</schema>
<!-- 分片節點:映射到具體 MySQL 實例上的庫 -->
<dataNode name="dn1" dataHost="dockerhost1" database="order_db"/>
<dataNode name="dn2" dataHost="dockerhost2" database="order_db"/>
<!-- 節點主機:定義連接池、心跳、讀寫分離 -->
<dataHost name="dockerhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="bboyjing"/>
</dataHost>
<dataHost name="dockerhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="127.0.0.1:3316" user="root" password="bboyjing"/>
</dataHost>
</mycat:schema>
balance="0":讀寫分離模式。0=不開啟(全走 writeHost),1=所有 readHost+writeHost 負載均衡,2=僅 readHost 負載均衡,3=所有 host 負載均衡 (慎用)。writeType="0":寫負載模式。0=寫第一個 writeHost,故障切換;1=輪詢寫入 (危險,易主主衝突)。switchType="1":心跳檢測類型。1=不自動切換 (推薦),2=基於 MySQL 主從狀態自動切換,3=管理員決定。<tableRule name="mod-long">
<rule>
<columns>id</columns> <!-- 分片鍵 -->
<algorithm>mod-long</algorithm> <!-- 算法引用 -->
</rule>
</tableRule>
<function name="mod-long" class="org.opencloudb.route.function.PartitionByMod">
<property name="count">2</property> <!-- 分片數量,與 dataNode 數量一致 -->
</function>
算法含義: id % 2,結果 0 路由至 dn1,1 路由至 dn2。MyCat 內建豐富算法:PartitionByMod(取模)、PartitionByRange(範圍)、PartitionByDate(日期)、PartitionByPattern(正則)、PartitionByCRC32PreSlot(一致性哈希) 等。
cd /opt/mycat
bin/mycat start
# 查看日誌確認啟動成功
tail -f logs/mycat.log
# 關鍵日誌: "connected successfully MySQLConnection" 表示後端 MySQL 連接池建立正常
MyCat 預設端口:8066 (數據端口)、9066 (管理端口)。
mysql -h127.0.0.1 -P8066 -uroot -pbboyjing
mysql> SHOW DATABASES;
+----------+
| DATABASE |
+----------+
| OrderDB | <-- 來自 server.xml 用戶 schemas 屬性
+----------+
mysql> USE OrderDB;
mysql> CREATE TABLE `t_order` (
-> `id` INT(11) NOT NULL,
-> `status` TINYINT(4) NOT NULL,
-> `price` INT(11) NOT NULL,
-> `create_time` BIGINT(20) NOT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.05 sec)


登入兩個後端 MySQL 實例,檢查表結構自動建立:
# MySQL1 (3306)
mysql> USE order_db; SHOW TABLES; DESC t_order;
# MySQL2 (3316)
mysql> USE order_db; SHOW TABLES; DESC t_order;
兩側均自動建立相同結構的 t_order 表,證明 MyCat 成功攔截 DDL 並路由至所有分片節點。
# 通過 MyCat 插入測試數據
INSERT INTO t_order (id, status, price, create_time) VALUES (1, 1, 100, 1234567890);
INSERT INTO t_order (id, status, price, create_time) VALUES (2, 2, 200, 1234567891);
INSERT INTO t_order (id, status, price, create_time) VALUES (3, 1, 150, 1234567892);
INSERT INTO t_order (id, status, price, create_time) VALUES (4, 3, 300, 1234567893);
# 驗證路由: id%2=1 -> dn1 (mysql1), id%2=0 -> dn2 (mysql2)
# MySQL1 應有 id=1,3
# MySQL2 應有 id=2,4
sequence_conf.properties 使用 LOCAL、DATABASE (需建 sequence 表)、ZK、SNOWFLAKE (雪花算法) 等方式生成全局唯一 ID。ER 關係表 (childTable) 將關聯表路由至同一分片,或應用層組裝。balance=1/2/3 可能導致主從延遲下讀到舊數據。核心寫入路徑建議 balance=0,讀請求顯式路由至從庫或使用中間件代理層 (如 ProxySQL) 實現更精細控制。SHOW @@datasource、SHOW @@cache、RELOAD @@config 等運行時指令,納入監控體系。MyCat 作為一款成熟的數據庫中間件,以 **「對應用透明、SQL 改造最小、運維成本可控」** 解決了 MySQL 單庫性能與存儲瓶頸。本文實戰驗證了核心配置鏈路:
用戶 → 邏輯庫 → 邏輯表(分片規則) → 分片節點 → 節點主機(物理 MySQL)
落地關鍵在於:
dataNode 映射與 dataHost 連接池參數。MyCat 並非銀彈,但對於中小型團隊從單庫向分布式架構演進,是極具性價比的落地選擇。