🌐 使用 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)

  1. 创建目录结构(以 A 节点为例)
mkdir -p /usr/local/mysql/data
vim /usr/local/mysql/my.cnf
  1. 配置 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_idreport_hostgroup_replication_local_address,并删除或注释 group_replication_bootstrap_group=1

  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_idgroup_replication_local_address 必须唯一
  • 🟡 推荐由第一个节点提供初始数据,其它节点自动 clone
  • 🟢 参数建议统一写入 my.cnf,减少人为失误
  • 🟡 遇故障可使用 RESET PERSIST 清除持久化参数后重新配置

✅ Navicat链接测试

image-20250428141910790

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_idgroup_replication_local_address
  • ✅ 初始数据建议由第一个节点提供,后续节点加入时会自动 clone 数据
  • ✅ 配置推荐全部写入 my.cnf,使用 docker-compose 启动,避免冗余命令
  • ✅ 若多次重启失败,可通过 RESET PERSIST 清理持久化配置后再尝试重新配置
posted @ 2025-04-28 14:21  wandereryjh  阅读(125)  评论(0)    收藏  举报