Cobar 是阿里巴巴開源的 Java 開發 MySQL 分布式中間件,支持透明分片、讀寫分離、高可用,協議兼容 MySQL,應用無感遷移。本文記錄從單機部署到集群高可用、多種分片算法配置的完整實踐過程。
my.cnf,啟動腳本 init_start.sh 批量初始化啟動。<schema name="lyw" dataNode="dnG">
<table name="h1" dataNode="dn0,dn1,dn2,dn3" rule="ruleLong" />
</schema>
<dataNode name="dn0">
<property name="dataSource"><dataSourceRef>ds[0]</dataSourceRef></property>
</dataNode>
... dn1-dn3 類似,dnG 映射 ds[8] ...
<dataSource name="ds" type="mysql">
<property name="location">
<location>192.168.1.8:14011/lyw</location> ... 9個location ...
</property>
<property name="user">lyw</property>
<property name="password">123456</property>
<property name="sqlMode">STRICT_TRANS_TABLES</property>
</dataSource>
schema.dataNode:默認節點 (非分片表落地處)。table.dataNode:分片表映射的物理節點集合。table.rule:路由規則名,定義於 rule.xml。<tableRule name="ruleLong">
<rule>
<columns>id</columns>
<algorithm>funcLong(${id})</algorithm>
</rule>
</tableRule>
<function name="funcLong" class="com.alibaba.cobar.route.function.PartitionByLong">
<property name="partitionCount">4</property>
<property name="partitionLength">256</property>
</function>
鐵律:partitionCount * partitionLength = 1024,否則啟動失敗。所有 function 定義必須在 tableRule 之後。
<user name="lyw">
<property name="password">123456</property>
<property name="schemas">lyw</property>
</user>
<cluster>
<node name="cobar1"><property name="host">192.168.1.8</property><property name="weight">1</property></node>
<node name="cobar2"><property name="host">192.168.1.9</property><property name="weight">1</property></node>
<node name="cobar3"><property name="host">192.168.1.10</property><property name="weight">1</property></node>
</cluster>
$ bin/startup.sh
$ jps | grep CobarStartup
$ netstat -nlp | grep java
# 8066: 數據端口 9066: 管理端口
連接測試:
mysql -ulyw -p123456 -h127.0.0.1 -P8066
CREATE TABLE h1 (id INT PRIMARY KEY, v VARCHAR(32));
INSERT INTO h1 (id, v) VALUES (1,'aa'), (2,'bb'), (256,'cc'), (600,'dd'), (900,'ee'), (1000,'ff');
-- 必須顯式寫列名,否則會向所有分片插入重複數據
SELECT * FROM h1 WHERE id = 256; → 單庫查詢 (dn1),極快。SELECT * FROM h1 WHERE id IN (256, 900, 901); → 計算路由,拆分為兩條 SQL 並發查 dn1、dn3,合併返回。EXPLAIN SELECT ... 可查看 Cobar 拆分計劃,不執行實際查詢。BEGIN 報錯。業務改用單語句原子操作 (如 UPDATE t SET a=a+1 WHERE id=2)。LIMIT 1 會從每個分片取 1 行合併返回 4 行。設計表結構時盡量讓高頻查詢落在單分片。<function name="funcString" class="...PartitionByString">
<property name="partitionCount">4</property>
<property name="partitionLength">256</property>
<property name="hashSlice">:12</property> <!-- 取前 12 字符 hash,負數表取後 N 字符 -->
</function>
<function name="funcFileMap" class="...PartitionByFileMap">
<property name="fileMapPath">/home/lyw/file_map.txt</property>
<property name="defaultNode">0</property>
</function>
映射文件格式 key=nodeIndex (如 beijing=0)。精確匹配,非前綴,未命中走 defaultNode。
<function name="func2D" class="...Dimension2PartitionFunction">
<property name="keyTypeX">string</property> <property name="partitionCountX">2</property> <property name="partitionLengthX">512</property> <property name="hashSliceX">:12</property>
<property name="keyTypeY">long</property> <property name="partitionCountY">2</property> <property name="partitionLengthY">512</property>
</function>
需配置三條規則:雙鍵、單鍵 X、單鍵 Y,否則單維查詢會全表掃描。規模通常 8×8=64 節點以上才有價值。
# 管理端口 9066
mysql -ulyw -p123456 -h127.0.0.1 -P9066
reload @@config; # 熱加載 schema.xml/rule.xml (server.xml system 部分需重啟)
rollback @@config; # 回滾一次
show @@heartbeat; # 查看後端 MySQL 與 Cobar 集群心跳狀態
show @@datanode; # 查看數據節點活躍狀態
switch @@datasource dn0:0; # 手動切換數據源 (僅當前 Cobar 生效,集群不同步,慎用)
<dataNode name="dn0">
<property name="dataSource">
<dataSourceRef>ds[0]</dataSourceRef> <!-- 主 -->
<dataSourceRef>ds[4]</dataSourceRef> <!-- 備 -->
</property>
<property name="heartbeatSQL">SELECT USER()</property> <!-- 建議用寫操作如 UPDATE heartbeat SET ts=NOW() WHERE id=1 -->
</dataNode>
流程:reload @@config → show @@datanode 觀察 INDEX (0=主, 1=備) → Kill 主庫 → 幾秒後 INDEX 自動變 1 → 讀寫自動切換到備庫 → 重啟主庫不會自動切回 (需手動 switch)。
注意:配置變更、故障切換不同步到集群其他 Cobar 節點,需人工保證一致性,存在風險。