前些天我发了一篇解读信通所分布式数据库发展报告内容的文章,有些朋友对我把Aurora、AlloyDB、PolarDB等也归类于分布式数据库感到有些不解。实际上这是信通所在报告里的归类,和国际上的常见归类方法也是一致的。通过认真研究其架构特点,我们也可以发现,实际上这些数据库产品(或者严格说是数据库服务产品)对传统集中式数据库进行了解耦和负载下载处理,与我们传统意义上的集中式数据库读写分离已经是完全不同的了,只是从我们的使用习惯上感受到好像这个数据库和我们使用的集中式数据库并无不同。
今天我就以谷歌的AlloyDB为例,分析一下此类数据库的一些技术特点。今年4月的GOOGLE I/O上,AlloyDB应该是一个十分亮的亮点。从谷歌官网上也可以看出对AlloyDB的一些自信。
以仅仅谷歌可以提供的方式来使用PostgreSQL,是不是够狂,把亚马逊的Aurora放哪去了?把那么多PG生态的分布式数据库都放在什么位置?实际上上图已经点出了Alloy DB的成功要点,PostgreSQL数据库+云原生架构+惊人优秀的工程团队+AI/ML的基因是成就AlloyDB的四个关键。根据谷歌发布的性能,AlloyDB比原生态PG在OLTP场景上处理性能高出4倍,而对于OLAP场景,则是100倍。虽然目前还没有正式的测试结果,业内普遍认为,在OLTP场景上,AlloyDB比Aurora在处理性能上高2倍以上,而在OLAP场景上,则呈现秒杀的局面。
AlloyDB是如何做到这一点的呢?我们的数据库厂商是不是也可以充分学习AlloyDB的经验,来进一步优化我们的数据库产品呢?实际上,AlloyDB也是全面学习了亚马逊的Aurora的“日志就是数据库服务”的理念而研发出来的数据库服务产品,并结合自身的优势,发扬光大了Aurora的优势,切实弥补了Aurora的不足。在官网上说,AlloyDB 结合了 Google 的横向扩展计算和存储、行业领先的可用性、安全性和 AI/ML 支持的管理与完全 PostgreSQL 兼容性(基于PG 14.4),以及性能、可扩展性、可管理性。如果用更为通俗的语言来表达就是,AlloyDB保持了与PostgreSQL的全兼容,并在横向扩展和计算能力以及可用性、安全性上充分利用了谷歌云的分布式架构。并且充分利用了AI/ML技术。
亚马逊的Auora出现于2014年,是一个真正云原生的数据库产品,虽然其数据库服务的RDBMS本身是基于MySQL和PostgreSQL这两个开源数据库,不过其充分利用了云存储的多副本复制与多ZONE高可用特性,创建了一种非对称读写分离的新型数据库服务架构。而8年后,作为后来者,AlloyDB在此基础上又有了很多值得我们学习的创新。
我们先来看看AlloyDB的一些技术特性。从高可用上,AlloyDB实现了连带维护工作耗时在内的真正的99.99%的高可用,并通过准确的自动检测,AlloyDB可以在绝大多数故障场景中,在几分钟内实现故障恢复,并且与数据库的负载和大小无关。通过内存中的列模式缓冲,AlloyDB可以支持较为复杂的HTAP场景。
AlloyDB的特性来源于其独特的架构设计。我们先来看看AlloyDB的一张读写流的示意图。
AlloyDB在一个区域里可以划分为多个安全区,其主库和只读从库分别位于不同的AZ。这个架构和Aurora十分类似,都是使用了共享块存储。不过如果仔细看这张图,我们会发现一些在Aurora或者一些国产的模仿者中不同的地方。AlloyDB 存储层是一个分布式系统,由三个主要部分组成: 1)低延迟的区域日志存储服务,用于非常快速的预写日志 (WAL) 写入;2)处理这些 WAL 记录并生成“物化”数据库块 的日志处理服务(LPS);3)容错、分片的区域块存储,即使在区域存储发生故障的情况下也能确保持久性。
我们重点来看LPS,这是AlloyDB与Aurora不同的主要地方,AlloyDB对LPS做了很好的优化,主实例中的WAL数据以流的方式实时传输给其他的副本,用于更新副本的SHARED BUFFERS,这种更新方式比起副本完全依靠WAL重演来还原最新数据要高效的多,也可以避免因为主实例中出现大量修改而引起副本重演延时过大的问题。
另外这种架构下,BGWRITER或者类似openGauss的PAGEWRITER没有了,被LPS完全替代了。主实例只需要将WAL数据流写入低延时的日志存储就可以了,数据文件的变更是完全依靠日志文件重演来实现的。也就是说一旦数据库创建,今后所有的PAGE的变化都基于WAL STREAM,因此困扰PG数据库十多年的FULL PAGE WRITE的问题也就消失了,这种结构下,永远不需要FULL PAGE WRITE和CHECKPOINT了。
上面是AlloyDB的写入流程,我们可以看到,只需要把WAL写入LOG STORE就可以了,没有BGWRITER,不需要考虑CHECKPOINT的优化,没有FULL PAGE WRITE,一切都由LPS搞定。
而对于读操作来说,由于LPS的存在,因此读操作上可能会有一定的性能损失,因为读路径的路径比传统的方式长了一些。所有的计算与存储分离架构的数据库都会或多或少的加长读取的路径,因此都会对读取性能有些影响。因此AlloyDB采用了十分激进的缓冲策略,希望通过更高的缓冲命中率来抵消这方面的缺点。实际上在激进的缓冲策略方面,谷歌全系列产品都如此,谷歌在这方面积累了丰富的经验,因此AlloyDB 也不例外。除了数据库缓冲区之外,AlloyDB 还在计算实例中添加了“超高速缓存”。这个缓冲区十分类似Oracle的FlashCache,其目的是为了让被DB CACHE淘汰的数据能够在此二次缓冲,避免通过较长的读取路径去读取。因此Ultra-fast Cache被设计为本地的,这一点也和Oracle的FlashCache类似。Ultra-fast Cache让更多的数据能够从本实例的缓冲中获得,因此大大减轻由于SHARED BUFFERS没有命中数据块导致的IO路径上的各种损失。同样值得注意的是,DB CACHE中未命中的数据块是从LPS获取的,而不是从块存储服务获取的。LPS除了具备处理WAL的能力外,还支持PostgreSQL的buffer cache接口。它这样做是为了缓存来自块存储服务的数据块,并将它们提供给主实例和副本实例。因此,LPS有效地成为架构中的另一个缓存层。
作为一个存算分离的分布式数据库系统,AlloyDB在设计上的创新还没有到头,因为LPS统一了持久化服务,将传统PG的bgwriter/walwriter的功能以及前台进程统一为一个服务,同时截断了backend访问PAGE的读取路径,因此真正彻底的把计算层和存储层分离了。
在这个架构里,LPS变成了整个数据库的性能要点,因为 LPS 既需要持续应用 WAL 记录,又需要服务来自主实例和多个副本实例的读取请求。为了解决这个问题,数据库持久层被水平划分为称为分片的块组。分片和 LPS 资源都可以水平且独立地扩展。每个分片会被固定分配给一个 LPS,但每个 LPS 可以处理多个分片。分片到 LPS 的映射是动态的,允许存储层通过扩展 LPS 资源的数量和重新分配分片来弹性地进行扩充。这不仅允许存储层扩展吞吐量,还可以避免热点。
谷歌官方网站给出了两个参考场景:第一个例子是当整体系统负载增加,几乎所有分片都收到比以前更多的请求。在这种情况下,存储层可以增加 LPS 实例的数量,例如将它们加倍。然后,新创建的日志处理服务器实例通过接管它们的一些分片来卸载现有实例。由于这种分片重新分配不涉及任何数据复制或其他昂贵的操作,因此它非常快速且对数据库层不可见。
另一个例子是一小部分分片突然在系统中变得非常热的时候,同样存储层可以动态做出反应——在最极端的情况下,如果发现有某个分片过热,访问流量不均匀,则可以通过将某个负载超高的分片分配给专门处理分片负载的专用 LPS 实例来避免过热的分片的性能不足。因此,通过重新分片和 LPS 弹性,即使在工作负载高峰的情况下,系统也可以提供高性能和吞吐量,并且在工作负载再次减少时也可以减少其资源占用。对于数据库层和最终用户,这种动态调整大小和存储层弹性是完全自动的,不需要用户操作。这是AI4DB能力的极好的应用。
AlloyDB的存储层是采用多副本的,其三副本数据位于不同的ZONE,并且确保每个区域都有自己的完整数据库状态副本,因此数据库层的块查找操作不需要跨越区域边界。此外,存储层在所有区域中持续应用 WAL 记录,数据库层为其请求的每个块提供目标版本 LSN,因此在读取操作期间无需读取仲裁,在享受分布式横向扩展的同时也享受到了类似于集中式数据库的便捷性。
总而言之,AlloyDB通过解耦数据库的计算层和存储层来获得较强的横向扩展能力,并通过LPS将许多数据库读写操作卸载到存储层。即使在存储层,完全分解的架构也允许它作为一个弹性的分布式集群工作,可以动态适应不断变化的工作负载,增加容错能力,提高可用性,并启用具有成本效益的读取池,以线性扩展读取吞吐量。卸载还有效提升了主实例的写入吞吐量,因为它可以完全专注于查询处理并将维护任务委托给存储层。而这种能力来自于AlloyDB 的智能、数据库感知存储层在AI技术上的使用。我想这些设计思想都会给我们的国产数据库厂商带来一种新的数据库设计思路,分布式数据库在总体架构上不一定非要完全学习Oracle,也可以脱离Oracle的技术框架,充分利用开源代码来走一条新路。
从今天的描述,可能有些朋友已经发现了AlloyDB与传统的集中式数据库的不同了。目前我们的国产数据库也在学习Aurora,不过学的还不够彻底,最主要的是存算解耦还不够彻底,负载无法从计算层更好的卸载到存储层,这和我们还没有能力彻底改造计算存储两层之间的接口,使之变成可横向扩展的服务有关。