🌐 使用 Docker 部署 MySQL InnoDB Cluster 高可用方案(带 Router 和持久数据)
🧱 使用 Docker 在四台服务器上部署 MySQL InnoDB Cluster + Router 高可用集群
🖥️ 节点规划
服务器 | 角色 | IP地址 | 容器名称 | MySQL 端口 | Router 端口 |
---|---|---|---|---|---|
A | MySQL 节点A | 192.168.0.101 | mysql1 | 3306 33061 | 无 |
B | MySQL 节点B | 192.168.0.102 | mysql2 | 3306 33061 | 无 |
C | MySQL 节点C | 192.168.0.103 | mysql3 | 3306 33061 | 无 |
D | Router | 192.168.0.104 | mysqlrouter | 无 | 6446 (写) / 6447 (读) |
🔧 每台 MySQL 节点配置(A/B/C)
- 创建目录结构(以 A 节点为例)
mkdir -p /usr/local/mysql/data
vim /usr/local/mysql/my.cnf
- 配置
my.cnf
[mysqld]
# ========== 插件配置 ==========
# 组复制插件加载(官方镜像已内置 recovery 功能,无需单独加载)
plugin_load_add=group_replication.so
# ========== 组复制核心配置 ==========
# 松散参数前缀确保兼容性(服务启动时不验证参数有效性)
loose-group_replication_group_name="7801cdc9-fc1c-4c1d-bf0b-88d2a35c7d8c" # 集群唯一标识UUID
loose-group_replication_group_seeds="192.168.0.101:33061,192.168.0.102:33061,192.168.0.103:33061" # 集群成员地址
loose-group_replication_local_address="192.168.0.101:33061" # 当前节点通信地址
loose-group_replication_start_on_boot=OFF # 禁止自动启动组复制
loose-group_replication_bootstrap_group=1 # 仅首节点启动时需要设为1
# ========== 复制基础配置 ==========
# GTID 全局事务标识(现代复制架构基础)
gtid_mode=ON
enforce_gtid_consistency=ON
# 写集提取算法(组复制必需配置)
transaction_write_set_extraction=XXHASH64 # 默认使用XXHASH64算法
# ========== 实例基础配置 ==========
server_id=1 # 必须保证集群内唯一
report_host=192.168.0.101 # 供集群其他节点识别
binlog_format=ROW # 组复制强制要求ROW格式
# ========== 系统参数 ==========
port=3306
lower_case_table_names=1 # 表名大小写不敏感
datadir=/var/lib/data
innodb_file_per_table=1 # 启用独立表空间
# SQL严格模式(推荐生产环境配置)
sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION'
# 存储引擎兼容模式(仅旧系统需要)
innodb_strict_mode=0 # 禁用InnoDB严格检查
# ========== 网络与性能 ==========
max_allowed_packet=1024M # 最大网络传输包大小
max_connections=1000 # 最大客户端连接数
max_connect_errors=10 # 连接错误阈值
# ========== 二进制日志配置 ==========
log-bin=mysql-bin # 启用二进制日志
binlog_expire_logs_seconds=864000 # 日志保留周期(10天)
# ========== 字符集与存储引擎 ==========
character-set-server=utf8mb4 # 默认字符集
collation-server=utf8mb4_unicode_ci # 默认排序规则
default-storage-engine=INNODB # 默认存储引擎
⚠️ B/C 节点只需改
server_id
、report_host
、group_replication_local_address
,并删除或注释group_replication_bootstrap_group=1
- 启动容器(使用 docker-compose)
services:
mysql1:
image: mysql:8.0.42-debian
container_name: mysql1 # B/C 节点依次递增
environment:
- MYSQL_ROOT_PASSWORD=123456 # 设置 root 密码
volumes:
- /usr/local/mysql/my.cnf:/etc/mysql/my.cnf # 自定义配置文件挂载
- /usr/local/mysql/data:/var/lib/data # 数据目录挂载
- /etc/localtime:/etc/localtime:ro # 保证容器时间一致
- /usr/share/zoneinfo:/usr/share/zoneinfo:ro # 保证时区一致
ports:
- "3306:3306" # 数据库端口
- "33061:33061" # 组复制通信端口
privileged: true # 特权模式,获取更多的服务器资源
restart: always
🟢 建议:统一目录结构、配置命名与挂载路径,便于维护和批量部署。
🔄 配置 InnoDB Cluster
在任意一台节点(建议 A)中安装MySQL shell:
sudo apt update
sudo apt install mysql-shell
进入 Shell 后执行:
// 初始化当前实例,注册到 MySQL Shell
dba.configureInstance('root@192.168.0.101:3306')
// 创建集群(首次执行)
cluster = dba.createCluster('myCluster')
// 初始化其他节点
dba.configureInstance('root@192.168.0.102:3306')
dba.configureInstance('root@192.168.0.103:3306')
// 加入到集群当中
cluster.addInstance('root@192.168.0.102:3306')
cluster.addInstance('root@192.168.0.103:3306')
⚠️ 添加节点时目标实例必须可连通,并且配置无误。
初始化节点报错,可能是权限没授权,输入下方SQL语句授权并且刷新权限:
GRANT
CLONE_ADMIN,
CONNECTION_ADMIN,
CREATE USER,
EXECUTE,
FILE,
GROUP_REPLICATION_ADMIN,
PERSIST_RO_VARIABLES_ADMIN,
PROCESS,
RELOAD,
REPLICATION CLIENT,
REPLICATION SLAVE,
REPLICATION_APPLIER,
REPLICATION_SLAVE_ADMIN,
ROLE_ADMIN,
SELECT,
SHUTDOWN,
SYSTEM_VARIABLES_ADMIN
ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
🚦 部署MySQL Router(D 节点)
创建对应文件目录:
mkdir -p /usr/local/mysqlrouter
配置docker-compose文件:
services:
mysql-router:
image: mysql/mysql-router:8.0
container_name: mysql-router
user: root # 防止文件夹权限报错
environment:
MYSQL_HOST: "192.168.0.101"
MYSQL_PORT: "3306"
MYSQL_USER: "root"
MYSQL_PASSWORD: "123456"
MYSQL_INNODB_CLUSTER_MEMBERS: "3"
volumes:
- ./router-config:/tmp/mysqlrouter # 挂载配置文件目录
- ./router-data:/var/lib/mysqlrouter # 挂载数据目录
- ./router-logs:/var/log/mysqlrouter # 挂载日志目录
restart: always
network_mode: host
Router 会自动连接集群,创建两个端口:6446 写入路由、6447 只读负载均衡。
✅ 常见注意事项
- 🔴
group_replication_bootstrap_group=1
仅用于集群首次启动第一个节点 - 🟢
33061
端口仅用于节点间通信,应限制外部访问 - 🟢 每个节点
server_id
和group_replication_local_address
必须唯一 - 🟡 推荐由第一个节点提供初始数据,其它节点自动 clone
- 🟢 参数建议统一写入
my.cnf
,减少人为失误 - 🟡 遇故障可使用
RESET PERSIST
清除持久化参数后重新配置
✅ Navicat链接测试
Navicat连接集群需要在SSL配置那勾选✔使用SSL
🔌 Java 应用连接示例
// 写连接(自动指向主库)
String url = "jdbc:mysql://192.168.0.104:6446/yourdb?serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url, "root", "rootpwd");
// 读连接(负载均衡从库)
String readUrl = "jdbc:mysql://192.168.0.104:6447/yourdb?serverTimezone=UTC";
✅ 常见注意事项
- ✅
group_replication_bootstrap_group=1
仅限用于首次启动第一个节点,后续节点必须禁用,否则集群异常 - ✅ 建议关闭
33061
的外部访问,仅供节点间通信 - ✅ 各节点必须使用唯一的
server_id
和group_replication_local_address
- ✅ 初始数据建议由第一个节点提供,后续节点加入时会自动 clone 数据
- ✅ 配置推荐全部写入
my.cnf
,使用docker-compose
启动,避免冗余命令 - ✅ 若多次重启失败,可通过
RESET PERSIST
清理持久化配置后再尝试重新配置