通過上一篇幅講解,應該很清楚分片規則配置文件rule.xml
位於$MYCAT_HOME/conf目錄,它定義了全部拆分表的規則。在使用過程當中能夠靈活使用不一樣的分片算法,或者對同一個分片算法使用不一樣的參數,它讓分片過程可配置化,只須要簡單的幾步就可讓運維人員及數據庫管理員輕鬆將數據拆分到不一樣的物理庫中。該文件包含兩個重要的標籤,分別是Funcation和tableRule。java
整體上分爲連續分片和離散分片,還有一種是連續分片和離散分片的結合,例如先範圍後取模。好比範圍分片(id 或者時間)就是典型的連續分片,單個分區的數量和邊界是肯定的。離散分片的分區總數量和邊界是肯定的,例如對 key 進行哈希運算,或者再取模。mysql
關於連續分片在上一篇幅中已經講過,那麼在這一篇幅中就不演示了,在這裏主要寫下怎麼配置及他的特色:算法
特色:容易出現冷熱數據sql
其實這裏面的按月分配和上一篇幅中講的單表中按月分片是同樣的形式,惟一的區別就是一個是單庫一個是多庫;docker
在上一篇幅中的三個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中加入邏輯表vim
在rule.xml中加入分片規則bash
事情搞定那和上一篇幅同樣,啓動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');
根據分片鍵進行十進制求模運算。student表前面已經有講過架構
特色:在插入數據時他會均勻的分佈在全部節點上,解決了上面的冷熱數據問題,可是他在數據遷移和增刪節點時工做量會比較大
枚舉分片適用場景,列值的個數是固定的,譬如省份,月份等。例如:全國 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);
特色:如開頭說的同樣適用於枚舉值固定的場景。
一致性 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節點上。
這是先求模獲得邏輯分片號,再根據邏輯分片號直接映射到物理分片的一種散列算法。
同樣在三個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, '張三');
先進行取模運算再根據求餘結果範圍進行分片,該種分片規則首先根據配置的分片字段,與配置的取模基數進行求餘操做,根據求餘的結果,而後判斷在哪個分片範圍內,由此對應到具體某個數據分片上。
建表數據
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, '張三');
該算法先進行範圍分片,計算出分片組,組內在取模
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, '張三');
1.2.六、其餘分片規則
連續分片優勢:
連續分片缺點:
離散分片優勢:
離散分片缺點:
1、準備工做
2、擴容縮容步驟
下面以取模分片表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 表不會進行數據遷移,格式:
注意:
修改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 便可。
注意事項:
前面已經用 mycat 實現了 MySQL 數據的分片存儲,第一個能夠實現負載均衡,不一樣的讀寫發生在不一樣的節點上。第二能夠實現橫向擴展,若是數據持續增長,加機器就 能夠了。固然,一個分片只有一臺機器還不夠。爲了防止節點宕機或者節點損壞,都要用副本機制來實現。MySQL 數據庫一樣能夠集羣部署,有了多個節點以後,節點之間數據又是個大問題。因此下面說下實現節點數據同步
3、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
vim /etc/mysql/my.cnf文件
[mysqld]下面增長几行配置:
log-bin=mysql-bin binlog-format=ROW server_id=1
配置完成以後,須要重啓mysql服務使配置生效。使用service mysql restart完成重啓。
在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
show master status;
記住file名字和position,後面會用到。這個時候master不要發生寫操做,不然position和file可能會變化。
[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
在 MySQL 多服務器的架構中,主節點,也就是產生數據的節點叫 master 節點。其他的副本,向主節點同步數據的節點,叫作 slave(默認是異步的,客戶端的數據在 master刷盤就返回)。一個集羣裏面至少要有一個 master。slave 能夠有多個。
數據備份:把數據複製到不一樣的機器上,以避免單臺服務器發生故障時數據丟失。負載均衡:結合負載的機制,均攤全部的應用訪問請求,下降單機 IO。高可用 HA:當節點故障時,自動轉移到其餘節點,提升可用性。主從複製的架構能夠有多種
不過在,MySQL 自身並無自動選舉和故障轉移的功能,須要依賴其餘的中間件或者架構實現,好比 MMM,MHA,percona,mycat。下面就來講下主從的實現
客戶端對 MySQL 數據庫進行操做的時候,包括 DDL 和 DML 語句,服務端會在日志文件中用事件的形式記錄全部的操做記錄,這個文件就是 binlog 文件(屬於邏輯日誌,跟 Redis 的 AOF 文件相似)。Binary log,二進制日誌。基於 binlog,咱們能夠實現主從複製和數據恢復。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%';
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
一、主庫開啓 binlog,設置 server-id
二、在主庫建立具備複製權限的用戶,容許從庫鏈接
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.2.106' IDENTIFIED BY 'root'; FLUSH PRIVILEGES;
三、從庫/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 節點)。
四、在從庫執行
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;
五、查看同步狀態
SHOW SLAVE STATUS
Slave_IO_Running 和 Slave SQL Running 都爲 yes 爲正常。
一、slave 服務器執行 start slave,開啓主從複製開關, slave 服務器的 IO 線程請求從 master 服務器讀取 binlog(若是該線程追遇上了主庫,會進入睡眠狀態)。
二、master 服務器建立 Log Dump 線程,把 binlog 發送給 slave 服務器。slave 服務器把讀取到的 binlog 日誌內容寫入中繼日誌 relay log(會記錄位置信息,以便下次繼續讀取)。
三、slave 服務器的 SQL 線程會實時檢測 relay log 中新增的日誌內容,把 relay log 解析成 SQL 語句,並執行。
爲何須要 relay log?爲何不把接收到的 binlog 數據直接寫入從庫? Relay log 至關於一箇中轉站,也記錄了 master 和 slave 的同步信息。
<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:主從切換配置