我在一台虚拟机上部署docker,并拉取的mysql8.0.35镜像。启动了三个mysql容器,现在我想将这三个mysql部署为InnoDb集群,容器分别为主库mysql-master对外端口3307,从库mysql-slave1对外端口3308,从库mysql-slave2对外端口3309,我该如何配置,详细一点,注释明确一点每一步都说明一下
时间: 2025-07-27 14:22:23 AIGC 浏览: 40
<think>我们将在同一台虚拟机上的Docker中部署三个MySQL容器,并将它们配置为InnoDB集群。注意:InnoDB集群基于MySQL GroupReplication,要求每个MySQL实例能够通过内部网络相互通信。我们将使用Docker网络来连接它们。步骤:1.创建Docker网络,以便容器可以通过容器名称通信。2.分别启动三个MySQL容器,注意配置不同的端口映射(主库3307,从库3308和3309)和各自的配置文件。3.在每个MySQL实例中配置GroupReplication所需参数(通过配置文件挂载)。4.使用MySQLShell初始化集群(在第一个节点上执行)。5.将其他两个节点加入集群。注意:由于我们使用端口映射,容器内部使用3306端口,但外部映射到不同的端口(3307,3308,3309)。在集群内部通信时,我们使用容器名称和内部端口(3306)进行通信。但是,Group Replication通信端口(默认33061)也需要容器间互通。详细步骤:1.创建Docker网络```bashdocker networkcreate mysql-cluster-net```2.准备配置文件每个节点需要不同的配置文件,主要区别在于server_id和group_replication_local_address。mysql-master(端口3307)配置文件`master.cnf`:```ini[mysqld]#基本配置server_id=1datadir=/var/lib/mysqlsocket=/var/run/mysqld/mysqld.sock#二进制日志配置log-bin=binlogbinlog_format=ROW#GTID配置gtid_mode=ONenforce_gtid_consistency=ON#组复制配置transaction_write_set_extraction=XXHASH64loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"#请替换为一个有效的UUID,可以使用uuidgen生成loose-group_replication_start_on_boot=OFFloose-group_replication_local_address="mysql-master:33061"loose-group_replication_group_seeds= "mysql-master:33061,mysql-slave1:33061,mysql-slave2:33061"loose-group_replication_bootstrap_group=OFF#其他配置log_slave_updates=ONmaster_info_repository=TABLErelay_log_info_repository=TABLE```mysql-slave1 (端口3308)配置文件`slave1.cnf`:```ini[mysqld]server_id=2datadir=/var/lib/mysqlsocket=/var/run/mysqld/mysqld.socklog-bin=binlogbinlog_format=ROWgtid_mode=ONenforce_gtid_consistency=ONtransaction_write_set_extraction=XXHASH64loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"#与master相同loose-group_replication_start_on_boot=OFFloose-group_replication_local_address="mysql-slave1:33061"loose-group_replication_group_seeds="mysql-master:33061,mysql-slave1:33061,mysql-slave2:33061"loose-group_replication_bootstrap_group=OFFlog_slave_updates=ONmaster_info_repository=TABLErelay_log_info_repository=TABLE```mysql-slave2 (端口3309)配置文件`slave2.cnf`:```ini[mysqld]server_id=3datadir=/var/lib/mysqlsocket=/var/run/mysqld/mysqld.socklog-bin=binlogbinlog_format=ROWgtid_mode=ONenforce_gtid_consistency=ONtransaction_write_set_extraction=XXHASH64loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"#与master相同loose-group_replication_start_on_boot=OFFloose-group_replication_local_address= "mysql-slave2:33061"loose-group_replication_group_seeds= "mysql-master:33061,mysql-slave1:33061,mysql-slave2:33061"loose-group_replication_bootstrap_group=OFFlog_slave_updates=ONmaster_info_repository=TABLErelay_log_info_repository=TABLE```注意:请确保将`loose-group_replication_group_name`替换为一个唯一的UUID(可以使用`uuidgen`命令生成)。3.启动容器注意:每个容器挂载自己的数据目录和配置文件,同时映射外部端口。```bash#启动主库容器(mysql-master)docker run-d--name=mysql-master--net=mysql-cluster-net \-p3307:3306 \-v $(pwd)/master.cnf:/etc/mysql/conf.d/master.cnf\-vmysql-master-data:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=root\mysql:8.0.35#启动从库1容器(mysql-slave1)docker run-d--name=mysql-slave1 --net=mysql-cluster-net\-p3308:3306\-v$(pwd)/slave1.cnf:/etc/mysql/conf.d/slave1.cnf\-vmysql-slave1-data:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=root\mysql:8.0.35#启动从库2容器(mysql-slave2)dockerrun -d --name=mysql-slave2--net=mysql-cluster-net \-p3309:3306 \-v $(pwd)/slave2.cnf:/etc/mysql/conf.d/slave2.cnf \-vmysql-slave2-data:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=root\mysql:8.0.35```4.初始化集群(在mysql-master上执行)进入mysql-master容器,并使用MySQL Shell配置集群。```bashdocker exec-itmysql-master mysqlsh```在MySQL Shell中执行:```javascript//连接到当前实例(使用root用户)\connectroot@localhost:3306//创建用于集群管理的用户(在所有节点都需要,所以先创建用户并授权)//注意:这里为了简化,使用root用户,但生产环境应创建单独用户//或者,我们可以创建一个新用户,并授予必要的权限//这里我们创建一个新用户'clusteradmin',并授予所需权限varcreateUserQuery ="CREATEUSER 'clusteradmin'@'%' IDENTIFIEDBY 'clusteradminpassword';";vargrantQuery= "GRANTALL PRIVILEGESON *.* TO'clusteradmin'@'%'WITH GRANT OPTION;";shell.session.runSql(createUserQuery);shell.session.runSql(grantQuery);//退出当前会话\disconnect//使用新创建的用户连接到当前实例\connect clusteradmin@mysql-master:3306//配置实例以支持组复制(检查并安装所需插件)dba.configureInstance('clusteradmin@mysql-master:3306',{password: 'clusteradminpassword'});//创建集群varcluster =dba.createCluster('myCluster');//添加其他两个节点cluster.addInstance('clusteradmin@mysql-slave1:3306',{password: 'clusteradminpassword'});cluster.addInstance('clusteradmin@mysql-slave2:3306', {password:'clusteradminpassword'});//检查集群状态cluster.status();```5.验证集群在MySQL Shell中,使用`cluster.status()`查看集群状态,应该显示三个节点都是ONLINE。注意:在添加节点时,可能会遇到GTID不一致的问题(如果之前有数据)。因为我们刚启动容器,数据目录是空的,所以不会有这个问题。如果遇到,可以重置实例(删除数据目录重新启动)或者使用`recoveryMethod:'clone'`(需要安装克隆插件)。重要:在配置过程中,确保每个容器的时间同步,否则可能导致组复制失败。以上步骤完成后,InnoDB集群就部署完成了。可以通过任意节点进行写操作(但通常建议通过主节点写,从节点读)。InnoDB集群会自动处理故障转移。注意事项:-生产环境请使用更安全的密码。-考虑持久化数据(使用卷)以避免数据丢失。-如果需要SSL,请配置SSL参数。如果遇到网络问题,请确保容器间可以通过容器名称和端口33061互相访问(在容器内使用telnet或ping测试)。§§相关问题§§:1.在InnoDB集群中,如何实现故障转移?故障转移后客户端如何知道新的主节点?2.如何监控InnoDB集群的状态和性能?3.在Docker中部署InnoDB集群时,如何处理容器重启后的集群恢复?4.如何为InnoDB集群配置MySQLRouter以实现读写分离和负载均衡?</think>### 在 Docker 中部署 MySQL InnoDB 集群的详细配置
以下是完整的配置步骤,将三个 MySQL 容器部署为 InnoDB 集群,包含详细的配置文件和操作说明:
#### 整体架构:
- **主节点**:`mysql-master` (外部端口 3307)
- **从节点1**:`mysql-slave1` (外部端口 3308)
- **从节点2**:`mysql-slave2` (外部端口 3309)
---
### 步骤 1: 创建 Docker 网络和配置文件
#### 1.1 创建专用网络
```bash
docker network create mysql-cluster-net
```
#### 1.2 生成配置文件
创建配置文件目录:
```bash
mkdir -p mysql-config && cd mysql-config
```
##### 主节点配置文件 (`master.cnf`)
```ini
[mysqld]
# 基础配置
server_id=1
port=3306
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
# 二进制日志配置
log-bin=mysql-bin
binlog_format=ROW
expire_logs_days=7
sync_binlog=1
# GTID 配置
gtid_mode=ON
enforce_gtid_consistency=ON
# 组复制配置
transaction_write_set_extraction=XXHASH64
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 使用 uuidgen 生成
group_replication_start_on_boot=OFF
group_replication_local_address="mysql-master:33061"
group_replication_group_seeds="mysql-master:33061,mysql-slave1:33061,mysql-slave2:33061"
group_replication_bootstrap_group=OFF
# 其他配置
log_slave_updates=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
innodb_flush_log_at_trx_commit=1
```
##### 从节点配置文件 (`slave1.cnf` 和 `slave2.cnf`)
```ini
[mysqld]
# 基础配置 (修改 server_id)
server_id=2 # slave2 改为 3
port=3306
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
# 二进制日志配置 (与主节点相同)
log-bin=mysql-bin
binlog_format=ROW
expire_logs_days=7
sync_binlog=1
# GTID 配置 (与主节点相同)
gtid_mode=ON
enforce_gtid_consistency=ON
# 组复制配置 (修改 local_address)
transaction_write_set_extraction=XXHASH64
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 与主节点相同
group_replication_start_on_boot=OFF
group_replication_local_address="mysql-slave1:33061" # slave2 改为 mysql-slave2:33061
group_replication_group_seeds="mysql-master:33061,mysql-slave1:33061,mysql-slave2:33061"
group_replication_bootstrap_group=OFF
# 其他配置 (与主节点相同)
log_slave_updates=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
innodb_flush_log_at_trx_commit=1
```
> **重要提示**:
> 1. 使用 `uuidgen` 命令生成唯一的 `group_replication_group_name`
> 2. 每个节点的 `server_id` 必须唯一
> 3. `group_replication_local_address` 使用容器名称+33061端口
---
### 步骤 2: 启动 MySQL 容器
#### 2.1 启动主节点
```bash
docker run -d --name mysql-master \
--hostname mysql-master \
--net mysql-cluster-net \
-p 3307:3306 \
-v $(pwd)/master.cnf:/etc/mysql/conf.d/master.cnf \
-v mysql-master-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=SecureRootPass123 \
-e MYSQL_DATABASE=app_db \
mysql:8.0.35 \
--server-id=1 \
--log-bin=mysql-bin \
--binlog-format=ROW
```
#### 2.2 启动从节点1
```bash
docker run -d --name mysql-slave1 \
--hostname mysql-slave1 \
--net mysql-cluster-net \
-p 3308:3306 \
-v $(pwd)/slave1.cnf:/etc/mysql/conf.d/slave1.cnf \
-v mysql-slave1-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=SecureRootPass123 \
mysql:8.0.35 \
--server-id=2 \
--log-bin=mysql-bin \
--binlog-format=ROW
```
#### 2.3 启动从节点2
```bash
docker run -d --name mysql-slave2 \
--hostname mysql-slave2 \
--net mysql-cluster-net \
-p 3309:3306 \
-v $(pwd)/slave2.cnf:/etc/mysql/conf.d/slave2.cnf \
-v mysql-slave2-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=SecureRootPass123 \
mysql:8.0.35 \
--server-id=3 \
--log-bin=mysql-bin \
--binlog-format=ROW
```
> **参数说明**:
> - `--hostname`: 设置固定主机名,解决容器ID变化问题
> - `--net`: 使用专用网络确保容器间通信
> - `-v`: 挂载配置文件和持久化数据卷
> - `-e`: 设置MySQL环境变量
> - 末尾参数: 覆盖配置文件中的部分设置
---
### 步骤 3: 初始化 InnoDB 集群
#### 3.1 在主节点安装 MySQL Shell
```bash
docker exec -it mysql-master bash
apt update && apt install -y mysql-shell
```
#### 3.2 配置集群用户
```bash
# 连接到主节点MySQL
mysql -u root -pSecureRootPass123
-- 创建集群专用用户
CREATE USER 'clusteradmin'@'%' IDENTIFIED BY 'ClusterAdminPass123';
GRANT ALL PRIVILEGES ON *.* TO 'clusteradmin'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
-- 配置组复制用户
SET SQL_LOG_BIN=0;
ALTER USER 'clusteradmin'@'%' IDENTIFIED WITH mysql_native_password BY 'ClusterAdminPass123';
SET SQL_LOG_BIN=1;
```
#### 3.3 初始化集群
```javascript
// 启动 MySQL Shell
mysqlsh
// 连接到主节点
\connect clusteradmin@mysql-master:3306
// 配置实例
dba.configureInstance('clusteradmin@mysql-master:3306', {
password: 'ClusterAdminPass123',
interactive: false
});
// 创建集群
var cluster = dba.createCluster('myCluster', {
localAddress: 'mysql-master:33061',
force: true,
memberSslMode: 'DISABLED' // 简化配置,生产环境应启用
});
// 添加从节点1
cluster.addInstance('clusteradmin@mysql-slave1:3306', {
password: 'ClusterAdminPass123',
localAddress: 'mysql-slave1:33061',
recoveryMethod: 'clone',
memberSslMode: 'DISABLED'
});
// 添加从节点2
cluster.addInstance('clusteradmin@mysql-slave2:3306', {
password: 'ClusterAdminPass123',
localAddress: 'mysql-slave2:33061',
recoveryMethod: 'clone',
memberSslMode: 'DISABLED'
});
// 检查集群状态
cluster.status();
```
---
### 步骤 4: 验证集群操作
#### 4.1 创建测试数据
```bash
# 连接到主节点 (外部端口3307)
mysql -u root -pSecureRootPass123 -h 127.0.0.1 -P 3307
-- 创建测试表
CREATE DATABASE cluster_test;
USE cluster_test;
CREATE TABLE test_data (
id INT AUTO_INCREMENT PRIMARY KEY,
value VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入数据
INSERT INTO test_data (value) VALUES ('Cluster Test 1'), ('Cluster Test 2');
```
#### 4.2 验证数据同步
```bash
# 连接到从节点1 (外部端口3308)
mysql -u root -pSecureRootPass123 -h 127.0.0.1 -P 3308
-- 检查数据
SELECT * FROM cluster_test.test_data;
# 连接到从节点2 (外部端口3309)
mysql -u root -pSecureRootPass123 -h 127.0.0.1 -P 3309
-- 检查数据
SELECT * FROM cluster_test.test_data;
```
#### 4.3 检查集群状态
```javascript
// 在 MySQL Shell 中执行
cluster = dba.getCluster()
cluster.status()
// 预期输出:
{
"clusterName": "myCluster",
"defaultReplicaSet": {
"name": "default",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"mysql-master:3306": {
"address": "mysql-master:3306",
"memberRole": "PRIMARY",
"status": "ONLINE"
},
"mysql-slave1:3306": {
"address": "mysql-slave1:3306",
"memberRole": "SECONDARY",
"status": "ONLINE"
},
"mysql-slave2:3306": {
"address": "mysql-slave2:3306",
"memberRole": "SECONDARY",
"status": "ONLINE"
}
}
}
}
```
---
### 关键配置说明:
1. **网络配置**:
- 使用 `--net` 创建专用网络
- `--hostname` 解决容器名称解析问题
- 端口映射:外部端口与容器内部端口分离
2. **组复制要求**:
- 所有节点相同的 `group_replication_group_name`
- 唯一的 `server_id` (1,2,3)
- GTID 模式必须启用
- 二进制日志格式为 ROW
3. **安全实践**:
- 使用专用集群用户(非 root)
- 不同服务使用不同密码
- 生产环境应启用 SSL 加密
4. **数据持久化**:
- 使用 Docker 卷持久化数据
- 避免容器重启数据丢失
---
### 故障排除技巧:
1. **节点无法加入集群**:
```bash
# 检查错误日志
docker logs mysql-slave1
# 测试网络连通性
docker exec mysql-master ping mysql-slave1
```
2. **GTID 不一致**:
```sql
-- 在问题节点执行
RESET MASTER;
SET GLOBAL gtid_purged='';
```
3. **克隆失败**:
```sql
-- 在所有节点执行
INSTALL PLUGIN clone SONAME 'mysql_clone.so';
```
---
阅读全文
相关推荐






