乐趣区

关于sql:分布式存储论文研读四Aurora

分布式存储钻研打算的最初一篇论文,研读 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:

比拟项 Spanner Aurora
架构 Shared Nothing Shared Disk
弹性 Yes Yes
继续可用 Paxos-based Quorum-based
写扩大 Yes No
分库分表通明 Yes No
分布式事务 Yes No
MySQL/Postgres 兼容 No Yes
退出移动版