三大云原生数据库:Aurora, PolarDB 与 Socrates

作者阿里云代理 文章分类 分类:新闻快递 阅读次数 已被围观 951

1.何谓「云原生数据库」

云计算的出现,加速了企业信息技术的发展。云计算供应商将海量的计算、存储、通信资源放入「池子」中,企业或个人用户按需购买计算资源,快速、低成本搭建信息系统。在系统的 workload 发送变化时,还可以按需扩缩计算机资源。对于与计算供应商来说,所有用户使用的海量的资源统一管理,规模效应显著,边际成本低。对于云计算用户来说,资源获取快捷、方便,按需使用比自建机房、搭建和运维基础系设施成本更低。站在全社会的角度来看,整体资源的利用率更加高,environmentally-friendly。

数据库是最常用的基础软件之一,它通常能提供 计算  存储 的能力。存储当然是数据的基础能力。计算能力对外体现在:数据库可以完成用户发出的复杂分析与计算请求(用 SQL 可以写出强大的计算逻辑),对内体现在:查询优化、事务处理、索引维护等内部计算。

单机数据库部署在普通主机上,其存储和计算能力受限于主机的硬件,难以扩展。分布式数据库可以通过适当增加机器,来拓展数据库的容量和计算能力,但是集群节点的能力依旧受到机器资源的限制。如果将它们简单的搬迁到云上,不做任何改造,普通主机换成云主机。

第一,数据库直接部署在云上,可能会有大量新的问题出现,例如网络瓶颈、可能会带来严重的写放大问题等;再比如:即使给单机数据库挂一个无限大的存储,当数据量极大时性能会很差。第二,无法完全发挥云计算最大的优势「资源弹性管理、按需使用」,也无法灵活运用琳琅满目的云存储产品。第三,信息化、数字化的高速发展,对数据库提出了更多要求:更高的性能、更低的成本、更好的灵活性,这些也是仅仅将单机数据库搬上云解决不了的。

虽然分布式数据库也做到了很好的扩展性,但它不能算是「云原生」。第一,概念上,它弹性扩展的单位是「机器」,而非更加细粒度的「计算和存储资源」。第二,它在设计的时候,并不会考虑云平台的特征,没有相应的优化,以达到最优性能和成本。第三,引入分布式事务、分布式集群管理等模块,也让系统变得更加复杂。(这里没有拉踩的意味,分布式数据库这条路也有巨大的优势,例如数据量极大、需要写扩展性、需要全球部署等场景)

「云原生数据库」的核心,是要设计 一种更加符合「资源弹性管理」这一理念、充分利用云平台池化资源、适配云平台已有的基础设置的数据库架构。

由于云计算平台的存储和计算资源是可以分开扩展的,所以云原生数据库必定是存储计算分离架构。

2. Aurora

2.1 关键问题

Aurora 是 AWS 推出的 OLTP 云数据库先驱,在 MySQL 代码基础上改造出存储计算分离架构。AWS 认为在云上构建数据库,存储资源很容易扩展,那么系统的瓶颈就落在网络上了,因为数据库实例与所有存储节点的交互都需要通过网络。因此 Aurora 最核心的理念就是要减少数据的网络传输量。

Aurora 论文里举了这样一个 MySQL 直接搬迁到云上的例子:

单机 MySQL 事务提交需要日志落盘,同时后台线程会异步刷脏页,为了避免页断裂,刷脏页时还需要将数据页写入 double write 区域。如下图所示,如果再考虑到生产环境中需要主备复制,AZ1 和 AZ2 各部署一个MySQL 实例同步镜像复制(这里应该是 DRBD 的方案?),底层存储采用 Elastic Block Store(EBS),每个EBS还有自己的一份镜像,另外部署Simple Storage Service(S3) 归档 redo 日志和 binlog 日志,以支持基于时间点的恢复。

以上写入同步,每个步骤都需要传递5种类型的数据:redo log,binlog,data page,double write 和 frm 元数据。由于是基于镜像的同步复制,因此图中的1,3,5步骤是顺序的,这种模型响应时间非常糟糕,要进行4次网络IO,且其中3次是同步串行的。从存储角度看,数据在 EBS 上存 4 份,需要 4 份都写成功才能返回。 所以在这种架构下,无论是 IO 量还是串行化模型都会导致性能非常糟糕。

编辑搜图

Aurora 为了减少 IO 的数量,所有节点之间的数据传输,只有 redo。为了做到这一点,需要将部分数据库的能力下推到存储节点。当然除了减少 IO,Aurora 的设计还带来了不少其他好处。

2.2 核心技术

2.2.1 存储计算分离架构

Aurora 下推到存储的主要功能主要和 redo 相关,包括:日志回放、故障恢复和备份还原。技术层保留了查询处理、事务处理、缓存管理、锁管理、访问控制等大部分功能。

编辑搜图

Aurora 的整体由跨 AZ 的一个主实例、多个副本(最多15个)实例及多个存储节点组成。主实例与只读实例/存储节点之间只传递 redo log 和元信息。主实例与副本实例共享一套分布式存储,因此增加副本实例是零存储成本的,这大大提高了 Aurora 的读扩展性。

主实例会异步向副本实例发送 redo log,副本实例收到后开始回放。如果日志对应的 page 不在 本地的 page cache,该 redo log 可以直接丢弃,因为存储节点拥有所有的 page 及 redo log,有需要时直接从存储节点请求即可。

存储节点收到 redo log 后会持久化,而回放日志和回收旧版本数据页的工作,可以一直异步在后台执行。存储节点可以较为灵活的分配资源做前台/后台的工作。同时相较于传统数据库,Aurora 不用后台去推进 checkpoint(这个动作往往会影响前台请求),分离的存储层不断地推进 checkpoint,对数据库实例丝毫没有影响,而且推进的越快,对读请求越有利。

存储层不断推进 checkpoint 也能加快故障恢复的速度,一般情况下,在 10w TPS 压力下,Aurora 可以在 10s 恢复完成。在故障恢复过程中,

详细来说,Aurora 写流程如下:

编辑搜图

(1) 存储节点接收主实例的日志,追加到其内存队列。

(2) 存储节点持久化日志后应答主实例。

(3) 按分片归类日志,确认是否有日志丢失。

(4) 与其它存储节点交互,填充丢失日志。

(5) 回放日志,生成数据页。

(6) 定期备份数据和日志到 S3。

(7) 定期回收过期数据页版本。

(8) 定期 CRC 校验数据页。

上述所有操作,只有第 (1) (3)是串行同步的,会直接影响请求响应时间,其它均为异步操作。

为了保证可用性,Aurora 持久化采用 Quorum 协议。假设复制集合包含 V 个节点,读请求需要得到 Vr 个节点响应,写请求需要得到 Vw 个节点详细,为了保证读写一致性,Quorum 协议主要有两个条件(1)Vr + Vw > V ;(2)Vw > V/2。

主实例的每次写入会发送到位于 3 个 AZ 的 6 个存储节点,收到 4 个持久化成功的回复便认为写入成功。因此 Aurora 的 Quorum 协议中,V = 6,Vw = 4,Vr = 3。当然在实际读请求中,不用真的去 3 个存储节点查询,只需要查询拥有最新数据的那个存储节点就行 。

Quorum 协议可以保证,只要 AZ 级别故障和节点故障不同时发生,数据库的可用性就能得到保证。同时 Aurora 采用分片管理的策略,每个分片 10G,6 个 10G 的副本组成一个 Protected Group,每个分片是一个故障恢复的单位,在 10G/s 网络下,一个分片可以在 10s 内恢复。因此只有当 10s 内同时发生超过2个分片的故障,可用性才会受到影响,这几乎是不可能发生的。

sysbench write only 测试,Aurora是基于镜像MySQL吞吐能力的35倍,每个事务的日志量比基于镜像MySQL日志量要少7.7倍。

总体来讲,Aurora 存储计算分离的架构带来了如下好处:(1)在云上部署,所有节点之间只传输 redo,网络压力小。(2)前后台线程互不干扰,后台任务可以不停歇的异步执行。(3)存储节点跨 AZ 高可用。(4)读副本、存储节点可线性扩展(有上限)。(5)故障恢复时间快。

2.2.2 一致性保证

从 MySQL 到 Aurora,单机系统进化为分布式系统,那么存储节点与数据库实例之间就需要保证数据一致性(consistency)。 Aurora 强调,传统保证分布式一致性的方法 2PC 协议复杂且容错性非常差,Aurora 依赖Quorum + Gossip 协议及基于 LSN 的算法来保证一致性。

我其实不太理解 Aurora 为啥要在论文中 cue 一下 2PC,虽然 2PC 能解决它的一致性问题,但是一般人肯定不会在这种场景下使用 2PC。一来,事务提交管理这种会改变数据库状态的操作主实例控制,也就意味着整个系统的一致性完全由主实例单机决定,存储节点只需要告知主实例其持久化结果,这一点和和单机数据库没有区别,看不出来哪里需要分布式的两阶段提交协议。二来,相较于分布式事务提交,Aurora 存储节点只有 redo 持久化这一个简单需求,没有其他资源的要求(例如:锁、事务上下文创建等),也没有提交结束释放资源的需求,完全没必要上 2PC。

说白了,要不要用 2PC 就是看数据库的状态变化由谁控制,存储节点虽然持久化了,但是数据库状态的变化,完全由事务管理器来控制。需要两阶段提交的情况是,事务处理器分布在不同节点(这样大大提高可了写扩展性),大家就事务应该提交还是回滚做出协商。

比较有意思的对比倒是在大部分系统都倾向于使用 Paxos/Raft 这样的共识算法,在底层实现一个强一致的存储系统来保证高可用时(例如 PolarDB, Spanner, OB...),Aurora 只是使用简单的 Quorum ,计算层和存储层结合起来实现高可用强一致。

以上是个人思考,其实在 Aurora 这种事务逻辑和单机数据库几乎没有区别的数据库,正常情况下,一致性保证没什么区别。主要的区别在于,数据库实例宕机重启时,需要这些宕机前未执行完的事务,决定哪些数据页中未完成的事务,应该提交还是回滚。因为单机数据库恢复依据的是单份日志,而 Aurora 需要从多个存储节点获得的多份日志,Aurora 需要决定哪些日志需要回放,哪些需要截断。

Aurora 事务都是由主实例发起的,因此主实例可以按时间顺序为每一个 redo 日志分配一个 Log Sequence Number(LSN)。为了保证一致性,Aurora 定义了如下几个关键日志点位。

Volume Complete LSN(VCL),表示存储层拥有 VCL 前的所有完整日志。故障恢复时,需要销毁所有 LSN 大于 VCL 的日志。

Consistency Point LSNs(CPLs),MySQL(InnoDB) 的事务由内部多个 Mini-Transaction 组成,每个 Mini-Transaction 是原子操作的最小单位。例如 B+-Tree 分裂需要修改多个 page,它们必须是原子的,必须由一组原子的 redo 日志来表示。CPL 是 Mini-Transaction 的最后一个日志的 LSN,日志回放时,需要以 CPL 为单位。一个事务通常由多个 CPL 组成。

Volume Durable LSN(VDL),所有 CPLs 中已经持久化的最大 LSN,它代表了数据库处于一致状态的最新位点,VDL 一定小于等于 VCL。为了保证 Mini-Transaction 的原子性,所有大于 VDL 的日志也需要被销毁。在故障恢复阶段,数据库实例通过 Quorum 读可以计算得到最新的 VDL。

举个例子,VCL=1007,CPLs={900,1000,1100},那么 1000 以后的日志都应该被截断。

3.PolarDB

PolarDB 是阿里云推出的云原生数据库,虽然都是计算存储分离架构,但是与 Aurora 在设计理念上有非常大的区别。

3.1 关键问题

PolarDB 在许多公开的分享和文章中,强调了传统数据库架构上云,存在很多问题,这里列举一些典型的:

扩展性相关:

  1. 由于物理机磁盘限制以及备份等策略,数据库的数据大小不能太大,太大的实例是运维的灾难。

  2. 活动上线时造成压力突增,而数据库却来不及升级。

  3. 业务发展很快,来不及进行拆库,也来不及分库分表。

性能相关:

  1. 传统备份技术,由于涉及到拷贝数据,并上传廉价存储,速度因此也受网络影响。一次全量数据备份需要大量时间,并且必须锁表等。

  2. 读写实例和只读实例各自拥有一份独立的数据,新建一个只读实例需要重新拷贝数据,考虑到网络限流,速度不会很快。

  3. MySQL数据库早期的版本,对早期的系统/硬件做了很多优化,但是并没有考虑到现代主流的系统/硬件的优秀特性,在高并发环境下,性能还有很大的提升空间。

  4. MySQL为了兼容性,需要写两份日志(事务日志和复制日志),与其他商业数据库相比,性能相对较差。

  5. 读写实例和只读实例通过增量逻辑数据同步,读写实例上所有的SQL需要在只读实例上重新执行一遍(包括SQL解析,SQL优化等无效步骤),同时,复制并发读最高是基于表维度,导致主备延迟非常普遍,进而影响各种切换任务。

  6. 应用扩容之后,上百台ECS连接一台数据库,因此在高并发下性能很差。

成本相关:

  1. 读写实例和只读实例各自拥有一份独立的数据,用户购买只读实例,不仅需要付出计算的成本,也需要付出存储资源的成本。

....

这些问题本质上都是单机数据库所面临的的问题,数据库上云,当然就是要解决这些问题。但是仅仅简单的将单机数据库部署在云上,这些问题还是存在的。PolarDB 的研发就是为了解决这一系列问题。

当然,我认为 Aurora 也是能够解决上述大部分问题的,只是 PolarDB 选择的技术路线与 Aurora 截然不同。

3.2 核心技术

3.2.1 存储计算分离架构

PolarDB 同样采用存储计算分离架构,计算节点是一个 MySQL 实例负责存储 SQL 解析、事务处理等,存储节点是 PolarDB 的核心组件 PolarStore,负责数据可靠存储。同一个集群的多个计算节点(1个读写实例和多个只读实例)共享一份数据,正因为如此,扩展只读实例的速度和成本都非常低。数据库实例的高可用通过只读实例在 failover 时迅速转变为读写实例保证,数据的高可用和一致性由 PolarStore 内部实现的 Parallel-Raft(支持乱序提交,性能比 raft 更好) 保证。

计算节点与存储节点采用高速网络互联,并通过RDMA协议进行数据传输,使网络不再成为瓶颈。

编辑搜图

PolarDB 的设计重点是一套高性能的分布式文件系统 PolarFS,能够向多个数据库实例提供高性能、高可靠的数据存取服务(支持同时挂载)。

3.2.2 PolarFS

PolarFS 是一个极低延迟,高可靠,利用了大量新硬件的分布式文件系统,对外的接口是 libpfs,数据库通过这一层与 PolarFS 交互。

PolarFS 存储层次上可以分为三级:Volume,Chunk,Block。用户创建 PolarDB 数据库实例时,系统就会为该实例创建一个 Volume,其大小范围可以是 10G~100T。每个 Volume 由多个 Chunk 组成,Chunk 是数据移动/高可用/分布式的最小单位,其必落在某块 SSD 盘上。每个 Chunk 大小为 10GB,远大于其他分布式文件系统(GFS为64MB)。这样做可以减少 Volume 到 Chunk 映射的元数据量大小,更有利于管理与缓存。不足之处在于热点不易打散。每个 Chunk 都有3 个副本,通过 ParallelRaft 协议保证高可用。Chunk 被进一步划分为 163,840 个 Block,每个块大小为 64KB。是预分配空间的最小单位。

PolarFS 的主要组件包括:

libpfs: 用户空间文件系统(User Space File System)库,是计算节点访问底层存储的API接口。

PolarSwitch :部署在计算节点的Daemon,负责将 IO 请求转化为对具体 ChunkServer leader 的访问。

ChunkServer :用于管理 Chunk,处理 Block IO 请求。一个存储节点可以部署多个 ChunkServer,每个ChunkServer 绑定一个CPU核,管理一块独立的 NVMe SSD 盘,ChunkServer 之间没有资源竞争。Chunk 修改会先 WAL,保证原子性和持久性。ChunkServer使用了 3D XPoint SSD 和普通 NVMe SSD 混合型WAL buffer,Log 会优先存放到更快的 3DXPoint SSD 中。

PolarCtrl :系统的控制平面,是PolarFS集群的控制核心,负责监控和 Balance ChunkServer、各种元信息维护、更新 PolarSwitch 元信息缓存等。

编辑搜图

PolarFS的写操作流程大致如下:

  1. POLARDB 通过 libpfs 发送写请求经由 ring buffer 到 PolarSwitch。

  2. PolarSwitch 根据本地缓存元数据,将写请求发送至对应 Chunk 的 Chunk Server Leader 节点。

  3. 请求到达 ChunkServer 后,节点的 RDMA NIC 将 Request 加入 request 队列。一个 IO 轮询线程不断轮询该请求队列,一旦发现有新请求则立即开始处理。

  4. IO 处理线程异步将请求写到 Chunk 对应的 WAL 块上(通过 SPDK),同时将请求异步发向给 Follower 节点。

  5. 写请求到达 Follower 后,同样通过 RDMA NIC 将其放到 request 队列。

  6. Follower 节点上的 IO 轮询线程被触发,同样异步写入。

  7. Follower 节点的写请求成功,通过 RDMA 向 Leader 发送应答。

  8. Leader节点收到 Followers 里任一节点成功应答后,即形成 majority,同样通过 SPDK 将写请求写到相应的数据块。

  9. Leader 通过 RDMA NIC 向 PolarSwitch 返回请求处理结果。

  10. PolarSwitch 标记请求成功并通知 POLARDB 数据库实例。

PolarFS 读写使用 SPDK 直接通过 DMA 操作 SSD,而非 OS 内核 IO 协议栈,通过轮询的方式监听硬件设备 IO完成事件。IO 线程和 CPU 核绑定,也不共享任何数据结构,相互之间没有竞争。这种 bypass OS IO 协议栈的方式,大大提升了高速设备的 IO 处理性能。同时通过 RDMA 网络大大提升网络 IO 性能。基本解决了 HDFS 和Ceph 等分布式文件系统存在的性能差、延迟大的问题。

3.2.3 物理复制

PolarDB 读写实例和只读实例共享一份数据,需要保证一致性,例如读写实例新写的 Page,即使没有刷脏,只读实例也应该可以看到。因此实例之间应当有一定的同步机制(为了保证主备之间的一致性,)。

MySQL 有两种主要日志: Binlog 和 InnoDB 的 Redo log。Binlog 是 tuple 级的数据变更日志,方便 MySQL 易构存储引擎之间同步数据,也方便下游消费。Redo log,记录的是文件物理页面的修改,是 InnoDB 为了支持事务的 ACID 特性。

Binlog 是 tuple 级别的,只读实例回放的效率太低,回放过程中只读实例可能还得去请求一些自己根本不需要的 Page。Redo log 显然是更合适做主备之间的数据同步。并且,使用 Binlog 复制目前只能按表级别并行复制,而物理复制可以按照数据页级别并发,粒度更细,并行效率更加高,主备之间的延迟可以保持在毫秒级别。同时在 Binlog 非必须的情况下,关闭 Binlog 也会对性能带来提升。

所有节点共享一份全量数据和 Redo log,增加只读节点非常容易,主备之间的同步只需要元数据即可。这使得系统在主节点发生故障进行 Failover 时候,切换到只读节点的故障恢复时间能缩短到 30 秒以内。

通过物理复制保证主备节点之间的一致性,其实有非常复杂的算法和策略去解决各种各样可能出现不一致的 case,这里就不详述了,可以阅读这篇 http:// mysql.taobao.org/monthl y/2017/09/01/

4.Socrates

4.1 关键问题

Socrates 是 Azure 在 SQL Server 基础上研发的云原生数据库,依旧采用计算存储分离的架构,和 Aurora 相比,分离的更加彻底,在存储层又将 Page 和日志存储分开,目的是将持久化和高可用分离。

Azure 认为云上的基于 log 主备同步的 SQL DB(RDS)存在以下几个主要问题:

编辑搜图

  1. 数据容量受到单机存储能力的限制。

  2. 超大事务可能打爆本地磁盘。

  3. Backup/Restore、新拉节点等操作的成本,和数据的体量成正比。

  4. 每个节点保存全量的数据,导致弹性能力较差。

微软为了解决这些问题,设计了一种新型的云原生数据库,在计算存储分离架构的基础上,进一步分离存储层,将 Log 从存储层分离出来,单独设计高性能 log 服务。从更高的层面来讲就是实现持久性(Durability,由日志实现)和高可用性(Availability,由存储层实现)分离。绝大部分数据库这两个能力均是由存储层提供的。

Socrates 分离这两个概念的思路在于: (1)持久化不完全需要昂贵的存储设备 (详见5.2.2) 。(2)高可用不完全需要跟多副本 (例如常规的3副本,详见 5.2.3)。

如果把这俩概念的需求分开,那么 Socrates 就需要(1)更少昂贵的告诉存储资源和计算资源,(2)更少的数据拷贝。那么他具体是怎么做的呢?

4.2 核心技术

Socrates 将数据库的各个组件拆成独立服务,提供不同的能力。并尽量使用异步的方式通信,减少响应时间,加快处理速度。Socrates 大体由 4 个组件组成

编辑搜图

4.2.1 计算节点

和上述两种云原生数据库一样,Socrates 计算层包括一个读写实例和多个只读实例。读写实例如出现故障,则某个只读会被选为新的读写实例。

如上面架构图所示,数据库实例如果需要读取本都未缓存的 Page,需要通过 GetPage@LSN(实际上是 GetPage(PageID, LSN)) 的 RPC 从响应的 Page Server 获取。PageID 是 Page 的唯一标识,LSN 则告诉 Page Server 需要返回 应用此 LSN 或者更新的 Page。

一个简单的例子:

  • 读写实例在本地缓存更新 Page X 。

  • 某种原因,本地 Buffer Pool 中 Page X 被淘汰(需要保证其修改已经 flush 到 XLOG)。

  • 读写实例再次读 Page X。

为了保证可以读到最新版本的 Page X,需要指定的 LSN。读写实例向 Page Server 发送 GetPage(X, X_LSN) 请求,Page Server 会等待所有小于 X_LSN 的日志都 Apply 完成了再返回 Page X。读写节点维护了一个 PageID -> Page LSN 的映射。

读写实例和只读实例之间没有直接交互,只读节点收到的日志,全部是 XLOG 广播过来的。只读节点收到后需要回放,回放过程中如果遇到相应 Page 不在 Buffer Pool,会直接丢弃。但是它也提供了另一种策略:从 Page Server 获取 Page 并回放,这就保证了主备之间缓存大体一致,当发生 failover 时,会更加稳定。

4.2.2 XLOG

编辑搜图

XLOG 是 Socrates 日志服务层,上图展示了 XLOG 服务的内部实现。

首先,读写节点直接将日志同步写到 Landing Zone(LZ) ,一个快速持久化存储服务,以降低写入延迟,它由 Azure 高级存储服务 (XIO) 实现,为了保证可靠性,数据也是三副本存储。

同时,读写节点异步写日志到 XLOG Process,该进程将日志传送到 Page Server 和只读节点。LZ 存在的目标仅是为了持久性,而非可用性,可用性由 Page Server 和计算节点保证。

读写节点并行写日志到 LZ 和 XLOG Process。因此,日志可能在 LZ 持久化之前到达只读节点,可能会在故障发生时,出现数据不一致的情况。为此 XLOG Process 只广播已在 LZ 中持久化的日志。读写节点首先将日志写入到 XLOG Process 的 Pending Blocks,一旦日志持久化成功,XLOG Process 将它从 Pending Blocks 移动到LogBroker 用于广播分发。

后台还有一个 Destaging 线程,将已经持久化的日志移动到本地 SSD 缓存,以实现快速访问。同时移动到XStore 长期归档保存(Long-Term Archieve, LT)。XStore 使用廉价存储,成本低、速度慢。LZ 和 LT 保存了所有的日志,共同实现持久化的目标。Socrates 默认将日志记录保留30天,用于指定时间点恢复和灾难恢复。显然,在 LZ 中保留 30 天的日志,成本非常高,XStore 可以完美接替这个任务。

LZ 快速但昂贵,有利于事务快速提交,XStore 廉价但慢,有利于节省成本。

4.2.3 Page Server

Page Server 主要负责三件事

  • 通过回放日志,管理数据库分区

  • 响应计算节点的 GetPage 请求

  • 打 Checkpoint 和向 XStore 备份

每个 Page Server 只需要关心和自己存储的 Page 相关的日志,日志中会增加充分的注释信息,标明日志记录需要应用到哪些分区中。XLOG Process 利用这些信息,可以为日志找到目标 Page。

Page Serve 和计算节点一样,也使用RBPEX(Resilient Buffer Pool Extention)。但计算节点缓存是传统数据库的缓存方式:缓存最热 Page 达到最好的性能。而 Page Server 缓存本分区的所有 Page。这对 GetPage 请求的性能非常友好,并且可以容忍 XStore 一定时间宕机。

新拉起一个 Page Server 也非常方便,RBPEX 缓存异步建立,同时 Page Server 可以接受请求和应用日志了。因为每个 Page Server 管理的数据并不大,恢复起来还非常快的。高可用通过数据单副本和廉价存储一份数据来共同实现。

4.2.4 XStore

数据库所有的数据保存在 XStore 中,Page Server 相当于是其一份缓存。XStore 是一个廉价、跨 AZ 高度复制的存储系统,几乎不会丢数据。XStore 相当于传统数据库中硬盘,计算节点和 Page Server 的内存和 SSD 缓存(RBPEX),相当于传统数据库的内存。

总体来讲,XLOG + XStore 实现了持久性,计算节点 + Page Server 实现高可用性。

5.对比

对比下来,Aurora 是云原生数据库的先驱,首次将数据库的存储和计算能力分割,并且将部分数据库的能力下沉到存储节点(主要是 Redo),大大减少数据的传输量,以提升性能和效率。Socrates 则在其之上更近一步,将数据库的组件拆的更加细,行成多个服务层。这种架构更加灵活,可用性和成本的控制粒度更细,可以帮助系统在保证性能和可用性的情况下,大幅控制成本。(并不是说 Socrates 比 Aurora 先进,Aurora 近几年发展非常快,在 Multi-Master、Serveless 等领域都有一定的突破,在云数据库领域依旧处于领先地位)

虽然 PolarDB 也是存储计算分离架构,多个节点共享一份数据,但它的切面与 Aurora/Socrates 不同,存储层是借助各种新硬件能力,保证高可靠、高性能的分布式文件系统,然后多个节点挂载在上面。PolarDB 认为高速网络和各类新硬件的发展让网络不再是大瓶颈,而瓶颈是在软件自身,因此做了大量的工作适配新新硬件,使用 OS-bypass 和 zero-copy 的技术提高 CPU 使用效率。PolarDB 这样的架构其实更容易跟进开源社区的新版本,因为计算层的功能性改动并不是特别大,主要是适配新的存储和物理复制等。

至于这两种方式谁更好,那就仁者见仁了。


本公司销售:阿里云新/老客户,只要购买阿里云,即可享受折上折优惠!>

我有话说: