分布式存储钻研打算的最初一篇论文,研读Amazon的Aurora数据库。其对应论文为:Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases。论文发表于2017数据库顶会SIGMOD。键值对数据库,Amazon提出了Dynamo,而关系型数据库,Amazon推出了Aurora。

Introduction

随着数据库上云,传统数据库的业务IO瓶颈曾经转化为数据库层和数据存储层之间的IO瓶颈,在这种状况下,内部存储节点、磁盘和网络门路对于响应工夫有很大的影响。另外,一些同步操作会导致数据库提早和环境切换。还有,事务提交也会很大水平上影响性能,尤其是2阶段提交等简单操作。

绝对应的,Aurora有以下长处:

  • 应用了一个独立的,能容忍谬误并自我修复的跨数据中心存储服务,保障了数据库不受网络层或数据存储层问题的影响。
  • 在数据存储中,只写入redo log记录,能够从量级上缩小网络IOPS。
  • 将耗时简单的性能从一次低廉的操作转变为间断的异步操作,保障这些操作不会影响前台解决。

Durability at Scale

为了保障大规模集群下的耐久性,Aurora次要有两项措施:应用一个仲裁模型(quorum model)以及分段存储。

仲裁模型,咱们曾经比拟相熟了,对于V个正本的数据,R + W > V即可保障一致性。在之前的Dynamo论文中也有提到。一个典型的取值是(V,R,W)=(3,2,2)。但Aurora认为这还不够。一个简略的例子是,将数据的三个正本别离放在三个可用区(AWS的AZ概念,在同一个地区相邻的三个数据节点),如果同时一个可用区产生了大规模故障,而另一个可用区里的一台服务器产生了偶尔故障,那么仲裁模型将不再无效。

为了保障(a)即使整个可用区加一台其它可用区服务器产生故障,零碎不会失落数据,以及(b)一整个可用区故障后仍能进行写数据,Aurora的参数设置为(V,R,W)=(6,3,4),每个可用区会有两个数据正本。能够看到(a)状况下,3个正本产生故障,不影响读操作,数据不失落。而(b)状况下,2个正本故障,不会影响写操作。

Segmented Storage

故障复原有两个概念:MTTF(Mean Time to Failure,均匀故障产生工夫)和MTTR(Meat Time to Repair,均匀故障修复工夫)。如果心愿零碎可能抵挡故障,那么须要MTTF > MTTR,在故障修复期中尽可能没有新的故障产生。MTTF很难优化,Aurora专一于升高MTTR,策略也很直观:将数据分段为10GB的Segment,每份会在3个可用区中有一共6个正本,数据存储在带有SSD的EC2上(亚马逊的虚构服务器)。那么Segment就是零碎探测生效和修复的最小单元。10GB的分段数据在10Gbps的网络连接上只须要10s就能传输结束,在这个窗口内1个可用区生效,外加另外可用区中两个正本同时生效的概率十分非常低。

Operational Advantages of Resilience

因为整个Aurora的设计针对故障保障了高可用性,那么利用这个高可用性也能够做很多运维操作。例如回滚一次谬误的部署;标记过热的节点为已损坏,由零碎从新将其数据调配到冷节点中去;以及进行节点为其打上零碎和安全补丁。其中,打补丁时,会一个个可用区顺次进行,同一时间一份数据只会有一个正本所在节点进行打补丁操作。

The Log is The Database

The Burden of Amplified Writes

Aurora在提供了弱小的高可用性背地,理论放大了整个数据库读写的操作。例如一个MySQL的写操作须要写4次,在写的过程中,实际上分为了很多类的数据,包含redo log、binaray log(会被同步归档在S3中来反对实时restore)、批改的数据页、长期的double-write以及FRM元数据。所有数据都会在节点间流传和写入数据库。被放大了的网络负载如图:

Offloading Redo Processing to Storage

为了解决上述的问题,在Aurora中,在网络中流传的写数据只有redo log。在将log传递到数据存储层后,再在后盾或按需生成数据库的页。因而也才有了题目“The log is the database”。优化后的网络负载如图:

通过试验比照,这项优化达成了其同一时间解决的事务量进步到了35倍,优化前每个事务处理的I/O数量是优化后的7.7倍,以及更多数据上的性能进步。性能的进步也意味着零碎可用性的降级,升高了故障复原工夫。

Storage Service Design Points

Aurora的一项外围设计理念,就是把大部分的存储操作放到后盾,精简前台的解决以缩短响应工夫。拆散前后台的做法让整个零碎更加灵便。例如在CPU忙于解决前台申请的时候,就能够临时不必管旧页面的垃圾回收。后盾解决与前台解决出现负相关的关系,相互削峰填谷。一个更加粗疏的存储节点交互如图:

  1. 接管到日志记录,并填入一个内存队列。
  2. 在磁盘上将记录长久化,并返回一个应答。
  3. 整顿记录,并查看是否有因为一些操作失落导致的记录差别。
  4. 通过Gossip和其它节点交换填补差距。
  5. 将日志记录合并到新的数据页中去。
  6. 定期将日志和新页面备份到S3。
  7. 定期进行垃圾回收,清理掉无用的旧版本数据。
  8. 定期进行CRC校验。

其中只有第1第2步波及前台交互,影响响应工夫。

The Log Marches Forward

这节的题目起的很有意思,内容次要讲的就是Aurora如何在不应用简单的2PC协定的状况下进行多个状态(durable,runtime,replica)的数据同步。

Solution Sketch: Asynchronous Processing

Aurora的一个设计亮点就是redo log的日志流解决。这个log不单单是一个程序队列,实际上会和一个枯燥递增的序列号(LSN,Log Sequence Number)相关联。每个节点都有可能失落几个操作,此时它会和与它存储同一份数据的节点进行Gossip交换,填补缺失。这样失常的读操作(没有产生故障复原)就能够只读一个分片,防止仲裁读取的办法(在之后会有更具体的解释)。

而当须要进行故障复原时,Aurora首先会保障所有节点上的数据统一。应用的就是LSN。在数据恢复时,零碎先确定一个保障可用的最高LSN,称为VCL(Volume Complete LSN),任何LSN高于VCL的日志记录会被截断。数据库还能够进一步规定只有某些LSN可能被作为截断点,称之为CPL(Consistency Point LSNs),而定义VDL(Volume Durable LSN)为小于等于VCL的最大CPL。术语有些多,给一个简略的例子:以后日志的LSN曾经达到了1007,但数据库定义CPL为900,1000,1100这些特定值。那么咱们就须要在1000这个值进行截断,1000即为VDL。理论过程中的大抵流程如下:

  1. 每个数据库层事务被切分成多个有序且可被原子操作的小事务(mini-transactions,MTRs)
  2. 每个MTR由多个间断的log record组成。
  3. 一个MTR的最初一个log record被认为是一个CPL。

从这段形容能够看出,一个CPL其实就是一个原子MTR的完结标记。

Normal Operation

接下来具体介绍一下每种操作的具体原理。包含write,read,commit和replica。

  • Writes:当数据库收到一批log日志的write quorum的确认后,就会向前推动以后的VDL。在每一时刻,会有很多事务在同时进行,数据库会为每个日志调配一个惟一有序的LSN,同时LSN要小于以后VDL和LAL(LSN Allocation Lmit)的和。这段话翻译有些僵硬,其实就是为了避免前台操作太快,后盾存储系统解决不过去,LSN不能超前VDL太多,其差值最大为LAL,目前设置为10M。同时,为了解决每个分片可能存在的日志失落问题,每个日志都有一个向前的回链(像是一个反向链表),通过向前回溯,以及Gossip交互,能够为各个节点构建一个残缺的日志记录,称之为SCL(Segement Complete LSN),也即所有日志达到了所有节点的最大LSN。
  • Commits:Aurora的事务提交是齐全异步的。工作线程收到commit申请,在一个期待commit的事务列表中记录它的commit LSN,而后就持续解决其它申请。有一个专门的线程在VDL推动时,判断列表中有哪些LSN小于等于VDL,而后将这些事务的应答推回给还在期待的客户端。
  • Reads:Aurora和很多其它数据库一样,数据页会放在缓存中,命中失落时才会做一次IO申请,当缓存满时,零碎会依据特定的算法汰换数据页。Aurora不一样的是,它要求在缓存中的page LSN肯定要大于等于VDL。从而保障在这个数据页中所有申请都曾经写到log,且能够通过VDL始终获取到最新的长久化数据。也因而,失常的读取只须要读一个满足条件的分片就足够了。
  • Replicas:在Aurora中,一个存储磁盘能够挂载一个writer和最多15个read正本。减少一个read正本不会对性能有什么影响。为了放慢响应,写申请生成的日志流也会被发送到所有读正本中去。如果这个写申请波及到以后缓存中的某个数据页,那就把这个申请更新到数据页中,否则就间接抛弃了。这里读正本生产申请是异步的,须要遵循两条规定:一是会更新到数据页的申请,其LSN须要小于等于VDL。二是mini-transaction的批改须要原子性的写入缓存,以保障数据一致性。

Recovery

传统的数据库Recovery会应用相似ARIES的协定,依据WAL(write-ahead log),使得故障复原后的各个节点数据统一。这种办法的一个准则是在数据库故障离线期间,通过重放日志的形式来复原数据。而Aurora则将重放的过程放到了数据存储节点,齐全后盾话操作。即便故障产生时正在解决100K TPS,也能在10秒内复原。

当然,在故障复原后,零碎还须要从新构建它的运行时状态(runtime state)。此时的读取就须要进行quorum读,来保障数据一致性。同时进行VDL的计算,截断之后的record。数据库也须要对一些操作做回滚,但这些操作都能够在后盾进行。

Putting It All Together

整个Aurora的鸟试图如下:

其中数据库引擎就是社区版的MySQL/InnoDB。做的最次要的扭转就是InnoDB向磁盘读写数据的形式。

在社区版InnoDB中,写操作会将数据写入缓存页,相干的redo log record以LSN的程序写到WAL的缓存中。在事务提交中,WAL协定只要求redo log records长久化写到磁盘中,理论批改的缓存页通过double-write技术最终写到磁盘上。除了IO子系统,InnoDB还有事务子系统,lock manager,B+树的实现以及MTR。MTR理论就是对一些InnoDB内原子操作的建模,例如B+树的split和merge。

在Aurora中,每个MTR须要进行的redo log records会被组织成批量操作,在所有存储对应数据的分片中共享。这些批量操作会被写到存储服务,最初的一个log record被标记为一致性point。Aurora的读正本会接管到写申请的信息,来反对快照性能。数据库引擎负责了并发管制,而存储服务提供了一个逻辑上与你应用InnoDB写本地存储统一的数据。

在理论部署中,Aurora会在同一个region的不同AZ中散布实例,每个实例中会应用RDS来作为Host Manager,监控集群衰弱,判断是否须要敞开或一个实例须要被代替。为保障平安,Aurora集群会通过VPC限度相互沟通,其处于三个档次的VPC中:Custom VPC、RDS VPC、Storage VPC。存储服务由一系列EC2承载,如之前所述,至多3个AZ,每个AZ两台EC2。存储管理层会应用DynamoDB来存储集群和节点配置,卷的元数据,及向S3存储数据的详细描述。同时存储管理层会应用Amazon Simple Workflow Service来维持高可用和自动化运维。存储服务的关键点都会有继续监控。

Performance Results

产品上线前,Aurora通过了一系列比照测试。测试后果在原文中列举,这里不再具体列出。

在实验室测试中,有如下几点论断:

  1. Aurora能够进行通过扩大实例类型线性扩大其吞吐量。
  2. Aurora即便在大数据量的状况下,其读写吞吐量也显著优于MySQL。
  3. 随着客户端连贯的减少,Aurora能够线性扩大其吞吐量。
  4. Aurora相比于MySQL,写提早非常低(升高几个数量级)
  5. 在热行争用(hot row contention)的场景下,Aurora的性能也显著因为MySQL。

在实在客户场景下Aurora的性能也失去了很好的证实。

Lessons Learned

  • Multi-tenancy and Database Consolidation:许多客户的服务会面临多租户的场景,他们原有的利用不容易拆分,那么简略的办法就是为每个租户维持一张表,并把所有租户的表放到数据库中去。这和相似于Salesforce应用多租户数据结构,并把所有用户数据封装到一个表里的行为不一样。这种场景下,须要思考以下几个方面,Aurora都非常适合:
  1. 可能维持高并发
  2. 可能按用量动静调整数据库大小
  3. 可能尽量管制多租户数据之间的相互影响。
  • High Concurrent Auto-scaling Workloads:Aurora能够很好地解决拜访尖峰问题。
  • Schema Evolution:在应用数据库时,开发人员能够很轻松地扭转schema,而DBA就须要解决这些schema演变(实际上我没有相似的经验,不能很好地设想这种场景)。Aurora提供了两种机制:
  1. 对各个版本的schema历史做记录,在解析时按需应用对应的schema。
  2. 应用写时批改为最新Schema的机制,对每个独立的页进行“懒”降级。
  • Availability and Software Upgrades:线上利用根本不能承受数据库的停机降级。Aurora公布了一种零停机滚动降级的形式。具体来说,这个机制先找到一台不再处理事务的实例,将程序的长期状态存储到本地,为数据库打补丁,而后从新加载利用状态。

另一个我感觉解读地很好的博客:Amazon Aurora解读

Six Questions

这个技术呈现的背景、初衷和要达到什么样的指标或是要解决什么样的问题。

Amazon曾经有了DynamoDB这个弱小的NoSQL数据库,与之绝对应的是一个在线事务处理(On-line Transaction Processing)的关系型数据库Aurora。它的呈现源于Amazon的一个观点:在云端大规模集群中,传统的OLTP数据库曾经不能保障可用性和持久性。Aurora将传统数据库中的存储和计算拆散,在这种拆散架构下,关系型数据库的次要瓶颈曾经从数据处理和存储的转为了网络传输。因而Aurora的许多设计和优化都是针对此而来:构建一个简略的框架来解决大型数据库中的网络传输瓶颈。

这个技术的劣势和劣势别离是什么,或者说,这个技术的trade-off是什么。

Aurora的劣势在于,它扭转了传统关系型数据库的读写框架,使其实用于弹性伸缩的云端,取得了可用性和持久性,同时升高了网络传输,使得整个零碎响应低延时。上云之后,还有更多的长处,例如按需伸缩,多租户共享基础设施降低成本,故障可能疾速复原等。为此它继承了社区版MySQL的一些弱点,比方不能执行简单的查问,单点写,写程度扩大须要依赖其它中间件计划。同时目前最大反对64TB的数据量。

这个技术应用的场景。

Aurora实用于部署在云端弹性伸缩,读多写少,要求高并发低延时高可用性,处理事务的关系型数据库场景。

技术的组成部分和关键点。

Aurora实质上是将社区版的MySQL进行了从新架构,将计算和存储拆散。其要害的组成部分是通过批改的“Aurora MySQL”,配合应用AWS RDS进行元数据管理,并将数据存储到底层的磁盘和S3等存储服务中。

技术的底层原理和要害实现。

Aurora的底层引擎仍旧是社区版MySQL,其做的最次要的改良是剥离计算和存储,简化网络传输,在网络传输中只传递redo log。另外就是应用Quorum模型来保障高可用,应用分段存储来保障疾速地从故障中复原。

已有的实现和它之间的比照。

论文自身没有Related Work。依据之前举荐的博客,其一个比拟对象就是Google的MySQL数据库Spanner:

比拟项SpannerAurora
架构Shared NothingShared Disk
弹性YesYes
继续可用Paxos-basedQuorum-based
写扩大YesNo
分库分表通明YesNo
分布式事务YesNo
MySQL/Postgres兼容NoYes