亚马逊AWS官方博客

如何对 Amazon 关系数据库服务进行分片

Original URL: https://amazonaws-china.com/cn/blogs/database/sharding-with-amazon-relational-database-service/

分片(也被称为横向分区)是关系数据库领域一种颇为流行的横向扩展方法。Amazon Relational Database Service(关系数据库服务,简称Amazon RDS)是一项托管关系数据库服务,凭借出色的功能帮助用户轻松在云环境下实现分片。在本文中,我们将了解如何利用Amazon RDS实现分片数据库架构,进而实现数据存储的高扩展性、高可用性以及更强的容错能力。我们还将具体探讨在部署Amazon RDS数据库分片时,需要注意的架构设计与监控指标。此外,我们也将涉及重新分片过程中出现的难题,同时重点介绍Amazon RDS中提供的快速纵向与横向规模扩展解决方案。

分片数据库架构

分片技术的实质,在于将数据拆分成多个较小子集,进而分布于多个在物理层面相互分离的数据库服务器之上。其中每个服务器皆被称为数据库分片。各数据库分片往往具有相同的硬件、数据库引擎与数据结构类型,旨在保持彼此相近的性能水平。但是,各分片之间并不知晓对方的存在,这也是分片技术与其他横向扩展方法(例如数据库集群或复制)的核心差异所在。

非共享模式为分片数据库架构带来了独特的可扩展性与容错能力优势。在这种模式下,我们不必分神于各数据库成员之间的通信与争用,从而摆脱了由此带来的复杂性与操作开销。如果某一数据库分片遭遇硬件故障或者进行故障转移,因为该单一故障点(或称减速点)与其他分片保持物理隔离,所以其他分片不会受到任何影响。分片技术在理论上能够灵活掌控任意多个数据库服务器,唯一的前提就是驻留在应用层中的数据映射与路由逻辑不会产生无法接受的延迟。

然而,非共享模式也给分片机制带来不少难以克服的缺点:散布在不同数据库分片上的数据彼此分离。负责从多个数据库分片上读取或者联接数据的查询必须经过精心设计。与单分片运行场景相比,多数据库分片往往会带来更高的延迟。此外,无法为全体数据提供统一的全局视角也极大限制了分片数据库架构在联机分析处理(OLAP)环境中的作用。因为在这类环境中,我们往往需要对整个数据集执行数据分析功能。

不过在联机事务处理(OLTP)环境中,超大规模的写入操作或事务处理可能超出单一数据库的容量上限,并严重影响到系统的可扩展能力,这时候分片技术的优势将得到充分体现。随着Amazon RDS的问世,数据库设置与运营工作已经在很大程度上实现了自动化。换言之,分片数据库架构的使用门槛得以显著降低。Amazon RDS提供一组数据引擎选项,具体包括Amazon RDS for MySQL、 MariaDB、 PostgreSQL、 Oracle、 SQL Server以及 Amazon Aurora等等。您可以从中任意选择,并将其作为分片数据库架构中的分片构建单元。

下面,我们将通过示例了解如何使用Amazon RDS构建分片数据库架构。在AWS云计算环境中,数据流路径的具体位置具有以下几项特征(如下图所示)。

  • 数据通过托管在一组Amazon EC2实例(带有Auto Scaling功能)上的Web应用程序输入至系统当中。
  • 数据存储是分层的,其中OLTP环境与OLAP环境彼此独立,从而满足不同类型的业务与所有权要求。
  • OLTP环境使用数据库分片。整个环境由一组使用Amazon RDS构建的数据库组成,可凭借高度可扩展性满足用户对写入吞吐量的增长需求。各个数据库分片皆由具备多可用区部署功能的独立数据库进行构建,旨在实现高可用性。注意:如果您选择使用Aurora数据库集群构建数据库分片,还可以使用主实例配置读取副本以实现高可用性。
  • 根据规划将数据从OLTP环境中导出至OLAP环境。您可以使用Amazon Redshift承载来自所有数据库分片的数据,并针对数据分析功能构建起具备时间一致性的全局数据集。聚合而成的数据结果集将被进一步推送至Amazon S3以实现数据共享,供其他分析服务使用并保持长期存储。

数据分区与schema设计

实现分片数据库架构的前提条件,是对数据进行横向分区并在各数据库分片之间发布这些数据分区。您可以使用多种策略对表进行分区,例如列表分区、范围分区或者哈希分区等等。您也可以在各个数据库分片内以独立表的形式容纳一个或者多个表分区。

下图所示,为 Invoice表中以customer_id为分区键进行的横向分区示例。

当涉及多个表并绑定有外键关系时,我们可以在所有相关表上使用相同的分区键以实现横向分区。跨越多个表、但归属于同一个分区键的数据将被分配给同一个数据库分片。下图所示,为一组表内的横向分区示例。

其中使用的基本设计方法如下:

  • 每个数据库分片都包含一个分区键映射表,即customer,用于存储驻留在该分片上的分区键。应用程序从所有分片中读取此表,借此构建负责将分区键映射至数据库分片的数据映射逻辑。有时候,应用程序也可以使用预定义的算法来确定分区键具体位于哪个数据库分片中,这时也可以省略掉分区键映射表。
  • 示例中的分区键为 customer_id,它将被添加至所有表内作为数据隔离点。分区键直接影响到系统如何将数据及工作负载分配至不同的数据库分片。指向单一分区的查询将包含此分区键,以便应用层内的数据跌幅逻辑能够利用分区键映射至正确的数据库分片并正确对查询进行路由。
  • 主键在所有数据库分片中皆具有唯一的键值,以避免在将数据从一个分片迁移至另一分片、或在OLAP环境中合并数据时发生键冲突。例如,Invoice表中的主键invoice_id使用交错的数字,并为shard_id保留了最后两位数字。另一种常见的作法是使用GUID或者UUUID作为主键。
  • 可以在表中将带有时间戳数据类型的列定义为数据一致性点。在必要时,数据一致性点可被用作将数据库分片内数据合并至全局视图时的条件。例如,在将数据提取至OLAP环境中时,Invoice表中的creation_date将负责提取查询中的过滤条件,从而为所有分片指定统一的时间范围。

经过良好设计的分片数据库架构可使数据与工作负载均匀分布在所有数据库分片之上。而指向不同分片的查询,也应始终能够达到预期的性能水平。需要注意的是,分片上的数据分区越多,数据库引擎的资源消耗量也将随之提升,甚至在大规模硬件上造成资源争用与性能瓶颈。要确定在各个分片上使用多少个数据分区,我们通常需要在优化查询性能与合并目标之间寻找平衡,从而更好地利用资源、削减成本。

在将Amazon RDS部署为数据库分片时,大家还需要考虑到数据库引擎类型、数据库实例类以及RDS存储等要素。为了帮助用户轻松管理数据库配置,Amazon RDS提供一个数据库参数组,其中包含的一组配置值能够以一致性方式全面应用于所有数据库分片。

可扩展性监控

在全局情况下,您可以将对各个分片进行比较,从而验证系统当中是否存在热点。以此为背景,关注单一分片中的指标(例如系统资源使用量或数据库吞吐量)往往比较重要。此外,大家还应为监控数据设置适当的保留期。最后,您可以使用历史信息来分析系统变化趋势并规划容量,保证系统能够持续适应新的需求。

作为一项托管服务,Amazon RDS会自动收集监控数据并将其发布至Amazon CloudWatch。CloudWatch可提供数据库与系统层级的统一指标视图。其中一部分指标在所有数据库间通用,也有一些只适用于特定某款数据库引擎。关于监控指标的完整列表,请参阅Amazon RDS 与 Amazon Aurora说明文档。

这里,建议大家使用能够监控整体系统资源使用情况的指标,例如 CPUUtilization、 FreeableMemory、 ReadIOPS、 WriteIOPS以及 FreeStorageSpace。这些指标能帮助我们了解数据库分片上的资源使用情况是否与容量范围相符,以及还有多少增长空间。系统资源消耗量,是证明分片数据库架构是否需要进一步扩展/合并的一大重要依据。

下图所示为CloudWatch仪表板,此仪表板可为用户提供对分片数据库架构的良好可见性。它将来自所有数据库分片的实时与历史指标数据汇总到统一的视图当中。

当某一数据库分片具有较高的系统资源使用率并需要进行扩容时,我们可以选择纵向与横向两种扩展途径。Amazon RDS提供便捷的纵向扩展选项,您可以借此为数据库实例类添加更强的CPU与更大的RAM容量,或者调整数据库实例存储以获取更高的存储空间与IOPS水平。根据您所选择的不同数据库引擎或特定数据库版本,可用的实例类选项也将有所区别。建议大家通过AWS Management Console对了解这些具体可用选项。

如果您选择使用Amazon RDS for MySQL或者PostgreSQL以构建数据库分片,还可使用另一个扩展选项:迁移至Amazon Aurora数据库集群。Aurora数据库集群能够在集群存储卷上容纳多个数据库实例,借此提供比Amazon RDS数据库实例更强的性能与IOPS容量。Amazon RDS还提供一键式Aurora读取副本创建功能,大家可以借此设置复制流程,轻松将数据从Amazon RDS for MySQL或PostgreSQL数据库实例迁移至Aurora读取副本。在数据迁移完成之后,您还可以将Aurora读取副本提升为独立的Aurora数据库集群。

重新分片

所谓重新分片,就是对数据库分片进行横向扩展,也称再次分片。从广义角度看,重新分片还可以指所有对分片数据库架构进行分片数量调整的过程。此类过程包括添加新的分片,将一个分片拆分成多个分片或者将多个分片合并为一个分片。虽然各自诉求不同,但这些过程在本质上执行的是相同类型的操作:将现有数据从一个分片迁移至另一个分片。对于重新分片来说,如何在需要实时访问并更改数据的生产数据库中以最短停机时间实现数据迁移,一直是个令人头痛的问题。

Amazon RDS致力于降低重新分片的操作难度!在Amazon RDS for MySQL、MariaDB以及PostgreSQL中,Amazon RDS提供一键式横向扩展选项(读取副本),可将一个独立数据库拆分为多个新的数据库。下图所示为重新分片示例工作流,其中使用读取副本作为数据复制手段,实现了数据在不同数据库之间的迁移。

  1. 创建读取副本,用于连续从主数据库处复制数据。
  2. 主数据库将推迟写入活动,确保读取副本能够成功同步并被提升为新的独立数据库。在此期间,应用层内的映射与路由逻辑会将主数据库上多个数据分区的状态更新为只读。
  3. 修改数据映射与路由逻辑,将连接路由至新数据库。

如果大家选择使用Amazon Aurora数据库集群以构建数据库分片,则其读取副本将与主实例共享存储卷。这意味着我们无法使用其在Aurora集群之间复制数据;但与之对应,Amazon RDS提供数据库克隆功能,可利用来自源数据库的数据创建出新的Amazon Aurora数据库集群。对于Aurora MySQL数据库集群,您还可以设置MySQL复制选项,借此将数据快速复制到另一个新的Aurora MySQL数据库集群当中。

除了使用现有数据库技术进行数据复制之外,大家也可以利用其他工具在数据库分片之间迁移数据,从而实现重新分片。此类工具包括 AWS Database Migration Service (AWS DMS)或者由用户定义的数据提取流程。下图所示为基于工具的重新分片工作流示例,此工作流每次对一个数据分区执行迁移操作。

  1. 数据迁移工具将数据分区从一个数据库分片复制到另一个数据库分片。应用层内的映射与路由逻辑将数据分区的状态更新为只读。此后,数据迁移工具即可在两个数据库分片之间执行数据同步。
  2. 在数据同步完成后,应用层内的数据映射与路由逻辑将更新数据分区的映射与状态,使其在新的数据库分片上生效。

基于工具的重新分片方法更为灵活,因为每个数据分区都可以独立迁移。在迁移过程中,对应数据分区将进入只读模式,意味着应用程序仍然可以读取其数据。其他数据应用则仍然可以读取及写入,并保证整个分片数据库架构的持续可用性。

基于数据库的重新分片方法在进行数据库拆分时,会对数据库分片上多个数据分区的写入操作带来停机时间。在新数据库上线后,其中将包含来自原始数据库的所有数据分区(即使某些数据分区并不会实际使用)。因此,您需要单独消除掉其中的重复数据。

总结

在本文中,我们了解了如何使用分片这一提升关系数据库可扩展性的方法。我们探讨了如何使用Amazon RDS在云环境中实现分片数据库架构,以及如何借此实现数据存储与分析工作流。此外,我们还介绍了RDS为数据库分片提供的各种高度自动化管理、监控、纵向与横向扩展功能。

希望本文能帮助大家更深入地理解分片机制以及如何在AWS云计算环境中使用分片技术。如果您还有其他疑问,请在下方评论区中与我们交流。

 

本篇作者

Lei Zeng

AWS公司高级数据库工程师。