本文使用 Docker 搭建mysql一主一從的集羣環境 ,帶你一步步揭開mysql主從複製的神祕面紗
關於主從同步的流程圖,參考網上找的一張流程圖:
主從模式的優點
- 負載均衡:通常情況下,會使用 主服務器 對數據進行 更新、刪除 和 新建 等操作,而將 查詢 工作落到 從庫 頭上。
- 異地容災備份:可以將主服務器上的數據同步到 異地從服務器 上,極大地提高了 數據安全性。
- 高可用:數據庫的複製功能實現了 主服務器 與 從服務器間 的數據同步,一旦主服務器出了 故障,從服務器立即擔當起主服務器的角色,保障系統持續穩定運作。
- 高擴展性:主從複製 模式支持 2 種擴展方式:
scale-up
向上擴展或者 縱向擴展,主要是提供比現在服務器 性能更好 的服務器,比如 增加 CPU 和 內存 以及 磁盤陣列等,因爲有多臺服務器,所以可擴展性比單臺更大。
scale-out
向外擴展或者 橫向擴展,是指增加 服務器數量 的擴展,這樣主要能分散各個服務器的壓力。
主從模式的缺點
- 成本增加: 搭建主從肯定會增加成本,畢竟一臺服務器和兩臺服務器的成本完全不同,另外由於主從必須要開啓 二進制日誌,所以也會造成額外的 性能消耗。
- 數據延遲: 從庫 從 主庫 複製數據肯定是會有一定的 數據延遲 的。所以當剛插入就出現查詢的情況,可能查詢不出來。當然如果是插入者自己查詢,那麼可以直接從 主庫 中查詢出來,當然這個也是需要用代碼來控制的。
- 寫入更慢:主從複製 主要是針對 讀遠大於寫 或者對 數據備份實時性 要求較高的系統中。因爲 主服務器在寫中需要更多操作,而且 只有一臺 可以寫入的 主庫,所以寫入的壓力並不能被分散。
主從複製的前提條件
主從服務器 操作系統版本 和 位數 一致。
主數據庫和從數據庫的 版本 要一致。
主數據庫和從數據庫中的 數據 要一致。
主數據庫 開啓 二進制日誌,主數據庫和從數據庫的 server_id 在局域網內必須 唯一。
搭建集羣
本示例使用Mysql 5.7 作爲鏡像,使用docker-compose進行資源編排。
首先先對mysql 的master和slave進行配置,創建如下目錄問價結構
D:/docker/mysql-master-slave
結構樹:
- master
- data
- mysqld.conf
- slave
- data
- mysqld.conf
接着開始配置master目錄底下的mysqld.cnf 文件,內容如下:
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 以下是新增內容
# 標識不同的數據庫服務器,而且唯一
server-id=1
# 啓用二進制日誌
log-bin=mysql-bin
log-slave-updates=1
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
skip-host-cache
skip-name-resolve
slave 目錄底下的mysqld.cnf 內容爲:
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 以下是新增內容
server-id=2
log-bin=mysql-bin
log-slave-updates=1
# 多主的話需要注意這個配置,防止自增序列衝突。
auto_increment_increment=2
auto_increment_offset=2
read-only=1
slave-skip-errors = 1062
skip-host-cache
skip-name-resolve
接着使用docker-compose進行資源編排:
version: '3'
services:
mysql_master:
#構建mysql鏡像
image: mysql:5.7
container_name: mysql_master
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci #設置utf8字符集
restart: always
environment:
MYSQL_ROOT_PASSWORD: "root"
MYSQL_USER: "root"
MYSQL_PASSWORD: "root"
ports:
- '3307:3306'
volumes:
#mysql數據庫掛載到host物理機目錄/d/docker/mysql/data
- D:/docker/mysql-master-slave/master/data:/var/lib/mysql
- D:/docker/mysql-master-slave/master/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
mysql_slave:
#構建mysql鏡像
image: mysql:5.7
container_name: mysql_slave
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci #設置utf8字符集
restart: always
environment:
MYSQL_ROOT_PASSWORD: "root"
MYSQL_USER: "root"
MYSQL_PASSWORD: "root"
ports:
- '3308:3306'
volumes:
- D:/docker/mysql-master-slave/slave/data:/var/lib/mysql
- D:/docker/mysql-master-slave/slave/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
使用命令docker-compose up -d 啓動。
如果沒問題,進入mysql的master配置遠程連接,
docker exec -it mysql_master bash
# 剛開始默認沒密碼
mysql
# 支持root用戶允許遠程連接mysql數據庫
mysql> grant all privileges on *.* to 'root'@'%' identified by 'root';
mysql> flush privileges;
退出mysql:
mysql> exit
接着,使用數據庫連接工具就可以連上了。
下一步就是進入數據庫配置主從配置了,在終端中進入容器:
docker exec -it mysql_master bash
mysql -uroot -p
創建一個同步數據權限的用戶:
GRANT REPLICATION SLAVE ON *.* to 'backup'@'%' identified by 'root';
接着查看狀態,記住File、Position的值,在 Slave 中將用到
show master status;
退出當前容器,進入slave容器
docker exec -it mysql_slave bash
mysql -u root -p
設置主庫鏈接,注意master_log_file和master_log_pos要替換成自己相應的master信息,master_host的host可以通過docker inspect 容器id 獲得IPAddress
change master to master_host='172.17.0.2',master_user='backup',master_password='root',master_log_file='mysql-bin.000003',master_log_pos=439,master_port=3306;
最後啓動從庫同步
start slave
查看下狀態,如果 Slave_SQL_Running_State 是 Slave has read all relay log; waiting for more updates 表示正常運行。
show slave status \G
測試同步,在master上新建一個數據庫
docker exec mysql_master mysql -uroot -p -e "CREATE DATABASE test"
docker exec mysql_slave mysql -uroot -p -e "SHOW DATABASES"
可以看到同步成功了。
主從同步的簡單原理?
答:
MySQL的主從複製是一個異步的複製過程,數據庫從一個Master複製到Slave數據庫,在Master與Slave之間實現整個主從複製的過程是由三個線程參與完成的,其中有兩個線程(SQL線程和IO線程)在Slave端,另一個線程(IO線程)在Master端。
master 數據變化時會產生bin log日誌,slave上的線程拉去bin log,然後在slave上重新執行日誌。這樣就保證了數據一致性。
show slave status 中的Slave_IO_Running和Slave_SQL_Running的含義?
答:Slave 上會同時有兩個線程在工作, I/O 線程從 Master 得到數據(Binary Log 文件),放到被稱爲
Relay Log 文件中進行記錄。另一方面,SQL 線程則將 Relay Log 讀取並執行。
爲什麼要有兩個線程?這是爲了降低同步的延遲。因爲 I/O 線程和 SQL 線程都是相對很耗時的操作。
從服務器同步失敗?
答:看錯誤日誌 tail /var/log/mysql/error.log
重新執行同步
stop slave;
change master to master_log_file=‘mysql-bin.000100,master_log_pos=123’
關於 file 和 pos,需在master上執行show master status獲得。
或者使用 mysqlbinlog 命令分析。
如何添加多個從節點?
和添加第一個從節點類似,先導出master的數據,複製第一個slave配置文件,唯一要改變的是server-id,不能和其他的重複。之後啓動新的容器,進到容器內執行change master to …。
還需要注意當前master沒有寫入等操作,最好先鎖表,同步設置好後在解鎖。參考
參考鏈接:
docker學習系列12 輕鬆實現 mysql 主從同步
https://blog.csdn.net/u012562943/article/details/86589834