当前位置: 首页 > 工具软件 > Aurora > 使用案例 >

Aurora简介

萧星火
2023-12-01

Aurora是什么

Amazon Aurora 是一个专为云打造的关系数据库管理系统 (RDBMS),可与 MySQL 和 PostgreSQL 完全兼容

一些背景知识

EC2 和 EBS

  • 最早的时候,Amazon提供的云产品是EC2,它可以帮助用户在Amazon的机房里和Amazon的硬件上创建类似网站的应用。每个EC2实例都会运行一个标准的操作系统,比如说Linux,在操作系统之上,运行的是应用程序,例如Web服务、数据库。这种方式相对来说成本较低,也比较容易配置。最早的时候EC2用的都是本地盘,每个EC2实例会分到本地盘的一小部分。

  • EC2对于无状态的Web服务器来说是完美的,但是对于数据库来说,EC2就不像对于Web服务那样完美了,最直接的原因就是存储。如果数据库所在的服务器宕机了,并且数据存储在服务器的本地硬盘中,那么就会有大问题,因为数据丢失了。

  • 于是出现了EBS(Elastic Block Store)。从EC2实例来看,EBS就是一个硬盘,一个EBS volume看起来就像是一个普通的硬盘一样,但却是由一对互为副本EBS服务器实现,每个EBS服务器本地有一个硬盘,这两个EBS服务器会使用Chain Replication(9.5)进行复制。EBS存在的问题:

  • 每个EBS volume只能被一个EC2实例所使用

  • Amazon总是将EBS volume的两个副本存放在同一个数据中心。所以,如果一个副本故障了,那没问题,因为可以切换到另一个副本,但是如果整个数据中心挂了,那就没辙了

  • 如果你在EBS上运行一个数据库,那么最终会有大量的数据通过网络来传递【论文的图2】

云原生数据库

云计算时代,资源都是弹性管理、按需使用。这里的资源,自然就包括了数据库的计算和存储资源

数据库的存算分离

  • 存储当然是数据的基础能力。
  • 计算能力对外体现在:数据库可以完成用户发出的复杂分析与计算请求(用 SQL 可以写出强大的计算逻辑),对内体现在:查询优化、事务处理、索引维护等内部计算。
  • 优点: 资源优化:解决数据快速移动,实现计算、存储弹性扩展,按需分配
  • 例如数据导入类的任务,往往需要消耗比较大的IO、网络带宽,而CPU资源消耗不大。而复杂查询类任务往往对CPU的资源消耗非常大

Quorum 读写

  • Quorum系统背后的思想是通过复制构建容错的存储系统,并确保即使有一些副本故障了,读请求还是能看到最近的写请求的数据
  • Quorum系统的要求: 集群有N个节点, 读R个节点,写W个节点。(满足R + W >= N + 1 ),这样任意W个服务器至少与任意R个服务器有一个重合。【这里是这样工作的,当你执行写请求时,你会将新的数值和对应的版本号给所有N个服务器,但是只会等待W个服务器确认。类似的,对于读请求,你可以将读请求发送给所有的服务器,但是只等待R个服务器返回结果】
  • 每一次执行写请求,你需要将新的数值与一个增加的版本号绑定
  • 所以任何读请求可以从至少一个看见了之前写请求的服务器得到回复
  • 相对于chain replication的优点,可以轻易的剔除暂时故障、失联或者慢的服务器

Aurora的结构

  • 【论文图3】
  • 有6个数据的副本,位于3个AZ,每个AZ有2个副本。所以现在有了超级容错性
  • 这里通过网络传递的数据只有Log条目,这才是Aurora成功的关键。
  • 网络io里没刷脏页这种占用大量io的工作
  • quorum的写,任意4个副本确认写入了,数据库就可以继续执行操作
  • 【论文的表1】总结了一些结果。Mirrored MySQL将大的page数据发送给4个副本,而Aurora只是将小的Log条目发送给6个副本,Aurora获得了35倍的性能提升

容错

  • be able to write even if one AZ entirely dead
  • 当只有一个AZ彻底挂了之后,写操作不受影响
  • be able to read even if one dead AZ and one more storage server dead
  • 当一个AZ彻底下线了之后,对于读操作,Aurora还能容忍一个额外服务器的故障,并且仍然可以返回正确的数据
  • N=6, W=4, R=3

Aurora读写存储服务器

  • 当一个新的写请求到达storage server时,这个写请求只是一个Log条目,Log条目中的内容需要应用到相关的page中。但是我们不必立即执行这个更新,可以等到数据库服务器或者恢复软件想要查看那个page时才执行。对于每一个存储服务器存储的page,如果它最近被一个Log条目修改过,那么存储服务器会在内存中缓存一个旧版本的page和一系列来自于数据库服务器有关修改这个page的Log条目。
  • database server 也会缓存page, 如果之后数据库服务器将自身缓存的page删除了,过了一会又需要为一个新的事务读取这个page,它会发出一个读请求。请求发送到存储服务器,会要求存储服务器返回当前最新的page数据。在这个时候,存储服务器才会将Log条目中的新数据更新到page,并将page写入到自己的磁盘中,之后再将更新了的page返回给数据库服务器。同时,存储服务器在自身cache中会删除page对应的Log列表,并更新cache中的page
  • 数据库服务器写入的是Log条目,但是读取的是page。这也是与Quorum系统不一样的地方
  • 在一个普通的操作中,数据库服务器可以避免触发Quorum Read。数据库服务器会记录每一个存储服务器接收了多少Log。所以,首先,Log条目都有类似12345这样的编号,当数据库服务器发送一条新的Log条目给所有的存储服务器,存储服务器接收到它们会返回说,我收到了第79号和之前所有的Log。数据库服务器会记录这里的数字,或者说记录每个存储服务器收到的最高连续的Log条目号。这样的话,当一个数据库服务器需要执行读操作,它只会挑选拥有最新Log的存储服务器,然后只向那个服务器发送读取page的请求。所以,数据库服务器执行了Quorum Write,但是却没有执行Quorum Read。因为它知道哪些存储服务器有最新的数据,然后可以直接从其中一个读取数据。这样的代价小得多,因为这里只读了一个副本,而不用读取Quorum数量的副本。
  • 什么时候执行Quorum read? 当database server故障了需要重启时

Protection Group

  • 即Aurora的分片
    • 为了能支持超过10TB数据的大型数据库。Amazon的做法是将数据库的数据,分割存储到多组存储服务器上,每一组都是6个副本,分割出来的每一份数据是10GB
  • 两组PG可能使用相同的6个存储服务器,但是通常来说是完全不同的两组存储服务器
  • 当Aurora需要发送一个Log条目时,它会查看Log所修改的数据,并找到存储了这个数据的Protection Group,并把Log条目只发送给这个Protection Group对应的6个存储服务器。这意味着,每个Protection Group只存储了部分data page和所有与这些data page关联的Log条目。所以每个Protection Group存储了所有data page的一个子集,以及这些data page相关的Log条目。
  • 存储服务器挂了的恢复
    • 此不能创建一个新的副本。所以我们想要在一个副本挂了以后,尽可能快的生成一个新的副本。表面上看,每个存储服务器存放了某个数据库的某个某个Protection Group对应的10GB数据,但实际上每个存储服务器可能有1-2块几TB的磁盘,上面存储了属于数百个Aurora实例的10GB数据块。所以在存储服务器上,可能总共会有10TB的数据,当它故障时,它带走的不仅是一个数据库的10GB数据,同时也带走了其他数百个数据库的10GB数据。所以生成的新副本,不是仅仅要恢复一个数据库的10GB数据,而是要恢复存储在原来服务器上的整个10TB的数据。我们来做一个算术,如果网卡是10Gb/S,通过网络传输10TB的数据需要8000秒。这个时间太长了
    • 如果一个存储服务器挂了,假设上面有100个数据块,现在的替换策略是:找到100个不同的存储服务器作为数据源,进行并行的,快速的上恢复

Read-only database server

  • 论文的图3,你可以发现,Aurora不仅有主数据库实例,同时多个数据库的副本
    • 当客户端向只读数据库发送读请求,只读数据库需要弄清楚它需要哪些data page来处理这个读请求,之后直接从存储服务器读取这些data page,并不需要主数据库的介入。所以只读数据库向存储服务器直接发送读取page的请求,之后它会缓存读取到的page,这样对于将来的一些读请求,可以直接根据缓存中的数据返回。
  • Aurora的主数据库也会将它的Log的拷贝发送给每一个只读数据库。这就是你从论文中图3看到的蓝色矩形中间的那些横线。主数据库会向这些只读数据库发送所有的Log条目,只读数据库用这些Log来更新它们缓存的page数据,进而获得数据库中最新的事务处理结果。
  • 不想要这个只读数据库看到未commit的事务。所以,在主数据库发给只读数据库的Log流中,主数据库需要指出,哪些事务commit了,而只读数据库需要小心的不要应用未commit的事务到自己的缓存中,它们需要等到事务commit了再应用对应的Log。
 类似资料: