一、mycat分片規則
經過上一篇幅講解,應該很清楚分片規則配置檔案rule.xml
位於$MYCAT_HOME/conf目錄,它定義了所有拆分表的規則。在使用過程中可以靈活使用不同的分片演算法,或者對同一個分片演算法使用不同的引數,它讓分片過程可配置化,只需要簡單的幾步就可以讓運維人員及資料庫管理員輕鬆將資料拆分到不同的物理庫中。該檔案包含兩個重要的標籤,分別是Funcation和tableRule。
總體上分為連續分片和離散分片,還有一種是連續分片和離散分片的結合,例如先範圍後取模。比如範圍分片(id 或者時間)就是典型的連續分片,單個分割槽的數量和邊界是確定的。離散分片的分割槽總數量和邊界是確定的,例如對 key 進行雜湊運算,或者再取模。
1.1、連續分片
1.1.1、範圍分片
關於連續分片在上一篇幅中已經講過,那麼在這一篇幅中就不演示了,在這裡主要寫下怎麼配置及他的特點:
特點:容易出現冷熱資料
1.1.2、按月分片
其實這裡面的按月分配和上一篇幅中講的單表中按月分片是一樣的形式,唯一的區別就是一個是單庫一個是多庫;
在上一篇幅中的三個ghymycat庫中接著建立三張表
-- 建立表 CREATE TABLE `month` ( `create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在schema.xml中加入邏輯表
在rule.xml中加入分片規則
事情搞定那和上一篇幅一樣,啟動mycat服務然後測試
INSERT INTO month (create_time,name) VALUES ('2024-10-16', '11'); INSERT INTO month (create_time,name) VALUES ('2025-10-27', '11'); INSERT INTO month (create_time,name) VALUES ('2026-11-04', '11'); INSERT INTO month (create_time,name) VALUES ('2027-11-11', '11'); INSERT INTO month (create_time,name) VALUES ('2029-12-25', '11'); INSERT INTO month (create_time,name) VALUES ('2030-12-31', '11');
1.2、離散分片
1.2.1、十進位制取模分片
根據分片鍵進行十進位制求模運算。student表前面已經有講過
特點:在插入資料時他會均勻的分佈在所有節點上,解決了上面的冷熱資料問題,但是他在資料遷移和增刪節點時工作量會比較大
1.2.2、列舉分片
列舉分片適用場景,列值的個數是固定的,譬如省份,月份等。例如:全國 34 個省,要將不同的省的資料存放在不同的節點,可用列舉的方式。
和前面樣,在三個ghymycat庫中建立表
CREATE TABLE `t_vote` ( `age` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然後建立邏輯表
建立分片規則
最後建立分片演算法
策略檔案
測試資料
INSERT INTO `sharding_by_intfile` (age,name) VALUES (16, 11); INSERT INTO `sharding_by_intfile` (age,name) VALUES (17, 11); INSERT INTO `sharding_by_intfile` (age,name) VALUES (18, 11);
特點:如開頭說的一樣適用於列舉值固定的場景。
1.2.3、一致性雜湊
一致性 hash 有效解決了分散式資料的擴容問題。
原理:為將資料均勻分佈在各個節點中。對其進行雜湊,取值在 0 ~ 232-1 閉環中定位到順時針第一個節點,將此資料分配其中。由於節點有限,可能取雜湊分佈不均。設定虛擬節點比如160,先將雜湊分佈在160節點上,然後把對應的節點聚合到真實節點中。
在三個資料庫ghymycat中建表
CREATE TABLE `consistency` ( `id` int(10) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
邏輯表
分片規則
分片演算法
INSERT INTO `consistency` (id,name) VALUES (1, '張三'); INSERT INTO `consistency` (id,name) VALUES (2, '張三'); INSERT INTO `consistency` (id,name) VALUES (3, '張三'); INSERT INTO `consistency` (id,name) VALUES (4, '張三'); INSERT INTO `consistency` (id,name) VALUES (5, '張三'); INSERT INTO `consistency` (id,name) VALUES (6, '張三'); INSERT INTO `consistency` (id,name) VALUES (7, '張三'); INSERT INTO `consistency` (id,name) VALUES (8, '張三'); INSERT INTO `consistency` (id,name) VALUES (9, '張三'); INSERT INTO `consistency` (id,name) VALUES (10, '張三'); INSERT INTO `consistency` (id,name) VALUES (11, '張三'); INSERT INTO `consistency` (id,name) VALUES (12, '張三'); INSERT INTO `consistency` (id,name) VALUES (13, '張三'); INSERT INTO `consistency` (id,name) VALUES (14, '張三'); INSERT INTO `consistency` (id,name) VALUES (15, '張三'); INSERT INTO `consistency` (id,name) VALUES (16, '張三'); INSERT INTO `consistency` (id,name) VALUES (17, '張三'); INSERT INTO `consistency` (id,name) VALUES (18, '張三'); INSERT INTO `consistency` (id,name) VALUES (19, '張三'); INSERT INTO `consistency` (id,name) VALUES (20, '張三');
特點:可以一定程度減少資料的遷移可以解決容災,擴容。例如真實節點3個,比如:a,b,c;b當機,原來要分配到b節點上的會分配到c上;加節點x到ac中間,原來分配到c節點的資料分配到x節點上。
1.2.4、固定分片雜湊
這是先求模得到邏輯分片號,再根據邏輯分片號直接對映到物理分片的一種雜湊演算法。
一樣在三個ghymycat中建立表
CREATE TABLE `immobilization` ( `id` int(10) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
邏輯表
分片規則
平均分成 8 片(%1024 的餘數,1024=128*8):
這是均勻分佈的例子,下面再配置一個不均勻分佈的例子,只用 改動分片演算法(%1024 的餘數,1024=2*256+1*512)
INSERT INTO `immobilization` (id,name) VALUES (222, '張三'); INSERT INTO `immobilization` (id,name) VALUES (333, '張三'); INSERT INTO `immobilization` (id,name) VALUES (666, '張三');
-
- 優點:這種策略比較靈活,可以均勻分配也可以非均勻分配,各節點的分配比例和容量大小由partitionCount 和 partitionLength兩個引數決定
- 缺點:和取模分片類似。
1.2.5、取模範圍分片
先進行取模運算再根據求餘結果範圍進行分片,該種分片規則首先根據配置的分片欄位,與配置的取模基數進行求餘操作,根據求餘的結果,然後判斷在哪一個分片範圍內,由此對應到具體某個資料分片上。
建表資料
CREATE TABLE `delivery` ( `id` varchar(20) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
邏輯表
分片規則
分片演算法
INSERT INTO `delivery` (id,name) VALUES (19, '張三'); INSERT INTO `delivery` (id,name) VALUES (222, '張三'); INSERT INTO `delivery` (id,name) VALUES (371, '張三');
-
- 優點:可以自由地決定取模後資料的節點分佈
- 缺點:dataNode 劃分節點是事先建好的,擴充套件比較麻煩。
1.2.6、範圍取模分片
該演算法先進行範圍分片,計算出分片組,組內在取模
CREATE TABLE `delivery_mod` ( `id` varchar(20) DEFAULT NULL, `name` varchar(20) DEFAULT NULL ) ;
邏輯表
分片規則
分片演算法
INSERT INTO `delivery_mod` (id,name) VALUES (666, '張三'); INSERT INTO `delivery_mod` (id,name) VALUES (6667, '張三'); INSERT INTO `delivery_mod` (id,name) VALUES (16666, '張三'); INSERT INTO `delivery_mod` (id,name) VALUES (21111, '張三'); INSERT INTO `delivery_mod` (id,name) VALUES (22222, '張三');
- 優點:綜合了範圍分片和取模分片的優點,分片組內使用取模可以保證組內的資料分佈比較均勻,分片組之間採用範圍分片可以兼顧範圍分片的特點,事先規劃好分片的數量,資料擴容時按照分片組擴容,則原有分片組的資料不需要遷移,分片組內還可以避免熱點資料問題。
- 缺點:在資料範圍時固定值(非遞增值)時,存在不方便擴充套件的情況,例如將 dataNode Group size 從 2 擴充套件為 4 時,需要進行資料遷移才能完成
1.2.6、其他分片規則
- 應用指定分片 PartitionDirectBySubString
- 日期範圍雜湊 PartitionByRangeDateHash
- 冷熱資料分片 PartitionByHotDate
- 也可以自定義分片規則: extends AbstractPartitionAlgorithm implements RuleAlgorithm。
1.3、連續分片和離散分片的特點
連續分片優點:
- 範圍條件查詢消耗資源少(不需要彙總資料)
- 擴容無需遷移資料(分片固定)
連續分片缺點:
- 存在資料熱點的可能性
- 併發訪問能力受限於單一或少量 DataNode(訪問集中)
離散分片優點:
- 併發訪問能力增強(負載到不同的節點)
- 範圍條件查詢效能提升(平行計算)
離散分片缺點:
- 資料擴容比較困難,涉及到資料遷移問題
- 資料庫連線消耗比較多
1.4、切分規則的選擇
- 找到需要切分的大表,和關聯的表
- 確定分片欄位(儘量使用主鍵),一般用最頻繁使用的查詢條件
- 考慮單個分片的儲存容量和請求、資料增長(業務特性)、擴容和資料遷移問題。例如:按照什麼遞增?序號還是日期?主鍵是否有業務意義?一般來說,分片數要比當前規劃的節點數要大。
二、 Mycat 擴縮容
一、準備工作
- mycat 所在環境安裝 mysql 客戶端程式
- mycat 的 lib 目錄下新增 mysql 的 jdbc 驅動包(我這裡下的是mysql-connector-java-5.1.27.jar)
- 對擴容縮容的表所有節點資料進行備份,以便遷移失敗後的資料恢復
二、擴容縮容步驟
下面以取模分片表student為例
複製 schema.xml、rule.xml 並重新命名為 newSchema.xml、newRule.xml 放於 conf 目錄下
修改 newSchema.xml 和 newRule.xml 配置檔案為擴容縮容後的 mycat 配置引數(表的節點數、資料來源、路由規則)注意:只有節點變化的表才會進行遷移。僅分片配置變化不會遷移。
修改newSchema.xml配置
因為節點數發生了變化所以newRule.xml配置中的count節點數也需要修改成2
修改 conf 目錄下的 migrateTables.properties 配置檔案,告訴工具哪些表需要進行擴容或縮容,沒有出現在此配置檔案的 schema 表不會進行資料遷移,格式:
注意:
- 不遷移的表,不要修改 dn 個數,否則會報錯。
- ER 表,因為只有主表有分片規則,子表不會遷移。
修改bin目錄下的dataMigrate.sh指令碼檔案,引數如下:
tempFileDir 臨時檔案路徑,目錄不存在將自動建立 isAwaysUseMaster預設true:不論是否發生主備切換,都使用主資料來源資料,false:使用當前資料來源 mysqlBin:mysql bin路徑 cmdLength mysqldump命令列長度限制 預設110k 110*1024。在LINUX作業系統有限制單條命令列的長度是128KB,也就是131072位元組,這個值可能不同作業系統不同核心都不一樣,如果執行遷移時報Cannot run program "sh": error=7, Argument list too long 說明這個值設定大了,需要調小此值。 charset匯入匯出資料所用字符集 預設utf8 deleteTempFileDir完成擴容縮容後是否刪除臨時檔案 預設為true threadCount並行執行緒數(涉及生成中間檔案和匯入匯出資料)預設為遷移程式所在主機環境的cpu核數*2 delThreadCount每個資料庫主機上清理冗餘資料的併發執行緒數,預設為當前指令碼程式所在主機cpu核數/2 queryPageSize 讀取遷移節點全部資料時一次載入的資料量 預設10w條
指定臨時檔案路徑 #臨時檔案路徑,目錄不存在將自動建立,不指定此目錄則預設為mycat根下的temp目錄 RUN_CMD="$RUN_CMD -tempFileDir=/root/data/program/mycat/temp" 指定為false可以檢視此過程中產生的sql #完成擴容縮容後是否刪除臨時檔案 預設為true RUN_CMD="$RUN_CMD -deleteTempFileDir=false"
通過命令"find / -name mysqldump"查詢mysqldump路徑為"/usr/bin/mysqldump",指定#mysql bin路徑為"/usr/bin/"
#mysql bin路徑 RUN_CMD="$RUN_CMD -mysqlBin=/usr/bin/" 這個一定得配置
停止mycat服務(如果可以確保擴容縮容過程中不會有寫操作,也可以不停止mycat服務)
通過crt等工具進入mycat根目錄,執行bin/ dataMigrate.sh指令碼,開始擴容/縮容過程:
指令碼執行完成,如果最後的資料遷移驗證通過,就可以將之前的 newSchema.xml和 newRule.xml 替換之前的 schema.xml 和 rule.xml 檔案,並重啟 mycat 即可。
注意事項:
- 保證分片表遷移資料前後路由規則一致(取模——取模)。
- 保證分片表遷移資料前後分片欄位一致。
- 全域性表將被忽略。
- 不要將非分片表配置到 migrateTables.properties 檔案中。
- 暫時只支援分片表使用 MySQL 作為資料來源的擴容縮容。migrate 限制比較多,還可以使用 mysqldump。
前面已經用 mycat 實現了 MySQL 資料的分片儲存,第一個可以實現負載均衡,不同的讀寫發生在不同的節點上。第二可以實現橫向擴充套件,如果資料持續增加,加機器就 可以了。當然,一個分片只有一臺機器還不夠。為了防止節點當機或者節點損壞,都要用副本機制來實現。MySQL 資料庫同樣可以叢集部署,有了多個節點之後,節點之間資料又是個大問題。所以下面說下實現節點資料同步
三、MySQL 主從複製
主從同步原理:
準備兩臺機器
master 192.168.2.103
slave 192.168.2.106
因為我是在docker中建的mysql容器,所以想要進入mysql內部要執行下面命令
docker exec -it e1066fe2db35 /bin/bash
如果沒裝vim的要先裝下vim,執行命令:apt-get install vim
這時候需要執行命令:apt-get update
這個命令的作用是:同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,這樣才能獲取到最新的軟體包。
重新執行命令:apt-get install vim
安裝完成。
如果用clone的方式得到兩個MySQL服務,需要注意的地方:不同機器的UUID不能重複,否則IO執行緒不能啟動:
find / -name auto.cnf vim /var/lib/mysql/auto.cnf
把裡面的UUID隨便改掉一位。
重啟服務命令:
service mysqld restart
103主節點配置
配置檔案開啟binlog
vim /etc/mysql/my.cnf檔案
[mysqld]下面增加幾行配置:
log-bin=mysql-bin binlog-format=ROW server_id=1
配置完成之後,需要重啟mysql服務使配置生效。使用service mysql restart完成重啟。
建立給slave使用的使用者
在103主節點建立給slave 106節點訪問的使用者(發放通行證)
連線到MySQL:
mysql -uroot -proot;
執行SQL:
CREATE USER 'repl'@'192.168.2.106' IDENTIFIED BY 'root'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.2.106'; FLUSH PRIVILEGES;
如果有多個slave節點,使用同一個使用者,也可以把IP設定成萬用字元的方式,例如192.168.2.*
獲取binlog名字和position
接下來要獲取最新的binlog檔名和position
show master status;
記住file名字和position,後面會用到。這個時候master不要發生寫操作,否則position和file可能會變化。
slave節點配置
配置檔案
[mysqld]下面增加幾行配置:
log-bin=mysql-slave-bin binlog-format=ROW server_id=2
配置完成之後,需要重啟mysql服務使配置生效。使用service mysql restart完成重啟。
開啟主從同步
連線到MySQL:
mysql -uroot -proot;
file和pos是從主節點獲取的
change master to master_host='192.168.2.103', master_user='repl', master_password='root', master_log_file='mysql-bin.000028', master_log_pos=773;
檢視從節點狀態
show slave status;
注意,主從同步成功的標誌:
IO執行緒和SQL執行緒都是成功執行的:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
現在可以在master節點上面做任意對於庫表的修改操作,slave會自動同步。
不要直接操作slave。
如果IO執行緒not running:
stop slave; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; start slave; show slave status\G
3.1、主從複製的含義
在 MySQL 多伺服器的架構中,主節點,也就是產生資料的節點叫 master 節點。其他的副本,向主節點同步資料的節點,叫做 slave(預設是非同步的,客戶端的資料在 master刷盤就返回)。一個叢集裡面至少要有一個 master。slave 可以有多個。
3.2、主從複製的用途
資料備份:把資料複製到不同的機器上,以免單臺伺服器發生故障時資料丟失。負載均衡:結合負載的機制,均攤所有的應用訪問請求,降低單機 IO。高可用 HA:當節點故障時,自動轉移到其他節點,提高可用性。主從複製的架構可以有多種
3.3、主從複製的形式
- 一主一從/一主多從
- 雙主複製(互為主從)
- 級聯複製
不過在,MySQL 自身並沒有自動選舉和故障轉移的功能,需要依賴其他的中介軟體或者架構實現,比如 MMM,MHA,percona,mycat。下面就來說下主從的實現
3.4、binlog
客戶端對 MySQL 資料庫進行操作的時候,包括 DDL 和 DML 語句,服務端會在日志檔案中用事件的形式記錄所有的操作記錄,這個檔案就是 binlog 檔案(屬於邏輯日誌,跟 Redis 的 AOF 檔案類似)。Binary log,二進位制日誌。基於 binlog,我們可以實現主從複製和資料恢復。binlog 預設是不開啟的,需要在服務端手動配置。注意有一定的效能損耗。
3.4.1、 binlog 配置
編輯 /etc/my.cnf
log-bin=mysql-bin server-id=1
重啟 MySQL 服務
service mysqld stop service mysqld start ##如果出錯檢視日誌
vi /var/log/mysqld.log
cd /var/lib/mysql
是否開啟 binlog
show variables like 'log_bin%';
3.4.2 、binlog 格式
STATEMENT:記錄每一條修改資料的 SQL 語句(減少日誌量,節約 IO)。
ROW:記錄哪條資料被修改了,修改成什麼樣子了(5.7 以後預設)。
MIXED:結合兩種方式,一般的語句用 STATEMENT,函式之類的用
ROW。檢視 binlog 格式:
show global variables like '%binlog_format%';
Binlog 檔案超過一定大小就會產生一個新的,檢視 binlog 列表:
show binary logs;
大小:
show variables like 'max_binlog_size';
檢視 binlog 內容
show binlog events in 'mysql-bin.000001';
用 mysqlbinlog 工具,基於時間檢視 binlog
/usr/bin/mysqlbinlog --start-datetime='2025-08-22 13:30:00' --stop-datetime='2025-08-22 14:01:01' -d ljxmycat /var/lib/mysql/mysql-bin.000001
3.5主從複製原理
3.5.1 主從複製配置
1、主庫開啟 binlog,設定 server-id
2、在主庫建立具有複製許可權的使用者,允許從庫連線
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.2.106' IDENTIFIED BY 'root'; FLUSH PRIVILEGES;
3、從庫/etc/my.cnf 配置,重啟資料庫
server-id=2 log-bin=mysql-bin relay-log=mysql-relay-bin read-only=1 log-slave-updates=1
開啟 log-slave-updates 引數後,從庫從主庫複製的資料會寫入 log-bin 日誌檔案裡,這樣可以實現互為主備或者級聯複製(它自己也可以作為一個 master 節點)。
4、在從庫執行
stop slave; change master to master_host='192.168.2.103',master_user='repl',master_password='root',master_log_file='mysql-bin.00000 1', master_log_pos=4; start slave;
5、檢視同步狀態
SHOW SLAVE STATUS
Slave_IO_Running 和 Slave SQL Running 都為 yes 為正常。
3.5.2 主從複製原理
1、slave 伺服器執行 start slave,開啟主從複製開關, slave 伺服器的 IO 執行緒請求從 master 伺服器讀取 binlog(如果該執行緒追趕上了主庫,會進入睡眠狀態)。
2、master 伺服器建立 Log Dump 執行緒,把 binlog 傳送給 slave 伺服器。slave 伺服器把讀取到的 binlog 日誌內容寫入中繼日誌 relay log(會記錄位置資訊,以便下次繼續讀取)。
3、slave 伺服器的 SQL 執行緒會實時檢測 relay log 中新增的日誌內容,把 relay log 解析成 SQL 語句,並執行。
為什麼需要 relay log?為什麼不把接收到的 binlog 資料直接寫入從庫? Relay log 相當於一箇中轉站,也記錄了 master 和 slave 的同步資訊。
3.5.3 mycat 讀寫分離的實現
<dataHost name="host122" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="192.168.2.103:3306" user="root" password="root"> <readHost host="hostS1" url="192.168.2.104:3306" user="root" password="root" /> </writeHost> </dataHost>
balance:負載的配置,決定 select 語句的負載
writeType:讀寫分離的配置,決定 update、delete、insert 語句的負載
switchType:主從切換配置