Docker 环境下 MySQL 主从复制集群、MGR 搭建及 Nginx 反向代理配置
在现代的软件开发和运维中,容器化技术如 Docker 极大地简化了应用程序的部署和管理。本文将详细介绍如何使用 Docker 搭建 MySQL 主从复制集群、MySQL Group Replication (MGR) 集群,以及配置 Nginx 反向代理,同时提供相应的配置步骤和测试方法。
一、MySQL 主从复制集群搭建
1. 架构图
MySQL 主从复制集群由一个主节点(Master)和两个从节点(Slave)组成,架构图如下:
plaintext
+-------------------+ +--------------------+ +--------------------+
| | | | | |
| MySQL Master |--------------------------| MySQL Slave 1 |--------------------------| MySQL Slave 2 |
| IP: 172.18.0.10 | | IP: 172.18.0.11 | | IP: 172.18.0.12 |
| Port: 3306 | | Port: 3306 | | Port: 3306 |
| Data Dir: /data/mysql/master | Data Dir: /data/mysql/slave1 | Data Dir: /data/mysql/slave2 |
+-------------------+ +--------------------+ +--------------------+
2. 配置文件复制
首先启动一个临时 MySQL 容器来提取默认配置文件:
docker run -d --name mysql-temp mysql:8.0
等待几秒后,将配置文件复制到本地:
mkdir -p /data/mysql/conf
docker cp mysql-temp:/etc/my.cnf /data/mysql/conf/my.cnf
停止并删除临时容器:
docker stop mysql-temp && docker rm mysql-temp
创建主从节点的目录结构并复制配置文件:
mkdir -p /data/mysql/{master,slave1,slave2}/{conf,data}
cp /data/mysql/conf/my.cnf /data/mysql/master/conf/
cp /data/mysql/conf/my.cnf /data/mysql/slave1/conf/
cp /data/mysql/conf/my.cnf /data/mysql/slave2/conf/
3. 网络搭建
使用自定义网络和静态 IP 地址可以更好地规划和管理网络:
docker network create \--driver bridge \--subnet=172.18.0.0/24 \custom-mysql-network
启动 Master 容器并指定固定 IP:
docker run -d \--name mysql-master \--network custom-mysql-network \--ip 172.18.0.10 \-e MYSQL_ROOT_PASSWORD=root \mysql:8.0
4. 修改配置文件
分别修改主从节点的配置文件:
- Master 配置文件
/data/mysql/master/conf/my.cnf
:[mysqld] server-id=1 log-bin=binlog binlog-format=row
- Slave 1 配置文件
/data/mysql/slave1/conf/my.cnf
:[mysqld] server-id=2 relay-log=relaylog log-slave-updates=1
Slave 2 配置文件
/data/mysql/slave2/conf/my.cnf
:[mysqld] server-id=3 relay-log=relaylog log-slave-updates=1
5. 启动 MySQL 容器
启动主从节点的 MySQL 容器:
# 启动 Master docker run -d \--name mysql-master \--network custom-mysql-network \--ip 172.18.0.10 \--mount type=bind,source=/data/mysql/master/conf/my.cnf,target=/etc/my.cnf \--mount type=bind,source=/data/mysql/master/data,target=/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=root \mysql:8.0# 启动 Slave 1 docker run -d \--name mysql-slave1 \--network custom-mysql-network \--ip 172.18.0.11 \--mount type=bind,source=/data/mysql/slave1/conf/my.cnf,target=/etc/my.cnf \--mount type=bind,source=/data/mysql/slave1/data,target=/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=root \mysql:8.0# 启动 Slave 2 docker run -d \--name mysql-slave2 \--network custom-mysql-network \--ip 172.18.0.12 \--mount type=bind,source=/data/mysql/slave2/conf/my.cnf,target=/etc/my.cnf \--mount type=bind,source=/data/mysql/slave2/data,target=/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=root \mysql:8.0
6. 创建复制账户
进入 Master 容器创建用于复制的用户并查看 Binlog 状态:
# 创建复制用户 docker exec -it mysql-master mysql -uroot -proot -e " CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES; "# 查看当前 Binlog 状态 docker exec -it mysql-master mysql -uroot -proot -e "SHOW MASTER STATUS;"
7. 配置主从关系
分别配置 Slave 1 和 Slave 2 的主从关系并查看状态:
# 配置 Slave 1 docker exec -it mysql-slave1 mysql -uroot -proot -e " CHANGE MASTER TOMASTER_HOST='172.18.0.10',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='binlog.000003',MASTER_LOG_POS=2553; START SLAVE; " docker exec -it mysql-slave1 mysql -uroot -proot -e "SHOW SLAVE STATUS\G"# 配置 Slave 2 docker exec -it mysql-slave2 mysql -uroot -proot -e " CHANGE MASTER TOMASTER_HOST='172.18.0.10',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='binlog.000003',MASTER_LOG_POS=2553; START SLAVE; " docker exec -it mysql-slave2 mysql -uroot -proot -e "SHOW SLAVE STATUS\G"
8. 测试主从同步
在 Master 上插入测试数据,然后在 Slave 1 和 Slave 2 上查询数据:
# 在 Master 上插入数据 docker exec -it mysql-master mysql -uroot -proot -e " CREATE DATABASE testdb; USE testdb; CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50)); INSERT INTO users (name) VALUES ('Alice'), ('Bob'); "# 在 Slave 1 和 Slave 2 上查询数据 docker exec -it mysql-slave1 mysql -uroot -proot -e "SELECT * FROM testdb.users;" docker exec -it mysql-slave2 mysql -uroot -proot -e "SELECT * FROM testdb.users;"
二、MGR 搭建
1. 使用 GTID 主从
修改所有节点的
my.cnf
配置文件,启用 GTID 模式:# Master 配置 [mysqld] server-id=1 log-bin=mysql-bin gtid_mode=ON enforce-gtid-consistency=ON# Slave 1 配置 [mysqld] server-id=2 relay-log=mysql-relay-bin gtid_mode=ON enforce-gtid-consistency=ON# Slave 2 配置 [mysqld] server-id=3 relay-log=mysql-relay-bin gtid_mode=ON enforce-gtid-consistency=ON
重启所有 MySQL 容器:
docker restart mysql-master docker restart mysql-slave1 docker restart mysql-slave2
设置主库连接信息并验证 GTID 主从状态:
# 在 Slave 1 上执行 docker exec -it mysql-slave1 mysql -uroot -proot -e "STOP SLAVE;" docker exec -it mysql-slave1 mysql -uroot -proot -e " CHANGE MASTER TOMASTER_HOST='172.18.0.10',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_AUTO_POSITION=1; " docker exec -it mysql-slave1 mysql -uroot -proot -e "START SLAVE;"# 在 Slave 2 上执行 docker exec -it mysql-slave2 mysql -uroot -proot -e "STOP SLAVE;" docker exec -it mysql-slave2 mysql -uroot -proot -e " CHANGE MASTER TOMASTER_HOST='172.18.0.10',MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_AUTO_POSITION=1; " docker exec -it mysql-slave2 mysql -uroot -proot -e "START SLAVE;"# 验证 GTID 主从状态 docker exec -it mysql-slave1 mysql -uroot -proot -e "SHOW SLAVE STATUS\G" docker exec -it mysql-slave2 mysql -uroot -proot -e "SHOW SLAVE STATUS\G"
2. 修改配置文件
分别修改 Master、Slave 1 和 Slave 2 的配置文件:
# Master 节点配置 [mysqld] server_id=1 gtid_mode=ON enforce_gtid_consistency=ONplugin_dir=/usr/lib64/mysql/plugin binlog_checksum=NONEtransaction_write_set_extraction=XXHASH64 loose-group_replication_recovery_use_ssl=ON loose-group_replication_group_name="aaaaaaaa-aaaa-4aaa-aacd-1234567890ab" loose-group_replication_start_on_boot=OFFloose-group_replication_local_address="master:24901" loose-group_replication_group_seeds="master:24901,slave1:24901,slave2:24901"loose-group_replication_bootstrap_group=OFF# Slave1 节点配置 [mysqld] server_id=2 gtid_mode=ON enforce_gtid_consistency=ONplugin_dir=/usr/lib64/mysql/plugin binlog_checksum=NONEloose-group_replication_recovery_get_public_key=ON loose-group_replication_recovery_use_ssl=OFF loose-group_replication_group_name="aaaaaaaa-aaaa-4aaa-aacd-1234567890ab" loose-group_replication_start_on_boot=OFFloose-group_replication_local_address= "slave1:24901" loose-group_replication_group_seeds= "master:24901,slave1:24901,slave2:24901"loose-group_replication_bootstrap_group=OFF# Slave2 节点配置 [mysqld] server_id=3 gtid_mode=ON enforce_gtid_consistency=ONplugin_dir=/usr/lib64/mysql/plugin binlog_checksum=NONEloose-group_replication_recovery_get_public_key=ON loose-group_replication_recovery_use_ssl=OFF loose-group_replication_group_name="aaaaaaaa-aaaa-4aaa-aacd-1234567890ab" loose-group_replication_start_on_boot=OFFloose-group_replication_local_address= "slave2:24901" loose-group_replication_group_seeds= "master:24901,slave1:24901,slave2:24901"loose-group_replication_bootstrap_group=OFF
3. 启动容器
docker restart master docker restart slave1 docker restart slave2
4. 初始化 MGR 集群
进入 Master 容器进行初始化操作:
docker exec -it master mysql -uroot -proot
-- 清除旧主从信息 STOP SLAVE; RESET SLAVE ALL; RESET MASTER;-- 创建复制用户和权限 CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES;-- 安装 MGR 插件 INSTALL PLUGIN group_replication SONAME 'group_replication.so';-- 引导第一个节点加入组 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF;
分别进入 Slave 1 和 Slave 2 容器添加节点:
docker exec -it slave1 mysql -uroot -proot
-- 清除旧数据 STOP SLAVE; RESET SLAVE ALL; RESET MASTER;-- 安装插件 INSTALL PLUGIN group_replication SONAME 'group_replication.so';-- 设置同步账户 CHANGE MASTER TOMASTER_USER='slave',MASTER_PASSWORD='123456'FOR CHANNEL 'group_replication_recovery';-- 启动组复制 START GROUP_REPLICATION;
验证集群状态
SELECT * FROM performance_schema.replication_group_members;
三、Nginx 反向代理配置
1. 部署 Nginx 前端项目
docker run -itd --name n1 \ -v /data/nginx/html:/etc/nginx/html \ -p 80:80 \ nginx
2. 挂载对应配置文件
复制并修改配置文件:
server {listen 80;server_name localhost;location / {root /etc/nginx/html/;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}}
重新启动 Nginx 容器:
docker run -itd --name n1 \ -v /data/nginx/html:/etc/nginx/html \ -v /data/nginx/conf.d:/etc/nginx/conf.d \ -p 80:80 \ nginx
3. 部署后端服务
docker pull openjdk:8 docker network create my-networkdocker run -d \--name s1 \--network my-network \-v /data/java:/java \openjdk:8 \tail -f /dev/nulldocker run -d \--name s2 \--network my-network \-v /data/java:/java \openjdk:8 \tail -f /dev/nulldocker run -d \--name s3 \--network my-network \-v /data/java:/java \openjdk:8 \tail -f /dev/nulldocker exec s1 java -jar /java/msg.jar docker exec s2 java -jar /java/msg.jar docker exec s3 java -jar /java/msg.jar
4. 搭建反向代理
docker network connect my-network n1
# 服务器的集群 upstream tomcatList { server s1:8081 weight=1; server s2:8081 weight=1; server s3:8081 weight=1; } location ~^/api/ {rewrite ^/api/(.*)$ /$1 break;proxy_pass http://tomcatList;proxy_redirect default; }
通过以上步骤,我们成功搭建了 MySQL 主从复制集群、MGR 集群,并配置了 Nginx 反向代理。这些技术的应用可以提高系统的可用性、性能和可扩展性。