本文最后更新于 5 天前,其中的信息可能已经过时,如有错误请发送邮件到 big_fw@foxmail.com
以下是 MySQL 一主两从(主从复制 + 读写分离)架构搭建,按「主库(master)→ 从库 1(slave01)→ 从库 2(slave02)→ 主从配置」的顺序拆解:
注意:以下操作使用到了 3308,3309,3310 端口,记得在安全组将对应的端口开放!
一、主库(master)搭建步骤
1. 初始启动主库容器(临时,用于获取配置文件)
docker run –name master –restart always -p 3308:3306 -v /root/docker/volumes/etc/master:/etc/mysql -v /root/docker/volumes/var/lib/master:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riCXT8zM -d mysql:latest
- 作用:创建并启动名为
master
的 MySQL 容器,作为主库的临时实例,目的是获取默认配置文件。 - 参数说明:
--name master
:容器名称为master
。--restart always
:容器退出时自动重启。-p 3308:3306
:宿主机 3308 端口映射到容器 3306 端口(主库对外端口)。-v ...
:挂载配置目录(/etc/mysql
)和数据目录(/var/lib/mysql
)到宿主机,实现持久化。-e MYSQL_ROOT_PASSWORD=riCXT8zM
:设置 root 密码为riCXT8zM
。-d mysql:latest
:后台运行,使用最新 MySQL 镜像。
2. 复制容器内的默认配置文件到宿主机
docker cp master:/etc/my.cnf /root/docker/volumes/etc/master/my.cnf
- 作用:将容器内 MySQL 的核心配置文件
my.cnf
复制到宿主机挂载目录(后续需修改该文件开启主库日志)。 docker cp
:容器与宿主机之间复制文件的命令(格式:docker cp 容器名:容器内路径 宿主机路径
)。
(如果该命令执行失败,可能是因为你没有 my.cnf 文件,需要文件的可以留言评论私信我哟~)
3. 查看所有容器状态
docker ps -a
- 作用:确认
master
容器是否正常运行(状态为Up
),为后续停止和删除做准备。
4. 停止并删除临时主库容器
docker stop master # 停止容器
docker rm master # 删除容器(因配置文件已复制,临时容器可删除)
docker ps -a # 确认容器已删除
- 作用:临时容器的使命(获取配置文件)已完成,删除后重新启动带自定义配置的主库。
5. 启动最终的主库容器(带自定义配置)
docker run –name master -p 3308:3306 -v /root/docker/volumes/etc/master/my.cnf:/etc/my.cnf -v /root/docker/volumes/etc/master/my.cnf.d:/etc/mysql/my.cnf.d -v /root/docker/volumes/etc/master/conf.d:/etc/mysql/conf.d -v /root/docker/volumes/var/lib/master:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riCXT8zM -d mysql:latest
- 作用:基于修改后的配置文件启动主库容器,此时配置文件已包含主从复制所需的日志设置(如
log_bin
、server_id
等,需手动在my.cnf
中添加)。 - 参数说明:
- 多个
-v
分别挂载核心配置文件my.cnf
、配置子目录my.cnf.d
、conf.d
以及数据目录,确保配置生效且数据持久化。 - 未加
--restart always
可根据需求添加(若之前已设置宿主机挂载目录权限,可省略)。
- 多个
二、从库 1(slave01)搭建步骤
1. 初始启动从库 1 容器(临时,用于获取配置文件)
docker run –name slave01 –restart always -p 3309:3306 -v /root/docker/volumes/etc/slave01:/etc/mysql -v /root/docker/volumes/var/lib/slave01:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riDYQ8zM -d mysql:latest
- 作用:创建临时
slave01
容器,获取默认配置文件(与主库步骤 1 逻辑一致)。 - 区别:端口映射为
3309:3306
(从库 1 对外端口),密码为riDYQ8zM
,挂载目录为slave01
专属。
2. 复制从库 1 的默认配置文件到宿主机
docker cp slave01:/etc/my.cnf /root/docker/volumes/etc/slave01/my.cnf
- 作用:复制容器内
my.cnf
到宿主机,后续将修改该文件设置从库的server_id
等参数。
(同样如果该命令执行失败,可能是因为你没有 my.cnf 文件,需要文件的可以留言评论私信我哟~)
3. 停止并删除临时从库 1 容器
docker ps -a # 查看容器状态
docker stop slave01 # 停止容器
docker rm slave01 # 删除容器
docker ps -a # 确认删除
5. 启动最终的从库 1 容器(带自定义配置)
docker run –name slave01 -p 3309:3306 -v /root/docker/volumes/etc/slave01/my.cnf:/etc/my.cnf -v /root/docker/volumes/etc/slave01/my.cnf.d:/etc/mysql/my.cnf.d -v /root/docker/volumes/etc/slave01/conf.d:/etc/mysql/conf.d -v /root/docker/volumes/var/lib/slave01:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riDYQ8zM -d mysql:latest
- 作用:基于修改后的配置文件启动从库 1,配置文件中已添加从库专属的
server_id
等参数。
三、从库 2(slave02)搭建步骤
1. 初始启动从库 2 容器(临时,获取配置文件)
docker run –name slave02 –restart always -p 3310:3306 -v /root/docker/volumes/etc/slave02:/etc/mysql -v /root/docker/volumes/var/lib/slave02:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riEZG8zM -d mysql:latest
- 作用:创建临时
slave02
容器,逻辑同主库和从库 1。 - 区别:端口映射为
3310:3306
(从库 2 对外端口),密码为riEZG8zM
,挂载目录为slave02
专属。
2. 复制从库 2 的默认配置文件到宿主机
docker cp slave02:/etc/my.cnf /root/docker/volumes/etc/slave02/my.cnf
3. 停止并删除临时从库 2 容器
docker ps -a # 查看状态
docker stop slave02 # 停止容器
docker rm slave02 # 删除容器
docker ps -a # 确认删除
5. 启动最终的从库 2 容器(带自定义配置)
docker run –name slave02 -p 3310:3306 -v /root/docker/volumes/etc/slave02/my.cnf:/etc/my.cnf -v /root/docker/volumes/etc/slave02/my.cnf.d:/etc/mysql/my.cnf.d -v /root/docker/volumes/etc/slave02/conf.d:/etc/mysql/conf.d -v /root/docker/volumes/var/lib/slave02:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=riEZG8zM -d mysql:latest
- 作用:启动从库 2,配置文件中已添加其专属
server_id
。
四、配置从库与主库同步(slave01 和 slave02)
1. 配置从库 1(slave01)的 server_id
docker exec -it slave01 /bin/bash # 进入 slave01 容器内部
cat /etc/my.cnf # 查看配置文件(确认路径)
exit
# 1. 停止从库容器
docker stop slave01
# 2. 在宿主机上编辑配置文件(路径是挂载到宿主机的目录)
vi /root/docker/volumes/etc/slave01/my.cnf
#点击i进行编辑
# 3. 在文件末尾添加一行(手动输入,无需 sed 命令)
server_id=2
# 4. “:wq”保存退出后,重启容器
docker start slave01
mysql -uroot -priDYQ8zM # 登录从库1的 MySQL(在容器内执行)
#(此时若密码不正确,请跳转到文章的最后从库(slave01)的权限配置)
show variables like ‘server_id’; # 验证 server_id 是否为 2(确认配置生效)
- 说明:
server_id
是主从复制的必要参数,主库、从库 1、从库 2 必须唯一(通常主库设为 1,从库依次递增)。
2. 配置从库 2(slave02)的 server_id
docker exec -it slave02 /bin/bash # 进入 slave02 容器内部
cat /etc/my.cnf # 查看配置文件
#步骤同上
exit
# 1. 停止从库容器
docker stop slave02
# 2. 在宿主机上编辑配置文件(路径是挂载到宿主机的目录)
vi /root/docker/volumes/etc/slave02/my.cnf
#点击i进行编辑
# 3. 在文件末尾添加一行(手动输入,无需 sed 命令)
server_id=3
# 4. “:wq”保存退出后,重启容器
docker start slave02
mysql -uroot -priEZG8zM # 登录从库2的 MySQL
#若密码有问题同上操作,转至文字最后~
show variables like ‘server_id’; # 验证 server_id 是否为 3
五、主从复制核心配置(从库关联主库)
1. 在主库(master)中查看同步起点信息
#登录主库
docker exec -it master /bin/bash
#登录主库的MySQL
mysql -uroot -riCXT8zM #同样密码有问题转至文字最后进行修改~
show master status; # 在主库的 MySQL 终端执行
- 作用:获取主库的二进制日志文件名(如
binlog.000003
)和位置(如157
),这是从库开始同步的起点。 - 输出示例:(这个一定要记录下来,后续需要修改对应信息。
2. 在从库中配置主库信息(slave01 和 slave02 均需执行)
sql #登录主库
docker exec -it slave01 /bin/bash
#登录从库1的MySQL
mysql -uroot -priDYQ8zM
change master to
master_port=3308, # 主库对外端口(宿主机的3308)
master_user=’root’, # 用于同步的主库用户名(通常为root或专用同步用户)
master_password=’riCXT8zM’, # 主库root密码
master_host=’172.20.16.116′, # 主库所在宿主机的IP地址(容器间可通信的IP)
master_log_file=’binlog.000001′, # 主库的二进制日志文件名(从show master status获取)
master_log_pos=1350; # 日志位置(从show master status获取)
master_ssl=1; — 启用 SSL 加密连接
- 作用:告知从库 “要同步哪个主库、从哪个日志位置开始同步”。
3. 重新登录从库并启动同步(以 slave01 为例,slave02 步骤相同)
bash docker exec -it slave01 /bin/bash # 进入 slave01 容器
mysql -uroot -priDYQ8zM # 登录 MySQL
start slave; # 启动从库同步进程(执行后从库开始同步主库数据)
show slave status\G # 查看同步状态(确认 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes 表示成功)
show slave status \G;
显示 Slave_IO_Running: Yes
和 Slave_SQL_Running: Yes
,说明从库 IO 线程(读取主库 binlog)和 SQL 线程(执行中继日志)均正常运行,主从同步成功。
一、从库(slave01)的权限配置
- 修复从库 root 用户登录问题
- 初始登录从库时,出现
ERROR 1045
(密码错误),原因是从库root
用户默认使用caching_sha2_password
加密规则,与密码不匹配。 - 解决:sql # 首先可以使用免密登录数据库
mysql -uroot
— 切换到系统数据库
use mysql;
— 修改 root@localhost 的加密规则为兼容模式,并重置密码
alter user ‘root’@’localhost’ identified with mysql_native_password by ‘riDYQ8zM’;
— 允许 root 用户从任意主机登录(% 表示所有 IP)
update user set host=’%’ where user=’root’;
— 刷新权限使配置生效
flush privileges;
# 设置完毕
exit #退出
# 再尝试用密码登录
mysql -uroot -priDYQ8zM
# 搞定即可返回接着下一步操作 - 作用:确保从库
root
用户能正常登录,并允许远程连接(方便后续管理)。
- 初始登录从库时,出现
- 确认从库基础配置
- 查看
server_id
:show variables like 'server_id';
显示为2
,符合从库唯一 ID 的要求(与主库、其他从库不重复)。
- 查看
总结
整个流程的核心逻辑是:
- 分别为 主库、从库 1、从库 2 创建容器并挂载配置 / 数据目录,确保配置可自定义且数据持久化。
- 通过修改
my.cnf
配置文件,为主库开启二进制日志(log_bin
)并设置唯一server_id
,为从库设置不同的server_id
。 - 在从库中通过
change master to
命令关联主库,指定同步的起点(日志文件和位置),最终启动同步进程。
完成后,主库的写操作会通过二进制日志同步到两个从库,实现 “一主两从” 的读写分离架构(主库负责写,从库负责读)。