“Hi,这是我自学算力大集群相关知识的第7篇笔记。这次我们会了解Amazon Aurora在分布式架构方面的一些基础知识。其是亚马逊云服务(AWS)提供的一种高性能、高可用性且兼容 MySQL 和 PostgreSQL 的云原生关系型数据库服务。”
摘要
在Amazon提供的在线云服务中,客户可以租赁名为EC2实例的虚拟主机与配套服务。其使用场景多为MySQL、PostgreSQL相关数据库服务。
在提供面向全球用户的云服务时,若EC2实例所依赖的硬件发生崩溃或不可用,当保存有重要用户数据的磁盘发生损坏时,如何保证系统持续在线、数据完整并可用?
亚马逊至少提供了两个基本解决思路—— S3服务 与 EBS服务。
S3 提供可扩展的对象存储服务,用户可以存储和检索任何数量的数据。数据以对象的形式存储在存储桶(Bucket)中,每个对象包含数据、元数据和唯一的键。提供高可用性和持久性,并支持版本控制、访问控制、事件通知等高级功能。
而相关的S3 服务可以简单理解为:定期对数据库状态进行快照,并将其存储在S3中,以此作力备份和灾难恢复之用。但这种周期性快照的方式意味着,可能会丢失发生在定期备份之间的更新内容。
EBS服务,即表弹性块存储(Elastic Block Store)。基本单元由一对EBS服务器构成,每台服务器均附带一个硬盘驱动器。EBS提供的是名为EBS卷的服务,面向外部时的呈现与普通硬盘无异。其内部使用链式复制的方式提供数据保护。且每个EBS卷只能供一个EC2实例使用。
- EBS存在的的问题
1.如果在EBS上运行数据库,最终会导致大量数据通过网络传输。系统整体性能很大程度上受到网络限制;
2.容错性不强。出于性能考虑,亚马逊总是将EBS卷的两个副本放置在同一数据中心内。但如果整个数据中心瘫痪,根本就没有任何应对方案。
- RDS技术
在介绍RDS技术之前,我们先了解一下“可用区”的概念。上文提到出于性能考虑,亚马逊总是将EBS卷的两个副本放置在同一数据中心内,而“可用区”指的是:在临近城市或某一城市的不同地点的不同机房。
RDS尝试获取一个在多个“可用区”中进行复制的数据库,以便如果整个数据中心发生故障,可以恢复数据库内容。在RDS(关系型数据库服务)配置下,对于一个写入的请求,每当数据库追加日志或写入其任一页面时,数据都必须发送到两个副本中。它必须通过网络连接跨越城市的另一边的其他“可用区”进行发送,后者再将数据发送到其两个独立的EBS副本。在上述流程完成之后才会进行写入完成的回复。
例如,有一个EC2实例,作为数据库服务器,它将其数据和日志存储在EBS中,而不是本地磁盘上。数据库会将请求写入缓存并发送给副本。副本会对请求/修改先通过日志的方式记录,之后再对其进行写入/修改。因此,每当数据库执行日志写入或页面写入或其他任何操作时,这些写入都会发送到这两个EBS卷,即EBS副本。而副本位于同一个“可用区”中。对于数据库软件执行的每一次写入操作,将写入同时发送到第二个“可用区”内的特殊配置中,即转移到第二个机房里一台独立的计算机或是EC2实例等,其任务仅仅是镜像主数据库所执行的写入操作,即将这些写入操作复制到第二对EBS服务器上。只会才会回复请求写入/修改的客户端,其写入/修改的请求已完成。
亚马逊 Aurora
Aurora正是基于对RDS技术的改进而来。主要改进点有两个方面:
1. 对于EBS的数据替换,基本上涉及六个副本
在三个“可用区”中,每个区部署两台服务器,以提升容错能力。且优化网络传输,通过网络传输的只有日志记录,不包含请求数据等内容,从而实现网络性能的提升。
2.系统无需等待所有六个副本确认写入操作,数据库服务器便可继续运行
只要达到法定数量(即四台),数据库服务器便可持续运行,即,写入的确认只要这其中的任意四台服务器作出响应即可。
*Aurora并不是一个通用的解决方案,这跟对应的数据库类型相关,如其主要适配MySQL数据库。
- 关于法定数量
在确定法定数量之前,应该先确定系统需要达到的容错目标:
1.即使在某个“可用区”完全失效的情况下,也能够进行写入、读取和写入操作;
2.即使能够在有一个失效的“可用区”加上另一台失效服务器的情况下仍能进行读取;
3.在即使有一个“可用区”失效的情况下进行写入;
4.能够应对暂时性的慢速副本,避免因某一慢速副本拖慢系统整体响应速度;
5.具备快速重复制的能力,如果某个服务器永久性失效,希望能够从剩余的副本中尽快生成一个新的副本。
如何确定法定数量
确定法定数量的一个目的是构建能够利用复制提供容错存储的存储系统,并确保即使部分副本发生故障,读取操作仍能查看到最新的写入内容。假设如果拥有N个副本,若要进行写操作,为了确保写入成功,必须得到W个副本的确认,其中W小于副本总数N,即需要将每次写入操作至少发送给W个副本。并且,如果想进行读操作,必须从至少R个副本中获取读取信息。
关键点在于W和R必须相对于N进行设定,以确保向任意W个服务器发送写入操作时,这些服务器的集合必须与未来任何读取请求可能从中读取的任意R个服务器的集合存在交集。这表示,R加上W必须大于N,以确保任意W个服务器至少与任意R个服务器中的一个重叠。这里的W与R即为写入操作时的法定数量与读取时的法定数量。
读取数据时,读取操作要求读取者与满足R数量的服务器进行核对,并根据版本号判断当前获取数据是否为最新(由于写入操作并不需要所有副本均报告完成之后才能读取,所以存在遇到R数量的服务器对于读取请求时返回的数据不一致,即有新有旧的情况。当遇到读取返回的数据不一致时,取最新版本的数据)。
每次进行写入操作时,除了日志、写入数据,还需要将这些内容与一个递增的版本号一同发送。
注意,当读或写的请求无法满足连接到足够的法定数量时,系统只能不断尝试,直到服务器重新上线或再次连接。否则系统将不能回应对应请求。
在实际中,Aurora使用了N等于6、W等于4、R等于3的法定数量。这可以满足在存在三个故障服务器的情况下,仍拥有足够的法定数量(R)来读取数据并重建更多副本。但在创建更多副本用以替换这些失效副本之前,无法提供写入服务。当然,针对每个新追加的日志记录必须在至少四个副本的存储中被追加后,该写入操作才被视为完成,然后它便可以响应客户端。
如果数据库服务器本身遭遇崩溃。在发生崩溃后,当新的数据库服务器进行恢复时,它会执行读取法定数量(R)的日志条目操作,以确定每个前序日志条目都存在的最高日志编号。找出缺失的日志条目的编号,并通知副本丢弃该编号及其之后编号对应的日志条目(对于已提交的对应条目的副本要求数据进行回退)。
- Aurora 的读写性能
写操作只能通过单一的数据库服务器进行,读取操作则可以由多台只读数据库进行分流,Aurora最多支持15个读取节点。
因此,当客户端向只读数据库发送读取请求时,只读数据库会确定需要提供该请求的数据页,并直接将读取请求发送到存储系统,而无需打扰主读写数据库。Aurora主数据库也会向每个只读数据库发送一份其日志的副本,不过这也意味着只读数据库可能会稍微滞后于主数据库。
此外,系统不希望只读数据库看到来自未提交事务的数据。因此只读数据库需要谨慎地避免将未提交事务的写入操作应用到其缓存中。
- Aurora 如何处理大型数据库
若存在一个超过一个副本存储容量上限的数据库,系统会将该数据库的数据分散到多组六个副本中,每一被分割的部分是被称为分片的基本单位;而每个组被称为保护组,即PG(Protection Groups)。
那么在多个保护组中,该如何分割日志呢?
数据库服务器在发送日志记录时,会查看该日志记录所修改的数据,并确定存储这些数据的是哪些保护组。将每个日志记录仅发送给存储了日志条目中提及的、被修改的数据的保护组。即,每个保护组都存储了一部分数据页以及与这些数据页相关的所有日志记录。
当需要数据重建时。例如一个实体存储服务器A,它存储了多个10GB保护组的副本,如果发生故障后需要进行硬件的替换。策略是:
如果在存储服务器A上存储了n个10GB保护组,我们会选择n个不同的存储服务器,每个服务器都将接管一个新的保护组。也就是说,这n个服务器现在都将多一个分担的保护组的数据。
这样的操作将使得网络上并行传输着n份各10GB的不同副本,若性能与网络吞吐能力足够,整个过程的耗时将非常短,即这样方式的优势在于性能足够的情况下能够从单一机器的故障中极其迅速地并行恢复。
以上内容来自对 MIT 《分布式系统 6.824》的学习笔记,在此特别声明。