MySQL InnoDB Cluster高可用实践

更新时间:2025-04-15 07:40:23

单台MySQL数据库服务存在性能限制和单点故障风险,可能导致业务系统不可用。您可以通过多台ECS实例搭建MySQL InnoDB Cluster高可用数据库集群,并利用代理服务实现灵活调度和读写分离,提升数据库的可用性和容错能力。

架构说明

在搭建服务集群时使用多个可用区ECS服务器,可以降低单可用区内机器发生故障时的业务停机风险,增强业务系统的稳定性。

  • 代理节点:负责处理客户端请求,并将其转发到合适的数据库节点。这些代理节点同样可以部署在多个可用区内,进一步提升高可用性。

  • 主节点:作为集群中的核心数据处理节点,处理所有的写入操作并将数据同步给其他节点。

  • 从节点:通过复制主节点的数据保持一致性,仅支持只读操作。一旦主节点出现故障,从节点将自动进行新主节点的选举,保证集群的持续运行。

image

环境准备

  1. 创建4ECS实例,本文示例操作系统为Alibaba Cloud Linux 3。

    说明

    实例

    公网访问

    VPC

    虚拟交换机(vSwitch)

    IP地址

    说明

    实例

    公网访问

    VPC

    虚拟交换机(vSwitch)

    IP地址

    代理节点

    ECS A

    需要开通公网访问。

    安装完成后,可关闭公网访问以提升安全性。

    192.168.0.0/16

    192.168.0.0/24

    192.168.0.1

    主节点(读写)

    ECS B

    192.168.1.0/24

    192.168.1.1

    从节点(只读)

    ECS C

    192.168.2.0/24

    192.168.2.1

    从节点(只读)

    ECS D

    192.168.2.2

  2. ECS B、ECS C、ECS D安装 MySQL 服务,确保所有实例的MySQL版本一致,本文示例使用的是MySQL 8.4。如果您不了解如何安装,请参考手动部署MySQL数据库(Linux)

操作步骤

步骤一:设置集群节点

  1. 远程连接ECS B、ECS C、ECS D实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. ECS B、ECS C、ECS D创建一个用于集群通信的MySQL用户,用户名和密码需保持一致。

    重要
    • 请将代码中的<username>替换为创建MySQL用户的用户名。

    • 请将代码中的<password>替换为创建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. ECS B、ECS CECS DMySQL配置文件/etc/my.cnf中添加以下内容。

    #设置主机名为节点的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. 重启ECS B、ECS CECS DMySQL服务,使配置修改生效。

    sudo systemctl restart mysqld

步骤二:创建集群

  1. 远程连接ECS A实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. ECS A安装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连接到主节点,请将<username>替换为MySQL的用户名,<IP>替换为主节点IP地址,执行后需要输入密码,并且询问您是否保存密码,保存密码后再次连接无需输入密码。

    mysqlsh --js <username>@<IP>:3306

    image

  4. 创建集群,您需要修改<cluster_name>为集群名称。

    var cluster = dba.createCluster('<cluster_name>');
  5. 为集群添加从节点,请将<username>替换为MySQL的用户名,<IP>替换为从节点IP地址。您需要为每个从节点都执行添加动作。

    说明

    例如,若要添加节点地址为192.168.2.1,用户为cluster_user,则命令为:cluster.addInstance('cluster_user@192.168.2.1:3306');

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

    输出如下信息,表示从节点添加成功。image

  6. 查看集群状态。

    cluster.status();

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

步骤三:设置代理节点

  1. 远程连接ECS A实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. 执行命令初始化代理设置,请将<username>替换为MySQL的用户名,<IP>替换为主节点IP地址,执行后您需要输入MySQL用户的密码。

    说明

    命令默认将初始化文件存储到目录/mnt/mysqlrouter下。

    sudo mysqlrouter --bootstrap <username>@<IP>:3306 --directory /mnt/mysqlrouter \
    --conf-bind-address 0.0.0.0 --user=mysqlrouter
  3. 编辑mysqlrouter服务文件。

    说明

    命令默认使用目录/mnt/mysqlrouter,如果您修改了目录,需要修改ExecStartExecStop路径。

    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

验证集群

通过停止主节点(ECS B)模拟故障,验证集群能否自动切换节点并继续提供服务。

  1. 远程连接ECS A实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. 使用MySQL客户端连接到代理节点(ECS A),请将<username>替换为MySQL的用户名。

    mysql -h127.0.0.1 -P6450 -u<username> -p
  3. 执行SQL语句查看集群状态,结果显示三个节点在线,其中一个节点担任主节点。

    SELECT * FROM performance_schema.replication_group_members;

    image

  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,        -- 名称
        value DECIMAL(10, 2) NOT NULL
    );
    
    -- 4. 添加记录到 test_table
    INSERT INTO test_table (name, value) VALUES
    ('Item A', 100.50),
    ('Item B', 200.75);
  5. 停止主节点(ECS B)实例模拟宕机事件。

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

    SELECT * FROM performance_schema.replication_group_members;

    image

  7. 执行SQL语句查询数据查看是否有丢失数据。

    SELECT * FROM test_table;
  8. 启动主节点(ECS B)实例模拟宕机恢复。

  9. 执行SQL语句查看集群状态,结果显示三个节点在线,其中ECS B自动加入集群。

    SELECT * FROM performance_schema.replication_group_members;

    image

集群添加节点

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

重要
  • 当集群的节点宕机数量超过半数,会导致集群不可用,建议节点数量为单数以确保可用性。

  • 在节点加入集群前,您需要完成安装MySQL并按照步骤一:设置集群节点中的第2、3、4步设置集群节点。

  1. 远程连接ECS A实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. 通过MySQL Shell连接到集群中任意节点,请将<username>替换为MySQL的用户名,<IP>替换为节点IP地址,执行后需要输入密码,并且询问您是否保存密码,保存密码后再次连接无需输入密码。

    mysqlsh --js <username>@<IP>:3306
  3. 获取集群。

    var cluster = dba.getCluster();
  4. 为集群添加节点,请将<username>替换为MySQL的用户名,<IP>替换为节点IP地址。

    说明

    例如,若要添加节点地址为192.168.2.1,用户为cluster_user,则命令为:cluster.addInstance('cluster_user@192.168.2.1:3306');

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

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

指定集群主节点

MySQL InnoDB Cluster中,如果主节点宕机,系统会自动从剩余节点中选举出新的主节点。若需要手动指定主节点,可通过MySQL Shell连接集群,并使用setPrimaryInstance命令来设置目标主节点。

  1. 远程连接ECS A实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

  2. 通过MySQL Shell连接到集群中任意节点,请将<username>替换为MySQL的用户名,<IP>替换为节点IP地址,执行后需要输入密码,并且询问您是否保存密码,保存密码后再次连接无需输入密码。

    mysqlsh --js <username>@<IP>:3306
  3. 获取集群。

    var cluster = dba.getCluster();
  4. 为集群设置目标主节点,请将<username>替换为MySQL的用户名,<IP>替换为节点IP地址。

    说明

    例如,若要设置节点地址为192.168.2.1,用户为cluster_user,则命令为:cluster.setPrimaryInstance('cluster_user@192.168.2.1:3306');

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

    输出如下信息,表示节点设置成功。image

相关文档

  • 有关MySQL InnoDB Cluster更多信息,请参见MySQL官方文档

  • 推荐使用云数据库 RDS服务,简化部署和管理复杂性,更多信息,请参见什么是RDS MySQL

  • 对集群服务进行实时监控,包括CPU、内存、磁盘I/O、网络流量等指标,及时发现并处理异常,更多信息,请参见什么是云监控

  • 本页导读 (1)
  • 架构说明
  • 环境准备
  • 操作步骤
  • 步骤一:设置集群节点
  • 步骤二:创建集群
  • 步骤三:设置代理节点
  • 验证集群
  • 集群添加节点
  • 指定集群主节点
  • 相关文档
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等