亚马逊AWS官方博客

保驾护航 – 实战分享,通过 External Master 完成 Amazon RDS for MySQL 加密和升级

前言

数据安全是每个数据库用户尤其是企业级用户尤其关注的方面,同时连续运营不影响业务又是对数据库的最低要求。如何能在兼顾最小停机时间同时完成安全设置的更新显得尤为重要。本文是以企业级用户,在加强安全配置同时完成 10+TB 的 Amazon RDS for MySQL 数据库的 5.7 到 8.0 升级为目标的可行性实战方案。该方案依赖于 RDS External Master 机制,使用二进制日志文件复制来设置 RDS for MySQL 数据库实例与Amazon RDS 外部的 MySQL实例之间的数据同步。

升级前置条件

在执行升级之前,该企业级用户已经完成以下工作,具体的内容我们不再展开,可以参考保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级方案中的内容:

  1. 升级前的预检

我们准备可以详细的升级预检查的流程介绍,详细请参考:《保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级前预检查 》。

  1. 创建新的参数组

创建参数组并根据原配置设置新的参数组,最大限度减少升级过程中参数不一致带来的影响。具体步骤请参考:《保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级指南》。

  1. 更新现有库、代码

您需要根据升级预检查和新版本的特性应用需要更新现有的表结构、代码等。

该企业级用户数据库概况和目标

该企业级用户的使用 Amazon RDS for MySQL 数据库,一主(Multi-AZ),7 个读副本,10+ TB 生产数据,现在已经在生产环境中成功完成升级和加密,我们总结了用户最开始的需求,主要分为运维目标和业务目标。

  • 业务目标
    • 数据库加密和大版本升级在一次业务维护公告中操作完成, 维护公告期间最多三个小时
    • 优化成本,应用性价比更高的 r6g 机型
  • 运维目标
    • 完成 Amazon RDS for MySQL 的加密
    • 完成 Amazon RDS for MySQL 的数据库集群大版本升级,即从 MySQL 5.7 到 8.0
    • 保证 10 + TB 的核心数据库不可用时间在 15 分钟以内,这个指数据库从旧实例切换成新实例最多可接受的时间
    • 升级全过程自主可控,以 5 分钟作为最大操作颗粒度(用户把每一步任务细化拆解,任何一步操作不允许超过 5 分钟)
    • 如果数据库升级失败有回退措施

解决方案

根据用户的以上目标,我们分析了现有的方案, 包括本系列中的保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级方案 ,但鉴于用户同时需要完成数据库加密,最后选择了通过 External Master 的方式一站式解决用户的问题。

整体方案如下,

  1. 通过 Amazon RDS read replica 创建快照
  2. 利用复制快照的功能,为快照加密
  3. 通过加密的快照恢复成一个新的 Amazon RDS 实例
  4. 配置现存 RDS 实例为新 RDS 实例的 External Master,进行数据的复制并检查数据同步情况
  5. 为了不再应用层面做修改,我们会为新旧集群修改名字,在这里现有集群改为 rds-old,新集群改为旧集群现有的名字,例如 rds-current

用户的真实环境有 7 台 RDS Read Replica,因为篇幅有限,我们在架构图中暂时没有画出。

具体操作步骤

为了更直观的看到操作步骤,我们拆分成三部分,第一部分是在现有数据库上需要进行的操作,第二部分是在新建数据库进行的操作,最后我们会演示新旧数据库的数据同步和切换方法。

1. 现有数据库上的操作

1.1 准备一个 Amazon RDS read replica,我们将会对这个 read replica 创建快照。在创建快照前我们先检查读副本的 replica lag,通过 SHOW SLAVE STATUS 查看 Seconds_Behinds_Master 是否为零。

1.2 在 Seconds_Behinds_Master 为零后,我们停止从 MySQL 数据库实例中进行复制。注意在这个是否为零,和用户的业务场景有很大关系,如果一直不为零的话,需要在业务低谷期停下写的操作,进行打快照,再恢复写。

1.3 同时记录下该读副本上 Relay_Master_Log_FileExec_Master_Log_Pos 的值,这个会在后面使用到。

1.4 为读副本创建快照。在导航窗格中,选择 Snapshots(快照),并且 Take snapshots(拍摄快照)。

在数据库实例列表中,选择您想拍摄快照的数据库实例,在 Snapshot name(快照名称)框中,输入快照的名称。

1.5 登录到主库上,设置 binlog retention hours 参数,以便在完成操作所需的时间内保留二进制日志。在以下示例中,binlog retention hours 设置为 24 小时:

1.6 在主库上,设置复制用户,然后向该用户授予必要的权限, 后面会使用到该用户创建 External Master。

2. 新建数据库上的操作

2.1 首先我们通过复制快照的方式, 为数据库快照加密,具体操作步骤如下图:

2.2 还原加密后的快照,这时我们可以根据原来的配置选择数据库的配置,具体可以参考恢复快照,这里不再赘述。但是有一点需要额外说明下,建议在这部选择 Multi-AZ,因为我们最开始为了节省预算没有开启,但是会有延迟加载(Lazy Loading)的情况发生,在后面的章节会展开讨论。

2.3 我们使用保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级方案 中就地升级的方案,直接将数据库版本升级到 8.0.34。在就地升级成功后,请记录下新数据库的 Endpoint。

2.4 连接到第三步新建的数据库上 ,然后通过如下命令建立到现有数据库的复制连接:

YOUR_CURRENT_DB_ENDPOINT: 现有数据库的连接

YOUR_DB_USERYOUR_PASSWORD,替换为上面第 1.6 步创建的用户名和密码。

YOUR_RELAY_MASTER_LOG_FILE 和 YOUR_EXEC_MASTER_LOG_POS:替换为上面第 1.3 步中获取的值。

CALL mysql.rds_set_external_master ( '<YOUR_CURRENT_DB_ENDPOINT>' , 3306 , '<YOUR_DB_USER>' , '<YOUR_PASSWORD>' , 'YOUR_RELAY_MASTER_LOG_FILE' , YOUR_EXEC_MASTER_LOG_POS , 0 );

2.5 设置完成后,开始复制:

2.6 如果源数据库实例和只读副本之间的连接成功,则输出如下所示:

3. 测试功能

3.1 我们会通过 sysbench 的方式在现有数据库上创建一些数据库及表进行功能测试,sysbench 的安装和使用我们不在该文档中演示。

sysbench —db-driver=mysql —mysql-user=${username} —mysql-password=${password} —mysql-db=replicatest —mysql-host=${host} —mysql-port=3306 —tables=50 —table-size=50000 —time=${run_time} —forced-shutdown —rand-type=uniform —db-ps-mode=disable —report-interval=${interval} —threads=50 /usr/local/share/sysbench/oltp_write_only.lua prepare

3.2 我们会在新的数据库实例上看 lag 信息:

3.3 当 Seconds_Behind_Master 稳定在 0 值后,数据复制已完成。

3.4 停止流量并关闭现有数据库上的连接,这是我们可以看到 Slave_IO_State 已经从 “Waiting Master to send event” 到空。

3.5 附加步骤,当我们的数据已经完成复制并且不再使用该功能,我们可以通过 mysql.rds_reset_external_master 恢复为独立数据库服务器。

3.6 在实际的操作过程中,为了尽量减少用户应用层面的修改,我们会涉及到新旧数据库名字的更改,这一部分不再赘述,可以参考:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_RenameInstance.html

用户升级和加密中的一些实践经验

我们在该用户的升级和加密中通过碰过的问题总结如下经验,希望对后面升级的用户有所帮助。

  1. 对于超大数据库的快照恢复,官方特意说明可能存在延迟加载(Lazy Loading)的可能,对此我们采用了全表扫描操作,如在常用的表上做 SELECT * ,大大提高了加载速率。建议在数据库切换前,在新建的 MySQL 8.0 的库上尽早做。
  2. 尽早开启 Multi-AZ 设置,减少延迟加载的总体时间。
  3. 如果业务对于延迟加载非常敏感,建议提前规划 8.0 集群并选择合适的实例类型做全表或者活跃表的扫描,提高加载速度的同时节省成本。
  4. 根据实际的 lag 指标配置双一参数。如果发现 8.0 集群相对于源 5.7 集群有 Lag 产生,并且有增大趋势,可以检查 8.0 集群的 innodb_flush_log_at_trx_commit 和 sync_binlog 这两个参数是否都设置为 1,”双 1 设置”适合数据安全性要求非常高,且磁盘 IO 写能力足够的情况。在出现 lag 的情况下,根据自身业务场景灵活设置这两个参数。
  5. 对于新版本的新参数特性,以及老版本的客制化配置,在 MySQL 8.0 上做充分的测试。
  6. 在我们为新旧数据库重命名的时候,观察到 MySQL 5.7 的时间比 8.0 多一点,MySQL 5.7 大约 8 分钟全部完成更名,MySQL 8.0 在 4 分钟全部完成。当然这一部分可以通过 Route53 进行相应的配置,我们的用户是尽量减少应用的修改,暂时没有使用这个功能。
  7. 鱼与熊掌虽得兼,但需要通过快照和新建一个 Amazon RDS 实例同步主库的数据,付出了额外的资源开支,也因叠加了多个可变因子(数据库加密,数据库引擎变更,实例类型更换),在操作的技术难度上,性能评估上也提出了挑战。
  8. 对于核心且运维复杂的数据库,可以选购亚马逊的企业支持计划或重点事件管理帮助用户做升级的前期规划,中期支持,后期总结。

总结

在用户升级的过程中,整个数据库生产环境切换于 15 分钟完成,在 55 分钟内完成全业务单元数据校验,提前 1 小时完成应用维护。我们观察到开启数据加密后,RDS 节点的平均 CPU 使用率略有上升,考虑到业务高峰期的 CPU 使用率仍不足 45%,且 R6g 机型带来了性价比提升,目前没有针对性能的对参数做优化。希望本篇文章中描述的方案能够给考虑 Amazon RDS for MySQL 5.7 到 8.0 的升级,数据库加密以及为了提高性价比采用 Graviton 数据库机型的用户有所帮助,欢迎阅读我们本系列的其他文章。

参考

如何以极少的停机时间对适用于 MySQL 或 MariaDB 的未加密 Amazon RDS 数据库实例进行加密

保驾护航 – Amazon RDS for MySQL 5.7 到 8.0 升级方案

系列博客

本篇作者

冯秋爽

AWS 解决方案架构师,负责跨国企业级客户基于 AWS 的技术架构设计、咨询和设计优化工作。在加入 AWS 之前曾就职于 IBM、甲骨文等 IT 企业,积累了丰富的程序开发和数据库的实践经验。

朱煜

西云数据技术客户经理,10+ 年 IT 工作经验,从事开发、架构、售前咨询等技术岗位,曾供职于微软、斯伦贝谢、AWS 等世界 500 强企业,对大数据、人工智能,以及自动驾驶行业的技术落地有多年实战经验。

马丽丽

亚马逊云科技数据库解决方案架构师,十余年数据库行业经验,先后涉猎 NoSQL 数据库 Hadoop/Hive、企业级数据库 DB2、分布式数仓 Greenplum/Apache HAWQ 以及亚马逊云原生数据库的开发和研究。