Docker 实现 MySQL 主从复制
第一章:搭建一主一从
1.1 架构
- 一台
主机
用于处理所有写请求
,一台从机
负责所有读请求
,架构图如下:
- MySQL 主机对外暴露的端口是 3306 ,从机对外暴露的端口是 3307 。
1.2 搭建步骤
1.2.1 自定义网络
- 创建自定义网络,以便容器之间可以通过主机名和端口互相通信:
1.2.2 新建主机容器实例
- 新建主机容器实例,并将其加入到 mysql 自定义网络中:
docker run -d -p 3306:3306 --network mysql \
--name mysql-master \
-v mysql-master:/etc/mysql \
-v /var/mysql-master/logs:/var/log/mysql \
-v /var/mysql-master/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
注意:
- 这里我使用的是具名卷,意味着 MySQL 的配置文件在
/var/lib/docker/volumes/
目录下的mysql-master
进行维护。-v mysql-master:/etc/mysql
其实也是可以写成-v mysql-master:/etc/mysql/conf.d
,只不过如果写成-v mysql-master:/etc/mysql/conf.d
需要在/etc/mysql/conf.d
映射的目录中新建 my.cnf 配置文件,而写成-v mysql-master:/etc/mysql
是不需要新建 my.cnf 配置文件的,两种方式均可以。
- 查看主机容器实例:
- 列出所有卷:
- 查看卷详情:
1.2.3 修改主机容器实例的配置文件
- 修改主机容器实例的配置文件,并重启主机容器实例:
[mysqld]
# 以下是增加的配置
server-id=1 # [必须] 主服务器唯一ID
log-bin=binlog # [必须] 启用二进制日志,指名路径。比如:自己本地的路径/log/mysqlbin
binlog_format=STATEMENT
1.2.4 新建从机容器实例
- 新建从机容器实例,并将其加入到 mysql 自定义网络中:
docker run -d -p 3307:3306 --network mysql \
--name mysql-slave \
-v mysql-slave:/etc/mysql \
-v /var/mysql-slave/logs:/var/log/mysql \
-v /var/mysql-slave/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
注意:这里我使用的是具名卷,意味着 MySQL 的配置文件在
/var/lib/docker/volumes/
目录下的mysql-slave
进行维护。
- 查看从机容器实例:
- 列出所有卷:
- 查看卷详情:
1.2.5 修改从机容器实例的配置文件
- 修改从机容器实例的配置文件,并重启从机容器实例:
1.2.6 查看自定义网络
- 查看自定义网络是否有 MySQL 的主机和从机:
1.2.7 主机容器实例:建立账户并授权
- 进入 MySQL 的主机容器实例,创建账户,并进行授权:
- 查看 Master 的状态,并记录 File 和 Position 的值:
注意:执行完此步骤后
不要再操作 MySQL 主机容器实例
,防止主服务器的状态值发生变化。
1.2.8 从机容器实例:配置需要复制的主机
- 步骤 ①:从机上复制主机的命令
CHANGE MASTER TO
MASTER_HOST='主机的IP地址',
MASTER_USER='主机用户名',
MASTER_PORT='主机的端口号',
MASTER_PASSWORD='主机用户名的密码',
MASTER_LOG_FILE='binlog.具体数字',
MASTER_LOG_POS=具体值;
- 示例:
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='binlog.000006',
MASTER_LOG_POS=1114;
此处,如果没有写端口,默认是 3306,那么是暴露的 3306 ?当然不是,是内部的端口 3306 ,因为走的是自定义网络,和暴露的外部端口没有任何关系,暴露的外部端口只是让客户端(Java 等)进行远程连接而已,而主从复制之间的通信是不需要外部端口的。
- 步骤 ②:启动 Slave 同步
- 示例:
- 步骤 ③:查看同步状态
- 示例:
注意:如果出现错误,可能的原因如下:
- ① 网络不通。
- ② 账户密码错误。
- ③ ~~防火墙~~。
- ④ MySQL 配置文件问题。
- ⑤ 连接服务器时的语法。
- ⑥ 主服务器 MySQL 的权限。
1.2.9 测试
- 主机容器实例新建库、新建表、插入记录,从机复制:
- 主机容器实例和从机容器实例查询数据库:
1.2.10 停止主从同步
- 在从机容器实例停止主从同步:
- 如果在停止主从同步后,再开启同步命令的时候,报错,可以执行如下的命令:
第二章:搭建双主双从
2.1 架构
- 一个主机 m1 用于处理所有写请求,它的从机 s1 和另一台主机 m2 还有它的从机 s2 负责所有读请求。当 m1 主机宕机后,m2 主机负责写请求,m1 和 m2 互为备机,架构图如下:
2.2 准备工作
- 首先会创建一个自定义网络 mysql ,然后会启动 4 台 MySQL 容器实例,其中 2 台作为主机,2 台作为从机。
编号 | 主机名 | 备注 |
---|---|---|
1 | m1 | 主机 |
2 | s1 | 从 |
3 | m2 | 主机(备) |
4 | s2 | 从机(备) |
2.3 自定义网络
- 创建自定义网络,以便容器之间可以通过主机名和端口互相通信:
2.4 新建 4 台 MySQL 容器实例
- 新建 4 台 MySQL 容器实例,2 台容器实例为 MySQL 的主机,2 台容器实例为 MySQL 的从机:
docker run -d -p 3306:3306 --network mysql \
--name m1 \
-v m1:/etc/mysql \
-v /var/m1/logs:/var/log/mysql \
-v /var/m1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
docker run -d -p 3307:3306 --network mysql \
--name s1 \
-v s1:/etc/mysql \
-v /var/s1/logs:/var/log/mysql \
-v /var/s1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
docker run -d -p 3308:3306 --network mysql \
--name m2 \
-v m2:/etc/mysql \
-v /var/m2/logs:/var/log/mysql \
-v /var/m2/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
docker run -d -p 3309:3306 --network mysql \
--name s2 \
-v s2:/etc/mysql \
-v /var/s2/logs:/var/log/mysql \
-v /var/s2/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai \
--restart=always mysql:8.0.26 \
--lower_case_table_names=1 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_general_ci \
--default-authentication-plugin=mysql_native_password
2.5 查看自定义网络
- 查看自定义网络是否有 MySQL 的主机和从机:
2.6 查看卷
- 列出所有卷:
- 查看卷详情:
其余,依次类推即可。
2.7 双主搭建
2.7.1 主机搭建(m1)
- 修改主机 m1 容器实例的配置文件,并重启主机容器 m1 实例:
[mysqld]
# 以下是增加的配置
server-id=1 # [必须] 主服务器唯一ID,保证整个集群环境中唯一,取值范围在 1 - 2^32 -1 ,默认为 1
log-slave-updates # 在作为从库的时候,有写入操作也需要更新二进制日志文件
2.7.2 主机搭建(m2)
- 修改主机 m2 容器实例的配置文件,并重启主机容器 m2 实例:
[mysqld]
# 以下是增加的配置
server-id=3 # [必须] 主服务器唯一ID,保证整个集群环境中唯一,取值范围在 1 - 2^32 -1 ,默认为 1
log-slave-updates # 在作为从库的时候,有写入操作也需要更新二进制日志文件
2.8 双从搭建
2.8.1 从机搭建(s1)
- 修改从机 s1 容器实例的配置文件,并重启从机容器 s1 实例:
2.8.2 从机搭建(s2)
- 修改从机 s2 容器实例的配置文件,并重启从机容器 s2 实例:
2.9 双主:建立账户并授权
- MySQL 主机(m1)创建账号并授权:
- MySQL 主机(m2)创建账号并授权:
- 查看 MySQL 主机(m1)的状态,并记录 File 和 Position 的值:
- 查看 MySQL 主机(m2)的状态,并记录 File 和 Position 的值:
2.10 双从:配置需要复制的主机
- 步骤 ①:从机上复制主机的命令
CHANGE MASTER TO
MASTER_HOST='主机的IP地址',
MASTER_USER='主机用户名',
MASTER_PORT='主机的端口号',
MASTER_PASSWORD='主机用户名的密码',
MASTER_LOG_FILE='binlog.具体数字',
MASTER_LOG_POS=具体值;
- 示例:s1
CHANGE MASTER TO
MASTER_HOST='m1',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='binlog.000003',
MASTER_LOG_POS=1114;
- 示例:s2
CHANGE MASTER TO
MASTER_HOST='m2',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='binlog.000003',
MASTER_LOG_POS=1114;
- 步骤 ②:启动 Slave 同步
- 示例:s1
- 示例:s2
- 步骤 ③:查看同步状态
- 示例:s1
- 示例:s2
到此为止,我们只是配置了两台主从复制,还没有配置主主复制,请看下面的操作。
2.11 双主之间的相互复制
- 步骤 ① :查看 Master 的状态,并记录 File 和 Position 的值:
之所以再次执行,是为了防止 File 和 Position 有变化。
- 示例:m1
- 示例:m2
- 步骤 ②:m2 复制 m1,m1 复制 m2。
CHANGE MASTER TO
MASTER_HOST='主机的IP地址',
MASTER_USER='主机用户名',
MASTER_PORT='主机的端口号',
MASTER_PASSWORD='主机用户名的密码',
MASTER_LOG_FILE='binlog.具体数字',
MASTER_LOG_POS=具体值;
- 示例:m1
CHANGE MASTER TO
MASTER_HOST='m2',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='binlog.000003',
MASTER_LOG_POS=1114;
- 示例:m2
CHANGE MASTER TO
MASTER_HOST='m1',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='binlog.000003',
MASTER_LOG_POS=1114;
- 步骤 ③:启动 Master 同步
- 示例:m1
- 示例:m2
- 步骤 ④:查看同步状态
- 示例:m1
- 示例:m2
2.12 测试
-
在 m1 和 m2 上执行 DDL 和 DML 语句,查看涉及到的数据库服务器的数据同步情况。
-
示例:m1
# 执行 DDL 操作
CREATE DATABASE IF NOT EXISTS dbtest CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
- 示例:m2
- 示例:m1
- 示例:m2
- 示例:s1
- 示例:s2
更新: 2022-12-05 01:40:40
原文: https://www.yuque.com/fairy-era/yg511q/aptyqmf46zssnpaz