Active-active replication

MySQL Group Replication Plugin是一个社区插件,它建立在 Paxos 分布式算法的实现之上,允许最多九个数据库(DB)实例配置为active/active设置。对于任何事务提交,组中的大多数 DB 实例必须就给定事务在全局事务序列中的顺序达成一致。

我们可以使用 MySQL Group Replication插件为 RDS for MySQL 设置active-active集群, 在 RDS for MySQL 数据库实例之间设置主动-主动复制,为我们的应用程序提供持续可用性。在主动-主动集群中向两个或更多数据库实例写入数据可以帮助最大化可用性并减少写入延迟。

Group Replication插件在 Amazon RDS for MySQL 8.0.35 及更高版本中可用。

有关 MySQL Group Replication的信息,请参见 MySQL 文档中的Group ReplicationGroup Replication协议

下图说明了Group Replication体系结构:

过程如下:

  1. 配置 RDS for MySQL 实例的参数组

  2. 在 RDS for MySQL 实例之间配置Active-active复制

  3. 监控Active-active复制

  4. 测试Active-active复制

    • 测试持续可用性
    • 测试实例宕机时的数据完整性

创建两个RDS实例

本节总共用到三个RDS实例,在它们之间进行Active-active复制。

先基于原来的RDS实例创建两个replica,再将它们promote成单独集群。创建read replica:

image-20240706060756195

其他选项不变,将identifier分别命名为my-instance-2my-instance-3:

image-20240706060836101

创建完成两个read replica后,分别将其promote:

image-20240706063003453

参数组

使用 MySQL8 的默认配置创建一个参数组

image-20240706062301966

命名为group-replication-pg, 选择mysql 8.0:

image-20240706062350627

创建完成后:

使用以下参数修改参数组 (group-replication-pg) 以配置 MySQL active-active复制:

aws rds modify-db-parameter-group \
    --db-parameter-group-name group-replication-pg \
    --parameters "ParameterName=binlog_format,ParameterValue=ROW,ApplyMethod=pending-reboot" \
                 "ParameterName=group_replication_group_name,ParameterValue=9510b991-99b4-11ee-8669-0a9258440a9f,ApplyMethod=pending-reboot"\
                 "ParameterName=enforce_gtid_consistency,ParameterValue=ON,ApplyMethod=pending-reboot"\
                 "ParameterName=rds.group_replication_enabled,ParameterValue=1,ApplyMethod=pending-reboot"\
                "ParameterName=rds.custom_dns_resolution,ParameterValue=1,ApplyMethod=pending-reboot"\
                 "ParameterName=gtid-mode,ParameterValue=ON,ApplyMethod=pending-reboot"\
                 "ParameterName=slave_preserve_commit_order,ParameterValue=1,ApplyMethod=pending-reboot"

为上述创建的参数组修改了以下参数:

参数名称 其他注释
binlog_format ROW binlog_format 的值设置为 ROWgroup replication正常工作的先决条件。此参数的默认值设置为 MIXED。
group_replication_group_name 11111111-2222-3333-4444-555555555555 可以将其修改为使用我们自己的 UUID。
gtid_mode ON 用于跟踪每个服务器实例上已提交的事务。这是 group replication 正常工作的先决条件。
enforce_gtid_consistency ON 这是group replication正常工作的先决条件。
rds.custom_dns_resolution 1 此参数指定是否允许从 VPC 中的 Amazon DNS 服务器进行 DNS 解析。启用组复制时,必须启用 DNS 解析
rds.group_replication_enabled 1 在集群上启用group replication功能
slave_preserve_commit_order ON 此参数是必需的,以确保在并行执行事务时在每个 DB 实例上维护正确的事务顺序

首先,我们需要获取创建的 RDS for MySQL 实例的所有endpoint,以在active-active集群中使用。

group_replication_group_seeds_list=$(aws rds describe-db-instances --output text --query 'DBInstances[].[Endpoint.Address]'|sed 's/$/:3306/'|sed ':a;N;$!ba;s/\n/\\,/g')

确认上述命令的输出,在此列表中,我们将有所有 RDS 实例endpoint,用 “,” 分隔。

echo $group_replication_group_seeds_list

image-20240706063343716

现在我们有了所有 RDS for MySQL endpoint,为了在与每个 DB 实例关联的 DB 参数组中配置参数 group_replication_group_seeds,运行以下 modify-db-parameter-group CLI 命令:

aws rds modify-db-parameter-group --db-parameter-group-name group-replication-pg --parameters ParameterName=group_replication_group_seeds,ParameterValue=$group_replication_group_seeds_list,ApplyMethod=immediate

通过使用以下查询确认所有 RDS for MySQL 实例 (rdslab-group-mysql1rdslab-group-mysql2rdslab-group-mysql3) 处于 “available” 状态:

aws rds describe-db-instances --query 'DBInstances[].[DBInstanceIdentifier,Endpoint.Address,DBInstanceStatus]'

image-20240706064852251

然后修改几个实例的DB Parameter group,使用上面新建的group-replication-pg, 并选择立即应用:

image-20240706065052196

应用完成后,将三个实例分别重启,这样新的参数组才能生效。等待几个实例全部变成可用状态:

image-20240706065241635

配置Active-active replication

在配置 RDS 实例上的active-active集群之前,让我们设置group replication用户group replication recover channel二进制日志保留

  • replication group用户 : 在 DB 实例上创建复制用户 rdsgrprepladmin 用于group replicationactive-active集群中所有 DB 实例的 rdsgrprepladmin 用户密码必须相同。rdsgrprepladmin 用户名是group replicaion连接保留的。其他用户,包括主用户,都不能使用这个用户名。

  • replication group recovery channel : 为active-active集群设置 group_replication_recovery 通道。更多信息请参见: replication channel

  • bin log保留时长 : 二进制日志保留时间参数用于指定在 DB 实例上保留bin log文件的小时数。Amazon RDS 通常会尽快清除二进制日志,因此bin log对于复制active-active集群内的更改是必需的。

确保我们在active-active集群中的所有 RDS MySQL 实例上运行这些存储过程。

打开三个终端窗口,连接到所有 RDS for MySQL 实例:

mysql -u $DBUSER -p$DBPASS -h [endpoint]

运行以下存储过程来创建group replication用户 rdsgrprepladminrdsgrprepladmin 用户是active-active集群中group replication连接的保留用户。更多信息请参考管理主动-主动集群

call mysql.rds_group_replication_create_user('groupreplication');

image-20240706070157802

创建group replication recovery channel。此存储过程为active-active集群设置 ‘group_replication_recovery’ 通道。该过程使用保留的 ‘rdsgrprepladmin’ 用户来配置通道。

call mysql.rds_group_replication_set_recovery_channel('groupreplication');

image-20240706070258691将bin log保留配置为 7 天。我们可以根据需要调整此值。

call mysql.rds_set_configuration('binlog retention hours', 168);

image-20240706070347195

通过在集群的一个 RDS for MySQL 实例上运行以下存储过程来启动集群。该语句在集群的一个 DB 实例上启动group replication。将存储过程 rds_group_replication_start 的参数值设置为 1,表示我们正在引导集群。

确保我们只在主动-主动集群中的一个 RDS MySQL 实例上运行这些存储过程。例如: 我们可以在 DB 实例(rdslab-group-mysql1)上引导集群。

运行此命令来初始化复制组(仅在一个实例上运行一次)。此示例在 mysql.rds_group_replication_start 存储过程中指定 1 来初始化一个新group,其中包含当前的 DB 实例。

call mysql.rds_group_replication_start(1);

确认组复制已在该实例上成功启动。

image-20240706070648508

现在,通过在集群的其余 RDS for MySQL 实例上运行存储过程 rds_group_replication_start,并将参数值设置为 0,来启动组复制。

call mysql.rds_group_replication_start(0);

确保我们在主动-主动集群中的其他两个 RDS for MySQL 实例上运行这些存储过程。

确认以下输出:

image-20240706070902221