内附原文|详解SIGMOD’24最佳论文:PolarDB如何破解多主架构经典难题?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
简介: 在今年的SIGMOD会议上,阿里云瑶池数据库团队的论文《PolarDB-MP: A Multi-Primary Cloud-Native Database via Disaggregated Shared Memory》获得了Industry Track Best Paper Award,这是中国企业独立完成的成果首次摘得SIGMOD最高奖。PolarDB-MP是基于分布式共享内存的多主云原生数据库,本文将介绍这篇论文的具体细节。

在今年的SIGMOD会议上,阿里云瑶池数据库团队的论文《PolarDB-MP: A Multi-Primary Cloud-Native Database via Disaggregated Shared Memory》获得了Industry Track Best Paper Award这是中国企业独立完成的成果首次摘得SIGMOD最高奖。PolarDB-MP是基于分布式共享内存的多主云原生数据库,本文将介绍这篇论文的具体细节。

背景

现如今,对于支持写扩展的多主云原生数据库的需求日益增长。多主架构的数据库不仅可以支持写扩展,同时还可以提供更高的高可用性,并且能够更好地在serverless数据库中提供计算节点的弹性。目前,主流的多主数据库大多是基于share-nothing和share-storage架构。在share-nothing架构中,当一个事务需要访问多个分区时,必须使用分布式事务机制,如两阶段提交策略。这通常会引入显著的额外开销。此外,当系统需要扩容或缩容时,数据可能需要重新分区,这个过程常常伴随着繁重且耗时的数据迁移。而share-storage架构则完全相反,所有数据都可以从所有节点访问。这种架构下不需要使用分布式事务,每个节点都可以独立处理事务。DB2 pureScale和Oracle RAC是基于共享存储的两个传统数据库。它们通常部署在专用机器上,并且成本通常比当下云原生数据库更高。Aurora-MM和Taurus-MM是最近提出的云原生多主数据库。Aurora-MM采用乐观并发控制来处理写冲突,因此在发生冲突时会引发较多的事务中止。相反,Taurus-MM采用悲观并发控制,但是它在不同节点同步数据的效率较低,在高冲突场景下,扩展性不高。


为了应对当前多主数据库面临的这些问题,我们设计并实现了PolarDB-MP,利用分布式共享内存池来解决现有架构的挑战。

PolarDB-MP的整体架构

下图展示了PolarDB-MP的架构,不同于其他基于共享存储的多主数据库。PolarDB-MP引入了基于分布式共享内存的Polar Multi-Primary Fusion Server(PMFS)来实现对多主架构的支持。PMFS包括三个核心组件:事务融合(Transaction Fusion)、缓存融合(Buffer Fusion)和锁融合(Lock Fusion)。Transaction Fusion旨在管理全局事务处理,保证事务的ACID属性。Buffer Fusion在维护所有节点间的缓存一致性中扮演着至关重要的角色。Lock Fusion负责两种锁协议:页面锁(PLock)和行锁(RLock)。PLock协议确保在不同节点上访问页面时的物理一致性。RLock协议保证用户数据的事务一致性。此外,PolarDB-MP提出了逻辑日志序列号(LLSN)来对不同节点的redo log(write-ahead log)进行排序。LLSN为不同节点生成的所有redo log提供了一个偏序关系。

0625-01.png

长图首页-不带button.png

设计实现

(1)事务融合(Transaction Fusion)

事务融合解决的第一个问题是时间戳的问题,PolarDB-MP采用了TSO(timestamp oracle)的方式。事务提交时,会从TSO请求一个提交时间戳(CTS)。这个CTS是一个逻辑上递增分配的时间戳,确保事务提交的有序性。CTS通常通过RDMA操作获取,通常在几微秒内完成,并且在我们的测试中发现它不会成为瓶颈。为了有效管理集群中的所有事务信息,PolarDB-MP采用了一种分散的方法将这些信息分布在所有节点中。PolarDB-MP中的每个节点都保留了一小部分内存来存储其本地事务信息。节点可以通过RDMA远程访问其他节点的事务信息。下图展示了这种设计。每个节点都在事务信息表(TIT)中维护其本地事务的信息。TIT在管理事务方面发挥着关键作用,它为每个事务维护四个关键字段:pointer、CTS、version和ref。pointer是内存中事务对象的指针,CTS标记事务的提交时间戳,version用于识别同一槽中的不同事务,ref用来表示是否有其他事务在等待此事务释放其行锁。

0625-02.png

当一个事务在某个节点上开始时,会为该事务分配一个本地递增的唯一ID。然后,为此事务分配一个空闲的TIT slot。由于TIT slot可以被重用,version字段用于区分不同时期占用同一slot的事务,每个新事务都会使版本递增。为了在集群维度识别一个事务,PolarDB-MP将node_id、trx_id、slot_id和version组合成一个全局事务ID(g_trx_id)。有了这个g_trx_id,任何节点都可以通过RDMA从目标节点远程访问其他节点的事务的CTS。在PolarDB-MP中,在更新某个记录时,会将全局事务ID(g_trx_id)存储在该记录的元数据中。当事务提交时,如果当前事务所修改的记录仍然在缓存中,会将事务的CTS写入到这些记录的元数据,否则它们的CTS仍然是默认值(CSN_INIT)。在判断记录的可见性时,如果该记录的CTS字段是一个有效值,而不是初始值(CSN_INIT)时,可以直接从该记录的元数据中获取CTS。如果该记录的CTS没有填充,则需要使用TIT来获取该记录的CTS。首先需要从该记录的元数据字段中获取修改这条记录的事务ID(g_trx_id)。然后可以使用这个g_trx_id获取相应的TIT slot。如果TIT中的version与正在检查的g_trx_id的version不匹配,表明TIT slot已被新的事务重用,意味着原始的事务已经提交。在这种情况下,我们可以返回一个最小的CTS值以表明该记录对所有事务都是可见的。这是因为只有当一个TIT slot的CTS小于所有活跃事务的read view时,该slot才会被释放并重用。如果slot的version和当前g_trx_id的version匹配时,说明这个slot还没有被其他事务重用,我们可以直接从slot中直接获取CTS。

(2)缓存融合(Buffer Fusion)

在PolarDB-MP中,每个节点都可以更新任何数据页(page),这导致不同节点之间频繁地传输数据页。为了实现高效的跨节点数据移动,PolarDB-MP提出了Buffer Fusion。每个节点可以将其数据页写入到Buffer Fusion的分布式缓存池(distributed buffer pool, DBP),随后其他节点可以从这个DBP访问其他节点修改过的页面。在这种情况下,页面可以在不同节点之间快速移动。下图展示了Buffer Fusion的设计。当DBP中存储了页面的新版本时,Buffer Fusion会将其他节点上的副本失效。这样,当这些节点需要访问该页面时,它们会从DBP中重新加载新的页面版本,确保所有操作都基于最新的数据状态进行,从而维持数据库的整体一致性。DBP的实现高度融合了RDMA,使得LBP和GBP之间的延迟非常低。

0625-03.png

(3)锁融合(Lock Fusion)

Lock Fusion实现了页面锁(PLock)和行锁(RLock)两种协议。PLock类似于单节点数据库中的页面锁,确保对页面的原子访问以及内部结构的一致性。另一方面,RLock用于维护跨节点的事务一致性,遵循两阶段锁协议。PLock确保在并发访问时,只有持有锁的节点才能对数据库页面进行读写操作,这样可以避免数据冲突和不一致的问题。RLock则更加关注事务的一致性,允许更细粒度的数据访问控制,并使用两阶段锁协议。


PLock(页面锁):PLock主要用于维护物理数据的一致性,解决跨节点并发访问数据页的问题。PLock在节点级别管理,如下图所示。每个节点跟踪它持有或正在等待的PLock,并用一个引用计数来指示使用特定PLock的线程数。Lock Fusion维护所有PLock的信息,跟踪每个锁的状态。节点在对页面执行任何更新或读取之前,必须持有相应的排他锁(X)或共享锁(S)PLock。当节点需要一个PLock时,它首先检查其本地PLock管理器,查看是否已经持有所需的锁或更高级别的锁。如果没有,它会通过基于RDMA的RPC从Lock Fusion请求PLock。Lock Fusion会处理这个请求。如果存在冲突,请求节点将被挂起,待其 PLock 请求可以被满足时再唤醒。此外,当节点释放PLock时,会通知Lock Fusion,随后更新锁的状态,并通知其他等待该PLock的节点。

0625-04.png

RLock(行锁):PolarDB-MP在每一行数据中直接嵌入行锁信息,并且只在Lock Fusion上维护等待关系。对于每一行,会增加一个字段来表示持锁事务的ID。当事务尝试锁定一行时,它只需将其全局事务ID写入此字段。如果行的事务ID字段已经被一个活跃事务占用,则检测到冲突,当前事务必须等待。在PolarDB-MP中,当尝试更新一行时,必须已经持有包含该行的页面上的排他锁(X PLock)。因此,只有一个事务可以访问写入行的锁信息,只有一个事务可以成功锁定这一行。类似于单节点数据库,RLock协议也遵循两阶段锁协议,即事务持有锁直到事务提交。这种设计减少了锁信息的管理复杂性和存储开销,因为不需要在一个中心节点位置维护所有的锁状态信息。通过直接在行中嵌入锁信息,可以快速检测和解决锁冲突,从而提高了事务处理的效率和数据库的整体性能。


下面的例子展示了行锁的设计,节点2上的事务T30试图对一行数据施加排他锁(X-lock)。通过检查该记录的元数据发现,该行已被另一个事务(T10)施加了X-lock。随后,T30首先远程设置T10的元数据中的引用(‘ref’)字段。这个操作表明有一个事务(T30)正在等待T10释放锁。然后,T30与Lock Fusion通信,发送有关其等待状态的信息。这些信息被添加到Lock Fusion中的等待信息表中。一旦T10完成其事务并提交,它会检查其‘ref’字段。发现有其他事务正在等待时,T10通知Lock Fusion它已经提交。Lock Fusion在收到T10的通知后,检查等待信息表,然后通知T30,此时T30可以被唤醒并继续其处理。

0625-05.png

(4)LLSN:保证redo log的顺序关系

在PolarDB-MP中,每个节点可以生成各自的redo log,导致多个节点对同一页面有不同的redo log。由于每个redo log记录了对特定页面所做的更改,崩溃恢复的关键在于按照它们生成的顺序回放同一页面的redo log,而来自不同页面的log可以按任意顺序应用。所以,我们不必维护所有redo log的全序关系,相反,只需要确保对应同一页面的redo log有序。


因此,PolarDB-MP引入了逻辑日志序列号(LLSN),为不同节点的日志建立了偏序关系,确保与同一页面相关的redo log按生成顺序维护。然而,LLSN不对来自不同页面的redo log保证先后顺序,这也是不必要的。为了实现这个设计,每个节点维护一个节点本地的LLSN,该LLSN在每次日志生成时自动递增。当节点更新页面并生成日志时,新的LLSN记录在页面元数据中,也分配给相应的日志。如果节点从存储或DBP读取页面,它会更新其本地LLSN以匹配访问页面的LLSN,前提是页面的LLSN超过了节点当前的LLSN。这确保了节点的LLSN与其访问的页面保持同步。随后,当节点更新页面并生成日志时,其LLSN递增,保证新的LLSN大于之前更新该页面的任何节点的LLSN。由于PLock设计,一次只有一个事务可以更新页面。因此,当一个页面在不同节点上依次更新时,LLSN有效地维持了日志的生成顺序。

实验分析

我们用多种不同的工作负载和不同的配置测试了PolarDB-MP的性能。由于篇幅限制,这里只列出了两组实验结果,更多完整实验分析可以参见论文原文。我们首先对比了PolarDB和华为Taurus多主的性能。在下图中,y轴代表吞吐量,而每个条形图上的数字表示可扩展性(相对于单节点性能的归一化吞吐量)。PolarDB-MP在单节点时与Taurus-MM的性能相当。然而,PolarDB-MP在多节点中的优势变得明显。例如,在read-write和read-only工作负载中,PolarDB-MP在八节点集群中的吞吐量分别是Taurus-MM的3.17倍和4.02倍

0625-06.png

我们进一步在只有10%的共享数据时对比了PolarDB-MP和Aurora-MM的性能。由于Aurora-MM仅支持最多4个节点,因此其8节点的结果被省略。即使在共享数据比例较低的情况下,Aurora-MM在read-write工作负载中从2节点增至4节点也没有显示出任何的性能提升;在write-only工作负载中,2和4节点的表现甚至不如单节点,这归因于Aurora-MM使用乐观并发控制。在这些冲突较轻的场景中,尽管Taurus-MM表现出比Aurora-MM更高的可扩展性,但它仍然落后于PolarDB-MP,尤其是在八节点集群中。在write-only负载下,4节点时,PolarDB-MP的扩展性是Aurora-MM的5.4倍。8节点时,PolarDB-MP的扩展性是Taurus-MM的2.2倍。

0625-07.png


更多细节可参阅论文原文,👉 点击下载

PolarDB多写架构已经上线阿里云,欢迎使用和测试。👉 点击前往


相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
7天前
|
负载均衡 算法 架构师
系统架构设计师-软件水平考试(高级)-论文-可靠性设计
系统架构设计师-软件水平考试(高级)-论文-可靠性设计
|
15天前
|
存储 关系型数据库 分布式数据库
重磅|顶会最高奖+1,阿里云PolarDB再获SIGMOD最佳论文奖
阿里云斩获SIGMOD 2024最佳论文,PolarDB成功破解经典多主架构难题
重磅|顶会最高奖+1,阿里云PolarDB再获SIGMOD最佳论文奖
|
25天前
|
边缘计算 Cloud Native
“论SOA在企业集成架构设计中的应用”必过范文,突击2024软考高项论文
SOA架构,即面向服务的架构,它将系统中的所有功能都拆分为一个个独立的服务单元。这些服务通过相互间的沟通与配合,共同完成了整体业务逻辑的运作。在SOA架构中有几个核心概念:服务提供者、服务使用者、服务注册中心、服务规范、服务合同,这些概念清晰地阐述了服务应如何被提
150 6
“论SOA在企业集成架构设计中的应用”必过范文,突击2024软考高项论文
|
30天前
|
关系型数据库 Serverless 分布式数据库
|
12小时前
|
负载均衡 监控 算法
微服务架构下的API网关模式与实践
在现代的后端开发中,微服务架构因其灵活性和可扩展性而受到青睐。本文深入探讨了API网关模式在微服务架构中的应用,并结合实例分析了API网关如何提高系统的可维护性和安全性。通过对比分析,文章展示了API网关在处理跨域请求、负载均衡、认证授权以及日志记录方面的显著优势。
8 0
|
18小时前
|
运维 Kubernetes 云计算
云计算时代的运维革新:容器化与微服务架构的融合之道
在云计算技术飞速发展的当下,企业IT运维面临前所未有的挑战与机遇。传统的运维模式已难以满足现代业务对敏捷性、可伸缩性和自动化的需求。本文深入探讨了容器化技术和微服务架构如何共同推动运维领域的革命,通过数据支持和科学分析,揭示了这一融合趋势如何提高运维效率、降低风险并促进创新。
|
18小时前
|
设计模式 监控 测试技术
后端开发中的微服务架构:优势、挑战与实践策略
在现代软件开发领域,微服务架构已成为一种重要的设计范式,特别是在后端系统中。本文旨在深入探讨微服务架构的核心优势、面临的主要挑战以及实施该架构的策略。通过引用最新的研究成果和行业案例,文章将提供对微服务架构实际应用的深刻见解,并指导开发者如何有效地采用和优化微服务架构以提升系统性能和可维护性。
|
19小时前
|
Kubernetes Java 微服务
使用Spring Boot构建微服务架构
使用Spring Boot构建微服务架构
|
2天前
|
Kubernetes 测试技术 持续交付
深入理解微服务架构及其在现代后端系统中的应用
本文将深入探讨微服务架构的核心概念、设计原则以及如何在现代后端系统中实现和优化它。我们将从微服务的定义开始,逐步展开讨论其优势、面临的挑战,以及如何克服这些挑战。同时,文章还会涉及微服务与容器化技术、持续集成/持续部署(CI/CD)的协同作用,以及微服务架构的未来发展趋势。读者将获得对微服务架构全面而深刻的理解,并能够识别在实施过程中可能遇到的陷阱和解决方案。
21 1
|
2天前
|
存储 监控 负载均衡
深入理解微服务架构中的服务发现机制
【6月更文挑战第25天】在微服务架构中,服务发现是确保各独立服务组件能够高效、可靠通信的关键环节。本文将探讨服务发现的基本原理、核心组件以及在现代云原生应用中的最佳实践,旨在为读者提供一套系统化理解和实现服务发现机制的指导思路。

相关产品

  • 云原生数据库 PolarDB