13 December 2018

本文整理下之前看的笔记。

Abstract

作者认为现在高吞吐的DBMS的瓶颈,已经从计算和存储,转变了网络。Aurora的架构主要是DB和存储分离,把redo处理下沉到分布式的存储服务。

1. Intro

现代分布式的云服务,计算和存储分离被越来越多的使用,以期灵活和扩展性。

Aurora采用这种架构,上层DB是计算层,下层使用一个分布式共享存储,并把redo处理(包括持久化存储,故障恢复,备份和还原)下沉到storage层。

Aurora架构的主要优点有3个优点。第一,使用一套独立、自治的存储服务,可以屏蔽存储节点的各种故障和差异。其次,DB层向存储层只写redo Log,可以减少一个数量级的网络IOPS。去掉网络的瓶颈以后,可以从多个方面优化系统。最后,通过把逻辑复杂的操作(备份和redo恢复),从耗时的单次操作,均摊到持续的后台操作,去掉了checkpoint,能够快速恢复,并且备份不会影响到前台操作。

2. 扩展的持久化

2.1 副本策略

2PC在云环境下容错性较差,Aurora使用了Quorum机制。 有V个副本的数据来说,需要满足两个限制条件。

  • 第一个是 Vr + Vw > V, 每个读请求都要能看到最近的写操作;
  • 第二点是 Vw > V/2, 每个写请求需要能看到最近的写请求。

为了达到这两种容错能力:(a) 能够容忍整个AZ失败,同时还有一个节点失败,不丢数据;(b)整个AZ失败时,仍然可写; Aurora 采用3AZ 6副本,每个AZ部分2个副本。即写大多数是4/6(Vw=4), 读大多数是3/6(Vr = 3). Protection Groups (PGs)

2.2 Segment

一个DB的卷 (Volumn) 划分为多个10G大小的segment。6个segment副本,组成一个PG(Protection Groups ) 。segment是目前的最小单元,每个AZ部署两个segment。

3. Log即DB

这里主要从网络IO方面,分析对比了使用MySQL主从镜像的架构,和Aurora, 实验得出Aurora可以减少一个数量级以上。

4 Log推进

概要:异步处理

从上层来看,我们需要维护完整的和持久化的位点,并在接收到确认请求后,推进位点。 DB引擎会记录未完成的事务,在故障或者重启时undo;重启时,存储服务需要提供给DB一个一致的状态,保证日志的完整性(Completeness)和持久性(Durability)。

我们首先约定,1) 每个DB的事务都是由多个mini事务组成的(mini-transactions, MTRs), 每个mini事务都是原子的(atomically); 2) 每个mini-trx是有连续的record组成;3)mini-trx的最后一条record都是一个CPL,一个一致性位点,可以在恢复时做日志截断;

  • LSN (Log Sequence Number):我们将DB当做一个redo日志流, 每个记录有一个序列号;
  • VCL (Volume Complete LSN): storage service保证的 最高的LSN, 这个LSN和之前的日志都是可用的; 在storage恢复过程中,比VCL大的日志,都会被截断删掉;
  • CPL (Consistency Point LSNs): 每个mini-trx的最后一条record,恢复时可以做日志截断;
  • VDL (Volume Durable LSN): 小于等于VCL的最高的CPL,

完整性和持久性是不一样的,举个例子,我们虽然有完整的LSN到1007的日志,在CPL是900,1000,和1100的情况下,必须截断1000以后的记录。

恢复过程中,storage service的每个PG会建立持久化的位点,基于此得到VDL,然后截断VDL之后的记录。

4.2 基础操作

4.2.1 写操作

DB持续向storage service的大多数,发送写请求, 收到确认后,推进当前的VDL,标记事务为提交。 任意时刻,会有大量的并发的活跃事务,每个事务都会给新的日志记录分配有序的唯一LSN,我们通过限制新分配的LSN Allocation Limit (LAL),达到一定的限流效果。

每个PG的每一个segment,只能看到属于自己segment的Log记录;每条记录有一个反向指针,可以找到当前PG的上一条记录。storage node之间通过Gossip协议,交互SCL,补全确实的Log记录。

  • SCL (Segment Complete LSN): 当前PG的最大的完整LSN,即改LSN之前的所有记录,当前PG都收到了;

4.2.2 提交

Aurora是异步提交的。当客户端提交时,worker线程记录下commit LSN,将该事务移到等待提交列表,继续处理其他任务。在推进VDL后,如果最新的VDL大于等于事务的commit LSN,DB层通过一个线程给等待的客户端发送响应。

4.2.3 读请求

同样的,Aurora的page也保存在buffer cache,当cache没有命中时,才会发起一次storarge的IO请求。

当buffer cache满了,需要淘汰page时,传统的DBMS需要刷脏页,而Aurora保证cache中的page都是最新的,无需刷脏页。只有页面的 page LSN (页面的最新修改的LSN) 小于等于VDL时,page才会被淘汰。Aurora可以保证:(a)Log中已经持久化了page的所有的更新,同时(b)cache miss时,需要获取当前VDL下page的最新版本。

通常情况下,不需要read quorum去达到一致性。DB使用当前的VDL作为read point,通过每个节点的SCL,选一个有read point完整日志的storage node(SCL大于read point即可),就可以读到最新的page。

DB根据所有运行的读请求,维护每个PG的最小read point (PGMRPL PG Minimum Read Point LSN),表示每个PG的日志记录的低水位,小于它的record没有读请求访问。因此,每个storage node可以根据PGMRPL, 合并老的记日志记录,推进page的物化,并回收旧版本。

4.2.4 副本

Aurora的一个共享存储卷(Volumn), 可以支持1个写副本和最多15个只读副本。增加只读副本,并不需要额外的存储成本和写盘操作。写副本除了发送存储节点日志,同时也会发送日志流给读副本,以降低延迟。读副本按照顺序回放日志,更新涉及到的page cache,无关日志则直接丢弃。从写路径来看,读副本是异步的回放日志,因此副本复制也不会影响用户提交。 副本回放有两个原则:(a) 只回放小于VDL的日志;(b) 按照mini-trx 原子的更新cache,保证副本的一致性。

4.3 恢复

通常数据库使用传统的ARIES的recovery方案,WAL加checkpoint。系统周期性的生成一致性的checkpoint,一般需要刷脏页,并记录checkpoint的日志。故障重启时,从上一个checkpoint开始,回放redo日志,DB最后达到crash前的一致状态;然后undo回滚未提交的事务。为了故障快速恢复,我们需要权衡checkpoint的频率,和由此带来的对前台请求的影响。Aurora没有使用这种方案。

首先,Aurora把redo回放逻辑和DB层解耦,放在storage node,且完全后台并行执行。DB启动后,能够通过storage node快速的重建Volumn信息。 DB层同样也需要重建crash之前的运行状态。每个PG,DB层会读大多数,保证能检查到之前写大多数成功的数据,根据每个PG的情况,计算出VDL,从大于VDL的日志,到最大的LSN,算出一个截断区间。由于LAL的限制(新分配的LSN和VDL的差值不超过一个阈值,避免产生过多同时运行的事务),这个阶段区间也有限制,能够很快的回放完成。

最后undo恢复阶段,DB可以先记录未完成事务列表,在DB恢复服务之后,在执行。



blog comments powered by Disqus