Amazon Aurora: Design Considerations for HighThroughput Cloud-Native Relational Databases,来自Sigmod 2017,可以在Werner Vogels Blog上下载到 (SIGMOD 官网还没更新)。
下图是AWS RDS方案,数据库的计算和事务使用EC2,存储则在分布式系统中: 在云计算场景下,一般使用块存储来Host数据库服务器,既数据库的读写会在多个存储节点上进行强一致性的同步处理,带来的好处是存储持久性(Durbility)高。并且分布式存储本身可以无限扩张,因此数据量不是大的问题。除此之外,一些新存储技术的诞生,例如NVMe SSD单机提供较高IOPS设备使得分布式存储也能在较高读写情况下有很强Throughput。
分布式存储并不是万能的,面临的最大挑战则是Transaction 等 2 Phase Commit(2PC)协议对于可靠性以及延时的TradeOff。 磁盘、网络、机柜、机房等都有一定的ATF(年故障率),并且日常维护重启、升级等操作会增加这类临时不可用时间。一般采用多副本选举来解决该问题:例如3个副本的情况下,写必须要有2个以上(Majority)副本写成功才可以,在读的情况下也必须保证有2个:V-Read + V-Write> V-Copy Aruora设计中使用了3 AZ,每个AZ 下2 Copy的设置,共计6个副本。AWS 传统的服务,例如S3、Kinesis等都是3副本设计。这样的设置主要从实际观察情况出发:
在同一个AZ下下硬盘、节点损坏、维修等是常态。在同一个AZ下设置2 Copy可以尽可能减少这类操作对用可用性影响机房级AZ问题不常发生,例如水灾、火灾以及天花板损坏等故障(roof failure?)在写入场景下6 Copy需要保证4个副本完成,在读场景下只要7-4=3 个副本一致就可以了
存储节点Segement这种设计对于日常运维比较重要,例如在热点问题上(Heat Management),两个实例都非常大需要进行调度,或存储节点OS需要Patch,存储节点的代码需要更新,这种类似Ping-Pang升级的方式可以使得AZ级存储节点能够灵活配置。
AWS传统RDS问题在于对于写放大,用如下这张图就能发现,在一个Master-Slave(主从热备)RDS场景下,主节点和存储层的交互会被放大多次:
Replication LogRedo Log (临时存储最后N个)Data(最新数据库结构数据,内存中定时Dump)FRM Files(这个数据量一般比较小)假设EBS有2-Copy,则一份数据写入/更改被放大了222 = 6 倍,如果EBS为3-Copy,这个数据约为12倍。如果有备节点也算上的话,这个数字既为24倍。直接使用分布式存储放大非常严重。 搞过Hbase人应该知道,对于LSM这样的场景,一般10MB/S原始数据写入,后台网络流量会达到80-100MB/S,原因也是类似,一份数据写入后放大如下3-Redo + 3 Mem File + 3 Times Merge = 9 Origin Input 但这种模式也带来来了好处,就是CPU会浪费得比较少,因为3-Copy只占据IO和网络,CPU本质上只有一份。 Aurora提出的思路是,计算节点直接将RedoLog下推到存储节点,每个存储节点根据RedoLog 来构成本地(Local Segment)存储状态,多个存储可靠性通过副本数来保障。每个存储节点也可以将Segment 定时同步到S3上增加可靠性。 每个存储节点在处理时,在处理请求,写入本地RedoLog后既返回,以保证低延时: 存储节点共有5个数据链路上的步骤:
接收到请求,加入内存中的队列(主要是为了做batch commit)将批量Redolog存储到本地磁盘内存中对于批量redolog进行整理,确定还有哪些没有catchup与其他副本存储节点进行gossip,进行对齐(可选)将本地redolog和 snapshot data dump到S3进行备份后台工作(2个):
根据redo log进行gc,删除无用的data 和 redo log本地盘做CRC进行数据检查,以及恢复明白了主要差别后,其他的读、写、事物提交等也没有什么新的东西。性能测试等可以参见Paper。 最后来一张基于ELB、EC2、VPC等部署大图:
高可用性,以及升级能力:6 副本,单AZ内数据节点轮转升级,这点毫不费力
最后我们来看看Aurora定价形态:
和AWS RDS的方式类似,本质上是直接购买EC2的节点。在创建计算实例节点后,可以将资源扩展到 32 vCPU 和 244 GiB 内存更大的实例。也可以选择按量付费模式。
最低存储为 10GB(一个最小Segment),最大为64TB(应该是处于SSD最大本地盘的考虑)。因为存储层是以Segment进行管理的,所以可以弹性地从 10GB 自动增长到 64 TB,而不会影响数据库的性能。
每GB存储为0.1$ /Month,这对于单SSD存储而言是一个比较Fair价格,如果是默认6-Copy,则乘以6。
价格为 $0.200 每 100 万个请求,这个费用属于毛利率比较高的。
IO 是由 Aurora 数据库引擎依靠基于 SSD 的虚拟化存储层执行的输入/输出操作。每一个数据库页面读取操作为一个 IO。Aurora 数据库引擎依靠存储层发出读取,以获取不在缓冲缓存中的数据库页面。每个数据库页面为 16KB。
Aurora 目的是消除不必要的 IO 操作,以降低成本,并确保资源可服务于读/写流量。只有将事务日志记录推送到存储层,完成耐久型写入时,才消耗写入 IO。写入 IO 以 4KB 单位计算。例如,1024 字节的事务日志记录计为一个 IO 操作。然而,当事务日志小于 4KB 时,同时写入操作可通过 Aurora 数据库引擎批量进行,以便优化 I/O 消耗。