Intro
主從備份是容災的一種手段, 模擬主從備份可以有下面幾種方式:
- 不差錢方式, 買幾臺主機測試, 這種方式也比較接近線上環境.
- 通過創建幾臺虛擬機來模擬. 這種方式對本機性能要求相對較高. 相對不差錢可以選這種方式, 但安裝幾臺虛擬機也不是一件效率高的事.
- 在一臺主機上創建多個數據庫實例. 缺點是環境無法隔離, 需要額外加多一些配置
- 通過 Docker-compose 直接創建多個數據庫容器, 暴露端口訪問即可.
binlog
是MySQL數據庫的二進制日誌,用於記錄用戶對數據庫操作的SQL語句(不包括 SELECT
),可以在配置文件開啓,也可以在 MySQL 客戶端開啓. 可以在客戶端鍵入show plugins;
查看 binlog
是否已安裝開啓( Active )
+----------------------------+----------+--------------------+---------+---------+
| Name | Status | Type | Library | License |
+----------------------------+----------+--------------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
環境準備
0.1 測試環境
必須安裝有 docker
及 docker-compose
用於構建容器環境, 本測試在 Ubuntu 16.04 及下列版本下進行, 使用其他版本可能會有使用差異.
docker-compose 1.25.4
docker 19.03.6
有關安裝的細節, 請搜索相關關鍵詞, 或者直接根據 Docker 官方文檔 進行安裝
0.2 Docker 加速
由於衆所周知的原因, 拉取鏡像時可能會很慢, 推薦設置國內的鏡像源進行加速
在 Ubuntu/Centos/Debian
下修改或創建此文件 /etc/docker/daemon.json
示例文件內容如下, 可以自由添加鏡像源. 鏡像源有可能會宕機, 鏡像源測試請參閱docker-registry-cn-mirror-test
{
"registry-mirrors":[
"https://dockerhub.azk8s.cn",
"https://docker.mirrors.ustc.edu.cn",
"https://reg-mirror.qiniu.com"
]
}
一. Docker 文件準備
1.1 文件目錄
-
Dockerfile
是一個文本文件, 只需要touch Dockerfile
創建即可. -
docker-compose.yml
是用於運行多個 Docker 容器的配置文件, 使用yaml
語言.
如只准備測試一主一從, 那麼移除 slave02
目錄, 添加多個從服務器則相應增加文件夾.
├── docker-compose.yml
├── master
│ ├── Dockerfile
│ └── my.cnf
├── slave01
│ ├── Dockerfile
│ └── my.cnf
└── slave02
├── Dockerfile
└── my.cnf
1.2 docker-compose 文件及解釋
-
environment
在創建 MySQL 密碼時, 測試用途用root
沒問題, 其他時候記得創建複雜密碼, 至少可以使用uuidgen
命令生成.
支持在創建時同時創建一個數據庫, 創建多個或進行其他數據初始化, 建議依靠外部SQL
文件. -
links
這個不是推薦的配置方式, 不利於擴展, 但在此處我們只是用於測試. 可以自由添加你要的從服務器名稱, 用於容器間的連接. 更推薦配置networks
-
ports
冒號左邊爲暴露的端口, 右邊爲容器內部的端口號, 在不配置網絡的情況下(此時默認爲127.0.0.1
), 爲了避免端口衝突, 必須使暴露的端口號不一致.
version: '2'
services:
mysql-master:
build:
context: ./ # 聲明構建的文件夾
dockerfile: master/Dockerfile # 聲明 Docker 文件目錄
environment: # 環境變量, 支持數組或列表方式
- "MYSQL_ROOT_PASSWORD=root"
- "MYSQL_DATABASE=db0" # 初始創建的數據庫
links:
- mysql-slave01
- mysql-slave02
ports:
- "33065:3306"
restart: always
hostname: mysql-master
mysql-slave01:
build:
context: ./
dockerfile: slave/Dockerfile
environment:
- "MYSQL_ROOT_PASSWORD=6954D5F0"
- "MYSQL_DATABASE=db0"
ports:
- "33066:3306"
restart: always
hostname: mysql-slave01
mysql-slave02:
build:
context: ./
dockerfile: slave02/Dockerfile
environment:
- "MYSQL_ROOT_PASSWORD=6954D5F0"
- "MYSQL_DATABASE=db0"
ports:
- "33067:3306"
restart: always
hostname: mysql-slave02
1.3 Dockerfile 文件及解釋
-
FROM
指定了基礎鏡像, 可以根據需求更改 MySQL 鏡像版本 -
COPY
將源文件複製到目標容器, 從服務器相應地創建Dockerfile
, 修改源文件位置. 也可以使用ADD
這個更高級的複製命令, 但沒必要.
FROM mysql:5.7.17
COPY ./master/my.cnf /etc/mysql/my.cnf
二. MySQL 配置文件準備
2.1 Master 節點配置
# master/my.cnf
[mysqld]
## 設置server_id,注意要唯一
server_id=100
## 複製過濾:也就是指定哪個數據庫不用同步(mysql庫一般不同步)
binlog-ignore-db=mysql
## 開啓二進制日誌功能,可以隨便取,最好有含義
log-bin=replicas-mysql-bin
## 爲每個session分配的內存,在事務過程中用來存儲二進制日誌的緩存
binlog_cache_size=1M
## 主從複製的格式(mixed,statement,row,默認格式是statement)
binlog_format=mixed
## 二進制日誌自動刪除/過期的天數。默認值爲0,表示不自動刪除。
expire_logs_days=7
## 跳過主從複製中遇到的所有錯誤或指定類型的錯誤,避免slave端複製中斷。
## 如:1062錯誤是指一些主鍵重複,1032錯誤是因爲主從數據庫數據不一致
slave_skip_errors=1062
2.2 Slave 節點配置
Slave 節點的配置與 Master 相似, 但每個節點的 server_id
必須不同, 此外增加了 relay_log
中繼日誌的配置以及只讀的設置
[mysqld]
## 設置server_id,注意要唯一
server_id=101
# ... 省略配置
## relay_log配置中繼日誌
relay_log=replicas-mysql-relay-bin
## log_slave_updates表示slave將複製事件寫進自己的二進制日誌
log_slave_updates=1
## 防止改變數據(除了特殊的線程)
read_only=1
三. 構建容器並運行
進入有 docker-compose.yml
的目錄, 執行以下命令
該命令十分強大,它將嘗試自動完成包括構建鏡像,(重新)創建服務,啓動服務,並關聯服務相關容器的一系列操作, -d
表示後臺運行鏡像.
docker-compose up -d
之後執行docker ps
查看正在運行的鏡像, 如果是一主一從, 可以看到至少兩個正在運行的鏡像
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef799b7d8cf8 mstest_mysql-master "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:33065->3306/tcp mstest_mysql-master_1
9d7ea93b7a85 mstest_mysql-slave "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:33066->3306/tcp mstest_mysql-slave_1
鍵入 docker exec -it [name/id] /bin/bash
進入容器, 可以是容器名稱也可以是容器 id, 如下方示例:
docker exec -it mysql-master_1 /bin/bash
四. 配置主從
可以直接進入容器再進入 mysql
配置, 也可以不進入, 直接在終端鍵入下方命令, port
就是 docker-compose.xml
設置的端口號, 例如前面 master
的 33065
mysql -uroot -p -P[port] -h127.0.0.1
4.1 獲取主節點狀態
鍵入 show master status;
記住當前 File
的名稱和 Position
, 這是從節點進行 binlog
複製找點用的.
mysql> show master status
-> ;
+---------------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------------+----------+--------------+------------------+-------------------+
| replicas-mysql-bin.000003 | 154 | | mysql | |
+---------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec
4.2 開啓從節點複製
這裏設置複製主節點的相關信息, 在前面文件用的是 root
密碼,因此這裏也是 root
用戶, 將MASTER_LOG_FILE
和 MASTER_LOG_POS
填上相應信息
CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='root', MASTER_PASSWORD='root', MASTER_LOG_FILE='replicas-mysql-bin.000003', MASTER_LOG_POS=154;
接着啓動複製.
- 鍵入
start slave;
- 鍵入
show slave status\G;
查看是否啓用成功, 關注Slave_IO_Running
和Slave_SQL_Running
是否爲Yes
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
同樣地, 如果有多個 Slave 節點, 就這一步多做幾次.
4.3 驗證是否成功
回到 Master 節點, 創建一個數據庫 或者 往已經創建好的 db0
寫入數據,
mysql> create database db1;
回到 Slave 節點, 查看兩邊是否同步.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db0 |
| db1 |
五. 後話——另一種主從複製 GTID
GTID 自 MySQL 5.6.MySQL 5.6.5 便引入了,中文叫全局事務 ID(Global Transaction ID)
在本文的基於二進制日誌複製中,從庫需要告知主庫要從哪個偏移量(就是 Log File 的 Position)進行增量同步,如果指定錯誤會造成數據的遺漏,從而造成數據的不一致。
但有了 GTID,發生主備切換時,MySQL 的其它從庫可以自動在新主庫上找到正確的複製位置,這大大簡化了複雜複製拓撲下集羣的維護,也減少了人爲設置複製位置發生誤操作的風險。另外,基於 GTID 的複製還可以忽略已經執行過的事務。
參考
公衆號:程序員的碎碎念
Github:github.com/FesonX