Intro
主從備份是容災(zāi)的一種手段, 模擬主從備份可以有下面幾種方式:
- 不差錢方式, 買幾臺主機測試, 這種方式也比較接近線上環(huán)境.
- 通過創(chuàng)建幾臺虛擬機來模擬. 這種方式對本機性能要求相對較高. 相對不差錢可以選這種方式, 但安裝幾臺虛擬機也不是一件效率高的事.
- 在一臺主機上創(chuàng)建多個數(shù)據(jù)庫實例. 缺點是環(huán)境無法隔離, 需要額外加多一些配置
- 通過 Docker-compose 直接創(chuàng)建多個數(shù)據(jù)庫容器, 暴露端口訪問即可.
binlog
是MySQL數(shù)據(jù)庫的二進制日志,用于記錄用戶對數(shù)據(jù)庫操作的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 |
環(huán)境準備
0.1 測試環(huán)境
必須安裝有 docker
及 docker-compose
用于構(gòu)建容器環(huán)境, 本測試在 Ubuntu 16.04 及下列版本下進行, 使用其他版本可能會有使用差異.
docker-compose 1.25.4
docker 19.03.6
有關(guān)安裝的細節(jié), 請搜索相關(guān)關(guān)鍵詞, 或者直接根據(jù) Docker 官方文檔 進行安裝
0.2 Docker 加速
由于眾所周知的原因, 拉取鏡像時可能會很慢, 推薦設(shè)置國內(nèi)的鏡像源進行加速
在 Ubuntu/Centos/Debian
下修改或創(chuàng)建此文件 /etc/docker/daemon.json
示例文件內(nèi)容如下, 可以自由添加鏡像源. 鏡像源有可能會宕機, 鏡像源測試請參閱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
創(chuàng)建即可. -
docker-compose.yml
是用于運行多個 Docker 容器的配置文件, 使用yaml
語言.
如只準備測試一主一從, 那么移除 slave02
目錄, 添加多個從服務(wù)器則相應(yīng)增加文件夾.
├── docker-compose.yml
├── master
│ ├── Dockerfile
│ └── my.cnf
├── slave01
│ ├── Dockerfile
│ └── my.cnf
└── slave02
├── Dockerfile
└── my.cnf
1.2 docker-compose 文件及解釋
-
environment
在創(chuàng)建 MySQL 密碼時, 測試用途用root
沒問題, 其他時候記得創(chuàng)建復(fù)雜密碼, 至少可以使用uuidgen
命令生成.
支持在創(chuàng)建時同時創(chuàng)建一個數(shù)據(jù)庫, 創(chuàng)建多個或進行其他數(shù)據(jù)初始化, 建議依靠外部SQL
文件. -
links
這個不是推薦的配置方式, 不利于擴展, 但在此處我們只是用于測試. 可以自由添加你要的從服務(wù)器名稱, 用于容器間的連接. 更推薦配置networks
-
ports
冒號左邊為暴露的端口, 右邊為容器內(nèi)部的端口號, 在不配置網(wǎng)絡(luò)的情況下(此時默認為127.0.0.1
), 為了避免端口沖突, 必須使暴露的端口號不一致.
version: '2'
services:
mysql-master:
build:
context: ./ # 聲明構(gòu)建的文件夾
dockerfile: master/Dockerfile # 聲明 Docker 文件目錄
environment: # 環(huán)境變量, 支持數(shù)組或列表方式
- "MYSQL_ROOT_PASSWORD=root"
- "MYSQL_DATABASE=db0" # 初始創(chuàng)建的數(shù)據(jù)庫
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
指定了基礎(chǔ)鏡像, 可以根據(jù)需求更改 MySQL 鏡像版本 -
COPY
將源文件復(fù)制到目標容器, 從服務(wù)器相應(yīng)地創(chuàng)建Dockerfile
, 修改源文件位置. 也可以使用ADD
這個更高級的復(fù)制命令, 但沒必要.
FROM mysql:5.7.17
COPY ./master/my.cnf /etc/mysql/my.cnf
二. MySQL 配置文件準備
2.1 Master 節(jié)點配置
# master/my.cnf
[mysqld]
## 設(shè)置server_id萍桌,注意要唯一
server_id=100
## 復(fù)制過濾:也就是指定哪個數(shù)據(jù)庫不用同步(mysql庫一般不同步)
binlog-ignore-db=mysql
## 開啟二進制日志功能散吵,可以隨便取孔轴,最好有含義
log-bin=replicas-mysql-bin
## 為每個session分配的內(nèi)存蓬衡,在事務(wù)過程中用來存儲二進制日志的緩存
binlog_cache_size=1M
## 主從復(fù)制的格式(mixed,statement,row杀糯,默認格式是statement)
binlog_format=mixed
## 二進制日志自動刪除/過期的天數(shù)扫俺。默認值為0,表示不自動刪除固翰。
expire_logs_days=7
## 跳過主從復(fù)制中遇到的所有錯誤或指定類型的錯誤狼纬,避免slave端復(fù)制中斷。
## 如:1062錯誤是指一些主鍵重復(fù)骂际,1032錯誤是因為主從數(shù)據(jù)庫數(shù)據(jù)不一致
slave_skip_errors=1062
2.2 Slave 節(jié)點配置
Slave 節(jié)點的配置與 Master 相似, 但每個節(jié)點的 server_id
必須不同, 此外增加了 relay_log
中繼日志的配置以及只讀的設(shè)置
[mysqld]
## 設(shè)置server_id疗琉,注意要唯一
server_id=101
# ... 省略配置
## relay_log配置中繼日志
relay_log=replicas-mysql-relay-bin
## log_slave_updates表示slave將復(fù)制事件寫進自己的二進制日志
log_slave_updates=1
## 防止改變數(shù)據(jù)(除了特殊的線程)
read_only=1
三. 構(gòu)建容器并運行
進入有 docker-compose.yml
的目錄, 執(zhí)行以下命令
該命令十分強大,它將嘗試自動完成包括構(gòu)建鏡像歉铝,(重新)創(chuàng)建服務(wù)盈简,啟動服務(wù),并關(guān)聯(lián)服務(wù)相關(guān)容器的一系列操作, -d
表示后臺運行鏡像.
docker-compose up -d
之后執(zhí)行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
設(shè)置的端口號, 例如前面 master
的 33065
mysql -uroot -p -P[port] -h127.0.0.1
4.1 獲取主節(jié)點狀態(tài)
鍵入 show master status;
記住當前 File
的名稱和 Position
, 這是從節(jié)點進行 binlog
復(fù)制找點用的.
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 開啟從節(jié)點復(fù)制
這里設(shè)置復(fù)制主節(jié)點的相關(guān)信息, 在前面文件用的是 root
密碼,因此這里也是 root
用戶, 將MASTER_LOG_FILE
和 MASTER_LOG_POS
填上相應(yīng)信息
CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='root', MASTER_PASSWORD='root', MASTER_LOG_FILE='replicas-mysql-bin.000003', MASTER_LOG_POS=154;
接著啟動復(fù)制.
- 鍵入
start slave;
- 鍵入
show slave status\G;
查看是否啟用成功, 關(guān)注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 節(jié)點, 就這一步多做幾次.
4.3 驗證是否成功
回到 Master 節(jié)點, 創(chuàng)建一個數(shù)據(jù)庫 或者 往已經(jīng)創(chuàng)建好的 db0
寫入數(shù)據(jù),
mysql> create database db1;
回到 Slave 節(jié)點, 查看兩邊是否同步.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db0 |
| db1 |
五. 后話——另一種主從復(fù)制 GTID
GTID 自 MySQL 5.6.MySQL 5.6.5 便引入了太示,中文叫全局事務(wù) ID(Global Transaction ID)
在本文的基于二進制日志復(fù)制中柠贤,從庫需要告知主庫要從哪個偏移量(就是 Log File 的 Position)進行增量同步,如果指定錯誤會造成數(shù)據(jù)的遺漏类缤,從而造成數(shù)據(jù)的不一致臼勉。
但有了 GTID,發(fā)生主備切換時餐弱,MySQL 的其它從庫可以自動在新主庫上找到正確的復(fù)制位置宴霸,這大大簡化了復(fù)雜復(fù)制拓撲下集群的維護囱晴,也減少了人為設(shè)置復(fù)制位置發(fā)生誤操作的風(fēng)險。另外瓢谢,基于 GTID 的復(fù)制還可以忽略已經(jīng)執(zhí)行過的事務(wù)畸写。
參考
公眾號:程序員的碎碎念
Github:github.com/FesonX