文档首页/ 弹性云服务器 ECS/ 最佳实践/ MySQL InnoDB Cluster高可用实践
更新时间:2025-08-27 GMT+08:00
分享

MySQL InnoDB Cluster高可用实践

读写分离是一种常见的数据库优化技术,通过将读操作和写操作分别路由到不同的数据库实例,可以显著提升系统的数据吞吐性能,提高数据库服务性能,避免业务系统因单点故障导致不可用。可以通过多台弹性云服务器搭建高可用数据库集群,利用代理服务实现灵活调度和读写分离。

背景介绍

在搭建MySQL服务集群时使用多个可用区的弹性云服务器,可以降低单可用区内节点故障时业务中断的风险。本文用4台弹性云服务器搭建MySQL高可用数据库集群,其中1台作为代理节点,1台作为主节点(配置读写权限),2台作为备节点(配置只读权限)。

前提条件

  • 购买4台弹性云服务器(以Huawei Cloud EulerOS 2.0操作系统为例),归属于同一个VPC下,其中代理节点、主节点、备节点分属三个子网。且4台云服务器都需要绑定弹性公网IP。
  • 1台MySQL主节点和2台MySQL备节点需要安装MySQL服务,且版本一致,若未安装MySQL,可参考数据库部署概述

操作步骤

  1. 设置集群节点。

    1. 远程连接MySQL主节点、MySQL备节点,参考Linux ECS登录方式概述
    2. 为三台MySQL节点创建一个用于集群通信的MySQL用户,用户名和密码应一致。

      密码建议设置高强度密码,即长度大于8个字符,且包含大小写字符、数字、特殊字符。

      #执行后需要输入root用户密码
      sudo mysql -uroot -p \
      -e "CREATE USER '<username>'@'%' IDENTIFIED BY '<password>';" \
      -e "GRANT ALL PRIVILEGES ON *.* TO '<username>'@'%' WITH GRANT OPTION;" \
      -e "FLUSH PRIVILEGES;"
    3. 在三台MySQL节点的MySQL配置文件/etc/my.cnf中添加如下内容,其中server_id的值需要注意每个节点配置一个不同的值。
      #设置主机名为节点的IP地址
      report_host=192.168.x.x
      #开启GTID强一致性
      enforce_gtid_consistency=ON
      gtid_mode=ON
      #设置节点服务ID,此值需要每个节点唯一正整数
      server_id=1
      #设置每个节点最大连接数,需要确保每个节点值统一
      max_connections=1024
      #禁用InnoDB以外的存储引擎
      disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
    4. 重启三台MySQL节点的MySQL服务,使配置生效。
      sudo systemctl restart mysqld

  2. 创建集群。

    1. 远程连接代理节点,参考Linux ECS登录方式概述
    2. 为代理节点安装mysql-shell、mysql-router。
      #添加MySQL官方源
      sudo rpm -Uvh https://repo.mysql.com/mysql84-community-release-el8-1.noarch.rpm
      #安装mysql-shell、mysql-router
      sudo dnf install -y mysql-shell mysql-router mysql-community-client
    3. 通过MySQL Shell连接到MySQL主节点,将username替换为MySQL的用户名,IP替换为主节点的IP地址,执行后输入密码,并询问是否需要保存密码,保存后无需再次输入密码。
      mysqlsh --js <username>@<IP>:3306

    4. 执行以下命令,对MySQL节点进行初始化配置,<username>和<IP>分别替换为节点的MySQL用户名和IP地址,每个MySQL节点都需要执行一遍。
      dba.configureInstance('<username>@<IP>:3306')

    5. 检查节点是否可加入cluster,<username>和<IP>分别替换为节点的MySQL用户名和IP地址。
      dba.checkInstanceConfiguration('<username>@<IP>:3306')

      可加入时回显如下,status提示ok。

    6. 创建集群,自定义集群名称替换cluster_name后执行。
      var cluster = dba.createCluster('<cluster_name>')
    7. 为集群添加从节点,username替换为MySQL的用户名,IP替换为不同的从节点IP地址,每个从节点都需要添加一遍,recovery method默认选择Clone。
      cluster.addInstance('<username>@<IP>:3306')

      输出信息如下,表示添加成功。

    8. 查看集群状态。
      cluster.status()

      输出信息如下,表示集群创建完成。

    9. 配置完成后可以输入\q退出mysqlsh程序。

  3. 设置代理节点。

    1. 远程连接代理节点,参考Linux ECS登录方式概述
    2. 执行命令初始化地理设置,将username替换为MySQL的用户名,IP替换为主节点的IP地址,执行后输入密码。
      sudo mysqlrouter --bootstrap <username>@<IP>:3306 --directory /mnt/mysqlrouter \
      --conf-bind-address 0.0.0.0 --user=mysqlrouter

    3. 编辑mysqlrouter服务文件。

      /mnt/mysqlrouter是默认目录,若修改了目录,需要同步修改ExecStart和ExecStop路径。

      sudo tee /usr/lib/systemd/system/mysqlrouter.service <<-'EOF'
      [Unit]
      Description=MySQL Router Service
      After=network.target
       
      [Service]
      User=mysqlrouter
      Group=mysqlrouter
      Type=forking
      ExecStart=/mnt/mysqlrouter/start.sh
      ExecStop=/mnt/mysqlrouter/stop.sh
      Restart=on-failure
      StandardOutput=journal
       
      [Install]
      WantedBy=multi-user.target
      EOF
    4. 执行命令启动服务。
      #刷新服务文件
      sudo systemctl daemon-reload
      #启动mysqlrouter
      sudo systemctl start mysqlrouter.service
      #设置mysqlrouter开机自启
      sudo systemctl enable mysqlrouter.service
      #查看服务状态
      sudo systemctl status mysqlrouter.service

  4. (可选)验证集群。

    模拟MySQL主节点故障,验证集群是否能够自动切换节点提供服务。
    1. 远程连接代理节点,参考Linux ECS登录方式概述
    2. 使用MySQL客户端连接到代理节点,<username>替换为MySQL的用户名,执行后输入MySQL密码。
      mysql -h127.0.0.1 -P6450 -u<username> -p
    3. 执行sql语句查看集群状态,结果显示3个节点在线,其中一个是主节点。
      SELECT * FROM performance_schema.replication_group_members;

    4. 执行SQL语句添加测试库和测试表。
      -- 1. 创建数据库
      CREATE DATABASE test_db;
       
      -- 2. 使用数据库
      USE test_db;
       
      -- 3. 创建表:test_table
      CREATE TABLE test_table (
          id INT AUTO_INCREMENT PRIMARY KEY, -- 自增主键
          name VARCHAR(100) NOT NULL,        -- 名称
          age INT NOT NULL
      );
       
      -- 4. 添加记录到 test_table
      INSERT INTO test_table (name, age) VALUES
      ('A', 5),
      ('B', 25);
       
      -- 5. 查看添加到test_table的信息(可选)
      select * from test_table;

    5. 停止MySQL主节点,模拟宕机事件。

    6. 等待MySQL主节点停止后,再次执行SQL语句查看集群状态,发现两个节点在线,且从节点已自动切换为主节点。
      SELECT * FROM performance_schema.replication_group_members;

    7. 执行SQL语句查询数据查看是否有丢失数据。
      select * from test_table;

    8. 启动MySQL主节点模拟宕机恢复。
    9. 执行SQL语句查看集群状态,结果显示三个节点在线,且主节点自动加入集群。
      SELECT * FROM performance_schema.replication_group_members;

  5. (可选)集群添加节点。

    在MySQL集群中,需要扩展集群或应对节点宕机时,可通过mysql-shell连接集群并使用addInstance命令添加新节点,新节点会自动同步数据。

    • 集群节点宕机过半会导致集群不可用,建议节点总数为单数以确保可用性。
    • 待加入集群的节点在扩容前需重复步骤1中设置集群节点的2、3、4步。
    1. 远程连接代理节点,参考Linux ECS登录方式概述
    2. 通过mysql-shell连接到集群中任意节点,使用MySQL客户端连接到代理节点,<username>替换为MySQL的用户名,<IP>替换为节点IP地址,执行后输入MySQL密码。
      mysqlsh --js <username>@<IP>:3306

    3. 获取集群。
      var cluster = dba.getCluster()
    4. 为集群添加节点,将<username>替换为MySQL用户名,<IP>替换为节点IP地址。
      cluster = dba.addInstance('<username>@<IP>:3306')

      通过以下命令查看cluster情况,可以观察到新扩容的节点情况。

      cluster.status()

      如需移出节点,可使用以下命令,根据将<username>和<IP>替换为需要移出的节点信息。

      cluster.removeInstance('<username>@<IP>:3306')

      回显类似如下信息。

  6. (可选)指定集群主节点。

    在MySQL集群中,若主节点宕机,系统会自动从剩下的从节点中选举出新的主节点,如需手动指定主节点,可以通过mysql-shell连接集群,使用setPrimaryInstance命令设置主节点。

    1. 远程连接代理节点,参考Linux ECS登录方式概述
    2. 通过mysql-shell连接到集群中任意节点,使用MySQL客户端连接到代理节点,<username>替换为MySQL的用户名,<IP>替换为节点IP地址,执行后输入MySQL密码。
      mysqlsh --js <username>@<IP>:3306

    3. 获取集群。
      var cluster = dba.getCluster()
    4. 为集群设置目标主节点,将<username>替换为MySQL用户名,<IP>替换为节点IP地址。
      cluster.setPrimaryInstance ('<username>@<IP>:3306')

      回显如下类似信息,表示设置成功。

相关文档