引言:
最近因為時間緣故,學校,比賽,面試很久沒有更新了,現在開始將會持續更新!!!歐克。我們往下看:
概述:
????????主從復制是指將主數據庫的DDL和DML操作通過二進制日志傳到從庫服務器中,然后在從庫上對這些日志重新執行(也叫重做),從而使得從庫和主庫的數據保持同步。 MySQL支持一臺主庫同時向多臺從庫進行復制,從庫同時也可以作為其他從服務器的主庫,實現鏈狀復制。
好處是 :
-
主庫出現問題,從庫可以快速提供服務
-
降低主庫的壓力,實習讀寫分離,
-
可以在從庫中去備份文件,避免備份期間影響主庫服務 (數據之間存在延遲) ?
缺點:
? ? ?1. 數據一致性問題 。從庫數據同步存在延遲,無法保證實時一致性
? ? ?2. 單點故障問題,雖然從庫可以接管,但主庫宕機期間無法寫入的
? ? ?3. 資源消耗啊,配置和維護復雜性等...
原理:
? ? ? ? 其實之間的數據一致性主要是靠的日志文件中的二進制日志文件 -> Binlog 日志文件,主庫對數據的增刪改(DDL) 和 對表庫結構的更改(DML) 都會記錄到這個二進制日志文件中去,然后從庫有兩組線程,一組IOthread 線程 一組SQLthread 線程,當配置好用戶權限后,IOthread線程會發送一個請求來連接指定的主庫,對取主庫中的Binlog 日志文件的內容,然后寫到自己的一個Relay log (中繼日志)文件中去,然后另一組線程SQLthread 會去讀取這個中繼日志文件的數據變化,然后去執行寫入到自己的數據庫中去就保證了主從復制 !!!
插曲疑問:為什么不直接讀取到binlog 日志的內容修改直接寫到從庫中去呢?還多一個中繼日志
這里的中繼日志 有點緩沖區的味道,而且有著性能優化作用,寫入中繼日志也是順序,直接庫表容易數據IO
小插曲: 主從復制如何推事件的 :?
MySQL實際機制 | 長連接+文件事件監聽 | 低(無輪詢) | 毫秒級 |
????????主從復制依賴于從庫 I/O 線程主動連接主庫并請求 binlog 數據。主庫通過 Binlog Dump 線程響應請求,并在有新數據時立即發送(利用阻塞等待機制實現高效“準推送”),而不是主庫主動推送或持續通知從庫。?
Binlog Dump :?主庫收到從庫的請求后,會為這個特定的從庫連接創建一個專門的?
Binlog Dump
?線程。每個成功連接的從庫在主庫上都有自己的 Binlog Dump 線程。
Binlog Dump 線程讀取主庫上的 binlog 文件。
它檢查從庫請求的 binlog 文件名和位置:
如果請求的位置在當前的 binlog 文件內,則從這個位置開始讀取后續事件。
如果請求的位置在更早的 binlog 文件(主庫可能已經進行了 binlog 輪轉,舊的 binlog 文件可能已被刪除或歸檔),Binlog Dump 線程會嘗試找到最早可用的 binlog 文件開頭,或者報錯(如果文件不可用)。
如圖:
從上圖來看,復制分成三步:
-
Master主庫在事務提交時,會把數據變更記錄在二進制日志文件Binlog中。
-
從庫讀取主庫的二進制日志文件 Binlog,寫入到從庫的中繼日志 Relay Log。
-
slave重做中繼日志中的事件,將改變反映它自己的數據。
搭建:
這里我就直接使用了虛擬機通過Docker 來創建2個容器來模擬主從庫,其效果也是一致的 !!!
1. 拉取MySQL鏡像
docker pull mysql:8.0
?
2. 創建網絡(這里方便讓容器可以互相通信,后續主庫連接使用)
docker network create mysql-replication-net
3. 啟動主服務器(Master)
docker run -d --name mysql-master \--network mysql-replication-net \-e MYSQL_ROOT_PASSWORD=rootpassword \-p 3306:3306 \-v mysql-master-data:/var/lib/mysql \mysql:8.0 \--server-id=1 \--log-bin=mysql-bin \--binlog-format=ROW \--character-set-server=utf8mb4 \--collation-server=utf8mb4_unicode_ci
參數:
--name mysql-master? ? ?為容器指定名稱?
mysql-master
,便于后續管理--network mysql-replication-net?
?--server-id=1 指定集群服務下 的 id 為1 從庫不能重復?
?--read-only=0? ?這里沒有指定,默認就是0表示讀寫 1 表示只讀
--log-bin=mysql-bin 這里顯示啟用二進制日志,指定日志文件的前綴為mysql-bin ,MySQL 8.0 默認就開啟了
--binlog-format=ROW 這里指定二進制日志文件記錄方式為 ROW 模式 (默認也就是ROW)
如圖創建并且啟動一個主庫:
??4. 配置主服務器
????????4.1: 接入主服務器容器:
docker exec -it mysql-master mysql -uroot -prootpassword
? ? ? ? 4.2 : 創建遠程連接賬號,并授予主從復制權限:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
注: 這里我測試環境,同時指定插件為mysql_native_password,避免 MySQL 8.0 默認的?caching_sha2_password
?導致的從庫連接問題(無需額外配置 SSL)。
4.3 :查看二進制日志的坐標
SHOW MASTER STATUS;
這里記住二進制日志文件,還有行數,后續便于從庫定位,決定從哪里開始復制!!!?
5. 啟動從服務器(Slave)
docker run -d --name mysql-slave \
--network mysql-replication-net \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-p 3307:3306 \
-v mysql-slave-data:/var/lib/mysql \
mysql:8.0 \
--server-id=2 \
--log-bin=mysql-bin \
--binlog-format=ROW \
--relay-log=mysql-relay-bin \
--log-slave-updates=1 \
--read-only=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
?如圖:
參數:
這里的 --read-only =1 表示當前的庫只是只讀,同時指定--server-id = 2 表示當前的服務id 不要重復即可!
6. 配置從服務器
6.1進入從服務器容器:
docker exec -it mysql-slave mysql -uroot -prootpassword
6.2 執行sql語句 (來連接主庫)
這里的參數要和上面的一致
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='replpassword',
MASTER_LOG_FILE='mysql-bin.000006',
MASTER_LOG_POS= 544;
?-- 檢查從服務器狀態
7. 開始測試:?
首先我們從庫主庫開始都只有系統表如下:
我們開始操作主庫:?
創建一個hz_mn庫, 同時在里面創建一個學生表,student 表,然后插入一些數據即可
如下:
CREATE DATABASE IF NOT EXISTS hz_mn;USE hz_mn;CREATE TABLE IF NOT EXISTS student (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(255),age INT
);INSERT INTO student(name, age) VALUES('hz', 19);SELECT * FROM student;
如圖:?
docker exec -it mysql-master mysql -uroot -prootpassword
然后去查看從庫:
docker exec -it mysql-slave mysql -uroot -prootpassword
可以看到 從庫 已經同步成功了,也出現了相應的庫hz_mn 和表 student,查詢student表的情況:
select? * from student;
歐克,沒有問題,我們主從復制也就搭建完成了? !!!?
總結:
????????主從復制是MySQL高可用架構的基礎,理解其原理并掌握搭建方法對于數據庫管理員至關重要。通過合理配置,可以實現讀寫分離、負載均衡、數據備份等多種應用場景。
歐克,我們下次再見