🌐 使用 Docker 部署 MySQL InnoDB Cluster 高可用方案(带 Router 和持久数据)

  • 🧱 使用 Docker 在四台服务器上部署 MySQL InnoDB Cluster + Router 高可用集群

    🖥️ 节点规划

    基础配置,安装docker,配置hosts解析就不进行演示了,但是这个很重要必须进行配置

    服务器 角色 主机名 IP地址 容器名称 MySQL 端口 Router 端口
    A MySQL 节点A master 192.168.0.101 mysql1 3306 33061
    B MySQL 节点B node1 192.168.0.102 mysql2 3306 33061
    C MySQL 节点C node2 192.168.0.103 mysql3 3306 33061
    D Router 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:33060,192.168.0.102:33060,192.168.0.103:33060"  # 集群成员地址
    loose-group_replication_local_address="192.168.0.101:33060"  # 当前节点通信地址
    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算法
    
    # 让错误日志输出到 Docker 可捕获的 stderr
    log-error=/var/lib/data/stderr
    
    # ========== 实例基础配置 ==========
    server_id=1                                # 必须保证集群内唯一
    report_host=192.168.0.101                  # 供集群其他节点识别
    binlog_format=ROW                          # 组复制强制要求ROW格式
    
    # ========== 系统参数 ==========
    port=3006
    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_0900_ai_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 节点依次递增
        #cap_add:
        #  - SYS_ADMIN
        security_opt:
          - seccomp:unconfined
        environment:
          - TZ=Asia/Shanghai
          - 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    # 保证时区一致
          - /etc/hosts:/etc/hosts:ro
        #ports:
        #  - "3306:3306"   # 数据库端口
        #  - "33060:33060" # 组复制通信端口
        # privileged: true  # 特权模式,获取更多的服务器资源
        restart: always
        network_mode: host
    

    🟢 建议:统一目录结构、配置命名与挂载路径,便于维护和批量部署。

    🔄 配置 InnoDB Cluster

    在任意一台节点(建议 A)中安装MySQL shell:

    sudo apt update
    sudo apt install mysql-shell
    

    执行mysqlsh命令登录数据库进行操作

    sudo mysqlsh root@192.168.0.101:3006
    

    进入 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 # 挂载日志目录
          - /etc/hosts:/etc/hosts:ro
        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 仅限用于首次启动第一个节点,后续节点必须禁用,否则集群异常
    • ✅ 建议关闭 33060 的外部访问,仅供节点间通信
    • ✅ 各节点必须使用唯一的 server_idgroup_replication_local_address
    • ✅ 初始数据建议由第一个节点提供,后续节点加入时会自动 clone 数据
    • ✅ 配置推荐全部写入 my.cnf,使用 docker-compose 启动,避免冗余命令
    • ✅ 若多次重启失败,可通过 RESET PERSIST 清理持久化配置后再尝试重新配置
posted @ 2025-04-28 14:21  wandereryjh  阅读(532)  评论(2)    收藏  举报