脚本宝典收集整理的这篇文章主要介绍了PolarDB PostgreSQL 架构原理解读,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。@H_304_0@背景
PolarDB PostgreSQL(以下简称PolarDB)是一款阿里云自主研发的企业级数据库产品,采用计算存储分离架构,兼容PostgreSQL与oracle。PolarDB 的存储与计算能力均可横向扩展,具有高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB 具有大规模并行计算能力,可以应对OLTP与OLAP混合负载;还具有时空、向量、搜索、图谱等多模创新特性,可以满足企业对数据处理日新月异的新需求。PolarDB 支持多种部署形态:存储计算分离部署、X-Paxos三节点部署、本地盘部署。
随着用户业务数据量越来越大,业务越来越复杂,传统数据库系统面临巨大挑战,如:
针对上述传统数据库的问题,阿里云研发了PolarDB云原生数据库。采用了自主研发的计算集群和存储集群分离的架构。具备如下优势:
下面会从两个方面来解读PolarDB的架构,分别是:存储计算分离架构、HTAP架构。
PolarDB是存储计算分离的设计,存储集群和计算集群可以分别独立扩展:
基于Shared-storage后,主节点和多个只读节点共享一份存储数据,主节点刷脏不能再像传统的刷脏方式了,否则:
对于第一个问题,我们需要有页面多版本能力;对于第二个问题,我们需要主库控制脏页的刷脏速度。
读写分离后,单个计算节点无法发挥出存储侧大IO带宽的优势,也无法通过增加计算资源来加速大的查询。我们研发了基于Shared-Storage的MPP分布式并行执行,来加速在OLTP场景下OLAP查询。 PolarDB支持一套OLTP场景型的数据在如下两种计算引擎下使用:
在使用相同的硬件资源时性能达到了传统Greenplum的90%,同时具备了SQL级别的弹性:在计算能力不足时,可随时增加参与OLAP分析查询的CPU,而数据无需重分布。
基于Shared-Storage之后,数据库由传统的share nothing,转变成了shared storage架构。需要解决如下问题:
首先来看下基于Shared-Storage的PolarDB的架构原理。
传统share nothing的数据库,主节点和只读节点都有自己的内存和存储,只需要从主节点复制WAL日志到只读节点,并在只读节点上依次回放日志即可,这也是复制状态机的基本原理。
前面讲到过存储计算分离后,Shared-Storage上读取到的页面是一致的,内存状态是通过从Shared-Storage上读取最新的WAL并回放得来,如下图:
上述流程中,只读节点中基于日志回放出来的页面会被淘汰掉,此后需要再次从存储上读取页面,会出现读取的页面是之前的老页面,称为“过去页面”。如下图:
只读节点在任意时刻读取页面时,需要找到对应的Base页面和对应起点的日志,依次回放。如下图:
通过上述分析,需要维护每个Page到日志的“倒排”索引,而只读节点的内存是有限的,因此这个Page到日志的索引需要持久化,PolarDB设计了一个可持久化的索引结构 - Logindex。LOGIndex本质是一个可持久化的hash数据结构。
通过LogIndex解决了刷脏依赖“过去页面”的问题,也是得只读节点的回放转变成了Lazy的回放:只需要回放日志的meta信息即可。
在存储计算分离后,刷脏依赖还存在“未来页面”的问题。如下图所示:
“未来页面”的原因是主节点刷脏的速度超过了任一只读节点的回放速度(虽然只读节点的Lazy回放已经很快了)。因此,解法就是对主节点刷脏进度时做控制:不能超过最慢的只读节点的回放位点。如下图所示:
如下图所示:
可以看到,整个链路是很长的,只读节点延迟高,影响用户业务读写分离负载均衡。
因为底层是Shared-Storage,只读节点可直接从Shared-Storage上读取所需要的WAL数据。因此主节点只把WAL日志的元数据(去掉Payload)复制到只读节点,这样网络传输量小,减少关键路径上的IO。如下图所示:
通过上述优化,能显著减少主节点和只读节点间的网络传输量。从下图可以看到网络传输量减少了98%。
在传统DB中日志回放的过程中会读取大量的Page并逐个日志Apply,然后落盘。该流程在用户读IO的关键路径上,借助存储计算分离可以做到:如果只读节点上Page不在BufferPool中,不产生任何IO,仅仅记录LogIndex即可。可以将回放进程中的如下IO操作offload到session进程中:
如下图所示,在只读节点上的回放进程中,在Apply一条WAL的meta时:
通过上述优化,能显著减少回放的延迟,比AWS Aurora快30倍。
在主节点执行DDL时,比如:drop table,需要在所有节点上都对表上排他锁,这样能保证表文件不会在只读节点上读取时被主节点删除掉了(因为文件在Shared-Storage上只有一份)。在所有只读节点上对表上排他锁是通过WAL复制到所有的只读节点,只读节点回放DDL锁来完成。而回放进程在回放DDL锁时,对表上锁可能会阻塞很久,因此可以通过把DDL锁也offload到其他进程上来优化回访进程的关键路径。
通过上述优化,能够回放进程一直处于平滑的状态,不会因为去等DDL而阻塞了回放的关键路径。
上述3个优化之后,极大的降低了复制延迟,能够带来如下优势:
数据库OOM、Crash等场景恢复时间长,本质上是日志回放慢,在共享存储Direct-IO模型下问题更加突出。
前面讲到过通过LogIndex我们在只读节点上做到了Lazy的回放,那么在主节点重启后的recovery过程中,本质也是在回放日志,那么我们可以借助Lazy回放来加速recovery的过程:
优化之后(回放500MB日志量):
上述方案优化了在recovery的重启速度,但是在重启之后,session进程通过读取WAL日志来回放想要的page。表现就是在recovery之后会有短暂的响应慢的问题。优化的办法为在数据库重启时BufferPool并不销毁,如下图所示:crash和restart期间BufferPool不销毁。
内核中的共享内存分成2部分:
而BufferPool中并不是所有的Page都是可以复用的,比如:在重启前,某进程对Page上X锁,随后crash了,该X锁就没有进程来释放了。因此,在crash和restart之后需要把所有的BufferPool遍历一遍,剔除掉不能被复用的Page。另外,BufferPool的回收依赖k8s。该优化之后,使得重启前后性能平稳。
PolaDB读写分离后,由于底层是存储池,理论上IO吞吐是无限大的。而大查询只能在单个计算节点上执行,单个计算节点的CPU/MEM/IO是有限的,因此单个计算节点无法发挥出存储侧的大IO带宽的优势,也无法通过增加计算资源来加速大的查询。我们研发了基于Shared-Storage的MPP分布式并行执行,来加速在OLTP场景下OLAP查询。
PolarDB底层存储在不同节点上是共享的,因此不能直接像传统MPP一样去扫描表。我们在原来单机执行引擎上支持了MPP分布式并行执行,同时对Shared-Storage进行了优化。 基于Shared-Storage的MPP是业界首创,它的原理是:
如图所示:
基于社区的GPORCA优化器扩展了能感知共享存储特性的Transformation Rules。使得能够探索共享存储下特有的Plan空间,比如:对于一个表在PolarDB中既可以全量的扫描,也可以分区域扫描,这个是和传统MPP的本质区别。图中,上面灰色部分是PolarDB内核与GPORCA优化器的适配部分。下半部分是ORCA内核,灰色模块是我们在ORCA内核中对共享存储特性所做的扩展。
PolarDB中有4类算子需要并行化,下面介绍一个具有代表性的Seqscan的算子的并行化。为了最大限度的利用存储的大IO带宽,在顺序扫描时,按照4MB为单位做逻辑切分,将IO尽量打散到不同的盘上,达到所有的盘同时提供读服务的效果。这样做还有一个优势,就是每个只读节点只扫描部分表文件,那么最终能缓存的表大小是所有只读节点的BufferPool总和。
下面的图表中:
倾斜是传统MPP固有的问题:
以上两点会导致分布执行时存在长尾进程。
需要注意的是:尽管是动态分配,尽量维护buffer的亲和性;另外,每个算子的上下文存储在worker的私有内存中,Coordinator不存储具体表的信息;
下面表格中,当出现大对象时,静态切分出现数据倾斜,而动态扫描仍然能够线性提升。
那我们利用数据共享的特点,还可以支持云原生下极致弹性的要求:把Coordinator全链路上各个模块所需要的外部依赖存在共享存储上,同时worker全链路上需要的运行时参数通过控制链路从Coordinator同步过来,使Coordinator和worker无状态化。
因此:
多个计算节点数据一致性通过等待回放和globalsnapshot机制来完成。等待回放保证所有worker能看到所需要的数据版本,而globalsnapshot保证了选出一个统一的版本。
我们使用1TB的TPCH进行了测试,首先对比了PolarDB新的分布式并行和单机并行的性能:有3个SQL提速60倍,19个SQL提速10倍以上;
另外,使用分布式执行引擎测,试增加CPU时的性能,可以看到,从16核和128核时性能线性提升; 单看22条SQL,通过该增加CPU,每个条SQL性能线性提升。
和传统MPP的Greenplum的对比,同样使用16个节点,PolarDB的性能是Greenplum的90%。
前面讲到我们给PolarDB的分布式引擎做到了弹性扩展,数据不需要充分重分布,当dop=8时,性能是Greenplum的5.6倍。
OLTP业务中会建大量的索引,经分析建索引过程中:80%是在排序和构建索引页,20%在写索引页。通过使用分布式并行来加速排序过程,同时流水化批量写入。
上述优化能够使得创建索引有4~5倍的提升。
PolarDB是对多模数据库,支持时空数据。时空数据库是计算密集型和IO密集型,可以借助分布式执行来加速。我们针对共享存储开发了扫描共享RTREE索引的功能。
本文从架构层面分析了PolarDB的技术要点:
后续文章将具体讨论更多的技术细节,比如:如何基于Shared-Storage的查询优化器,LogIndex如何做到高性能,如何闪回到任意时间点,如何在Shared-Storage上支持MPP,如何和X-Paxos结合构建高可用等等,敬请期待。
企业级分布式开源数据库 PolarDB for PostgreSQL-阿里云开发者社区
以上是脚本宝典为你收集整理的PolarDB PostgreSQL 架构原理解读全部内容,希望文章能够帮你解决PolarDB PostgreSQL 架构原理解读所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。