环境准备:

docker和docker-compose已安装

第一步:编写docker-compose.yml

version: '3.8'

# 提取公共配置,保持代码优雅
x-mysql-common: &mysql-common
  image: mysql:8.0
  restart: always  
  environment:
    MYSQL_ROOT_PASSWORD: Root_Password123!
    MYSQL_ROOT_HOST: '%'

services:
  mysql1:
    <<: *mysql-common
    container_name: mysql1
    hostname: mysql1
    command: ["mysqld", "--server-id=1", "--gtid-mode=ON", "--enforce-gtid-consistency=ON", "--binlog-format=ROW", "--transaction-write-set-extraction=XXHASH64", "--binlog-transaction-dependency-tracking=WRITESET"]
    networks:
      - cluster_net

  mysql2:
    <<: *mysql-common
    container_name: mysql2
    hostname: mysql2
    command: ["mysqld", "--server-id=2", "--gtid-mode=ON", "--enforce-gtid-consistency=ON", "--binlog-format=ROW", "--transaction-write-set-extraction=XXHASH64", "--binlog-transaction-dependency-tracking=WRITESET"]
    networks:
      - cluster_net

  mysql3:
    <<: *mysql-common
    container_name: mysql3
    hostname: mysql3
    command: ["mysqld", "--server-id=3", "--gtid-mode=ON", "--enforce-gtid-consistency=ON", "--binlog-format=ROW", "--transaction-write-set-extraction=XXHASH64", "--binlog-transaction-dependency-tracking=WRITESET"]
    networks:
      - cluster_net

  mysql-router:
    image: mysql/mysql-router:8.0
    container_name: mysql-router
    hostname: mysql-router
    restart: always
    depends_on:
      - mysql1
      - mysql2
      - mysql3
    environment:
      MYSQL_HOST: mysql1
      MYSQL_PORT: 3306
      MYSQL_USER: root
      MYSQL_PASSWORD: Root_Password123!
      MYSQL_INNODB_CLUSTER_MEMBERS: 3
    ports:
      - "6446:6446" # 读写分离:写端口 (永远指向 Primary 节点)
      - "6447:6447" # 读写分离:读端口 (轮询指向 Secondary 节点)
    networks:
      - cluster_net

networks:
  cluster_net:
    driver: bridge

第二步:一键拉起 MySQL 基础节点

docker-compose.yml 所在的目录打开终端,先只启动 3 个 MySQL 节点(暂时不启动 Router,等集群建好再启):

docker-compose up -d mysql1 mysql2 mysql3

第三步:使用 MySQL Shell 一气呵成建集群

这里我们直接拉起一个一次性的 MySQL Shell 容器来执行操作。

1. 进入交互界面:

docker run -it --network mysql-cluster_cluster_net --rm mysql/mysql-server:8.0 mysqlsh root@mysql1:3306 -pRoot_Password123!

注意:请确保 --network 后面的网络名正确,通常是 当前目录名_cluster_net

2. 在 JS 终端中,依次执行以下命令:

// 1. 创建集群
var cluster = dba.createCluster('myCluster');

// 2. 加入 mysql2(强制指定 clone 模式)
cluster.addInstance('root@mysql2:3306', {password: 'Root_Password123!', recoveryMethod: 'clone'});

// 3. 加入 mysql3
cluster.addInstance('root@mysql3:3306', {password: 'Root_Password123!', recoveryMethod: 'clone'});

// 4. 查看集群完美状态
cluster.status();

看到三个节点全绿 ONLINE,输入 \q 退出

第四步:启动流量大管家 MySQL Router

集群建立完毕,启动 Router 代理层:

docker-compose up -d mysql-router

第五步:客户端连接与“拔网线”测试

  • 打开 Windows 上的 Navicat。

  • 新建 MySQL 连接:

    • 主机: localhost (如果在虚拟机跑 Docker,填虚拟机 IP)

    • 端口: 6446 (千万别填 3306)

    • 用户名/密码: root / Root_Password123!

        点击确定,双击连接,成功连入

如果报错了

修改 MySQL 服务器的密码加密策略

进入主库容器

docker exec -it mysql1 mysql -uroot -pRoot_Password123!

在 MySQL 命令行中执行以下两条 SQL 把密码加密方式改回老版本:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Root_Password123!';
FLUSH PRIVILEGES;

在 Navicat 里建个库,插条数据。然后去终端把主库干掉:

关闭主库

docker stop mysql1

创建表没有问题

回到 Navicat,刷新一下或者继续写数据,你会发现业务毫无波澜,Router 已经把你的 SQL 悄悄送到了 mysql2mysql3 的手中。

去连接 还在运行的节点

# 连接到存活的 mysql2
docker run -it --network mysql-cluster_cluster_net --rm mysql/mysql-server:8.0 mysqlsh root@mysql2:3306 -pRoot_Password123!

进入后再次执行:

var cluster = dba.getCluster();
cluster.status();

可以看到mysql3"memberRole": "PRIMARY",说明mysql3成为了新的主库

更多推荐