PolarDB-X作为PolarDB分布式版,是阿里巴巴自主设计研发的高性能云原生分布式数据库产品,为用户提供高吞吐、大存储、低延时、易扩大和超高可用的云时代数据库服务。PolarDB-X在架构上能够简略分为CN节点和DN节点。计算节点CN负责SQL的解析和执行,存储节点DN负责数据的分布式事务和高可用存储。本文次要对存储引擎外围中高可用局部具体技术解读。

背景

传统的存储引擎高可用次要采纳主备同步的形式,然而主备同步形式人造存在以下限度:

  • 高性能与数据一致性的取舍:主备复制采纳强同步形式会导致主库写入性能升高,采纳异步形式无奈保障主库宕机时备库无损提供一致性保障,半同步形式尽管能无效缓解性能升高,但同样无奈提供严格的一致性保障
  • 零碎可用性:主备库形式在面临网络故障或提早较大场景时,可能会存在主库迟迟无奈提交事务,不能及时主备切换,从而影响零碎的可用性

针对主备库形式的问题,以后业界次要采纳基于多正本的高可用存储引擎计划。PolarDB-X同样基于该路线,自研了分布式一致性协定模块 X-Paxos,并将其与MySQL引擎深度联合,造成了PolarDB-X的多正本高可用存储引擎。

个性

下图是PolarDB-X多正本存储节点的根本架构,展现了一个部署三个正本的PolarDB-X DN集群。PolarDB-X DN集群是一个单点写入,多点可读的集群零碎。在同一时刻,整个集群中至少会有一个Leader节点来承当数据写入的工作。PolarDB-X DN节点的每个实例都是一个单过程的零碎,X-Paxos被深度整合到了数据库内核之中,替换了原有的复制模块。集群节点之间的增量数据同步通过X-Paxos来驱动实现,不再须要内部手动指定复制位点。

总的来说,PolaDB-X多正本存储引擎具备以下个性:

  • 强一致性保障:X-Paxos基于强Leadership的Multi-Paxos实现,大量实践和实际曾经证实了强Leadership的Multi-Paxos,性能好于Multi-Paxos/Basic-Paxos。PolarDB-X在解体复原时的一致性问题上更是做了深刻的保障
  • 高性能的数据同步:具备Batching/Pipelining形式的高效日志传输,具备多线程异步的高效数据传输,具备X-Paxos日志和Binlog交融的极致精简对立
  • 灵便的运维容灾:在线增加/删除/权重化配置任意节点,具备手动/主动选主的灵便策略
  • 低成本的数据存储:翻新引入Logger角色正本,让三正本具备最低两份存储的数据存储开销

上面针对以上个性别离进行深刻解读。

原理

强一致性保障

强一致性保障次要依赖X-Paxos模块,上图展现的X-Paxos整体架构,整体可分为网络层、服务层、算法模块、日志模块4个局部:

  • 网络层:基于libeasy网络库实现。libeasy的异步框架和线程池十分符合咱们的整体异步化设计,同时咱们对libeasy的重连、日志等逻辑进行了批改,以适应分布式协定的需要
  • 服务层:驱动整个Paxos运行的根底,为Paxos提供了事件驱动,定时回调等外围的运行性能。每一个paxos实现都有一个与之严密相干的驱动层,驱动层的架构与性能和稳定性密切相关。
  • 算法模块:一致性协定的外围,包含基于强Leadership的Multi-Paxos实现的选主模块,采纳预读缓冲区/热缓冲区的数据管理模块,复用Enhanced Multi-Threaded Slave技术的同步传输利用模块,以及扩大sync_relay_log_info零碎表的集群元数据模块。
  • 日志模块,本来是算法模块的一部分,出于对极致性能要求的思考,咱们把日志模块独立进去,并实现了一个默认的高性能的日志模块。

如果说算法模块是运行时强一致性的保障,那么日志模块就是容灾时的强一致性保障。 日志模块和Binlog极致耦合,同时也是保护解体复原逻辑的要害局部。Paxos多正本强统一算法网上介绍很多,这里不再论述。咱们重点阐明下PolarDB-X中的日志模块实现。

日志模块

在原有的MySQL主备复制模式中,Master节点负责写入binary log,并提交事务。Slave节点通过IO线程从Master节点发动dump协定拉取binary log,并存储到本地的relay log中。最初由Slave节点的SQL线程负责回放relay log。 默认状况Slave节点除了产生relay log,还会依据log-slave-updates有一份冗余的binary log。

PolarDB-X存储节点整合了binary log和relay log,实现了对立的consensus log,节俭了日志存储的老本。当某个节点是Leader的时候,consensus log表演了binary log的角色;同理当某个节点被切换成Follower/Learner时,consensus log表演了relay log的角色。新的consensus log基于一致性协定和State Machine Replication实践,保障了多个节点之间的数据一致性。

日志模块也接管consensus log的同步逻辑,勾销Relay IO线程,复用Relay SQL线程和Relay Worker线程,反对MTS多线程并行回放。同时提供对外的接口来实现日志写入和状态机回放。

依据算法模块和Binlog的依赖,日志模块引入了四种日志类型:

  • Consensus Log Event:标记在每个事务的Anonymous_GTID日志之前,用于记录以后事务对应协定层index、term、flag等元信息
  • Previous Consensus Index Event:写在每个binary log文件的最开始,Format_description events之后,Previous_gtids events之前,用于标记以后文件起始的事务index
  • Consensus Cluster Info Log Event:记录多正本集群配置变更的信息
  • Consensus Empty Log Event:记录X-Paxos协定选主日志

PolarDB-X日志模块同样革新了MySQL原有事务提交的流程。MySQL的Group Commit分为三个阶段:flush stage、sync stage、commit stage。对于多正本的Leader节点,PolarDB-X DN节点在 Binlog 的 Flush 和 Sync 过程中将携带Consensus Log Event的Binlog 内容同时播送到所有 Follower。所有进入commit stage的事务会被对立推送到一个异步队列中,进入quorum决定的断定阶段,期待事务日志同步到少数节点上,满足quorum条件的事务才容许commit,以保证数据的强统一。

此外,为了保障高性能,Leader上consensus log的本地写入和日志同步能够并行执行对于Follower节点,SQL线程读取consensus log,期待Leader的告诉。Leader会定期同步给Follower每一条日志的提交状态,达成多数派的日志会被分发给worker线程并行执行。

在事实利用场景中,Follower 和 Leader 的状态机难免会存在回放提早,比方一个大的 DDL 会导致 Follower 的回放提早被有限放大,而如果在回放提早存在的状况下 Leader 挂掉新主选出时,新主无奈对外提供服务,而此时老 Leader 可能曾经重启复原,所以在这种状况下 X-Paxos 会被动探测状态机的健康状况,如果在一段时间内回放提早无奈追平,则会尝试 Leader 被动回切,让没有回放提早的老 Leader 对外提供服务。

复原逻辑

PolarDB-X的多正本存储引擎的复原流程和原生MySQL大不相同,不同在Binlog参加的复原流程,须要X-Paxos协定层参加,并且须要重点解决原生MySQL XA 的不完整性问题。

PolarDB-X的多正本存储引擎的复原的流程如下:

  1. 扫描Binlog文件
  • 扫描consensus日志的完整性, 不残缺的日志须要整体切除。
  • 收集记录残缺提交Binlog的事务,构建提交事务的hash表

1)确认最初一次实例存活时产生的Binlog文件。以用作复原悬挂事务的根据
2)必须保障所有悬挂的事务都是在最初一个Binlog中,即便产生过切主
3)relay log 也必须保障没有悬挂事务, 因为这里会波及到前一个作为主的任期的悬挂事务

  1. 扫描InnoDB,取得所有的悬挂事务, 如果不在提交事务hash表,那么回滚
  2. 期待X-Paxos启动,推动回放位点,依据回放位点确定悬挂事务的是否提交

a. 如果回放之前节点是处于Binlog WORKING 状态,并且协定层也是leader role(leader 宕机复原),则意味着协定层没有降级,那么能够判断为是在写入的状态下宕机复原, 此时须要从零碎表的last_leader_term 字段中依据最初是leader的term来遍历日志, 从此term最初一条日志后开始作为回放终点。
b. 如果回放前节点是处于Binlog WORKING 状态,协定层曾经不是leader role(协定leader降级,或者是降级后server状态未变更时宕机),则意味着协定层曾经降级,在降级的时候把commit index 写入了start_apply_index。 此时就从start_apply_index前面的一条日志开始回放。
c. 如果回放前节点是处于RELAY LOG WORKING状态,协定层也是非leader(每次重启非leader的回放线程),则这意味着此实例始终是一个非leader, 那么找到slave_relay_log_info 表中记录的consensus_apply_index 作为回放位点
d. 如果回放前节点是处于RELAY LOG WORKING状态,然而协定层曾经切换到了leader (协定follower降级,或者是降级过程中server状态未变更时宕机),则这意味着此实例始终是一个非leader, 那么找到slave_relay_log_info 表中记录的consensus_apply_index 作为回放位点

  1. 启动apply 线程,实现复原流程
  2. 关上MySQL监听端口

MySQL XA 实现了一套两阶段提交协定,以便在分布式事务零碎中应用,但原生的 MySQL XA 存在完整性问题,如果在分布式场景中,Node1, Node2 ... NodeN 作为节点参与方,XA 应用 2PC 保障分布式事务的原子性,但对于每个节点中的 Binlog Storage 和 InnoDB Storage 两个参与方,MySQL 目前没有机制保障在每个阶段(Prepare 或者 Commit) 不同 Storage 参与方之间的一致性,这也源于Binlog Storage 自身没有 UNDO 的机制保障无关,这样 2PC 的解体复原协定也就无奈取得无效的节点事务状态。

为了保障严格的强一致性保障,PolarDB-X多正本存储引擎除了应用两阶段提交协定的 External Coordinator 以外,引入了应用 GTID 弥补协定的 Internal Coordinator 来保障 Storage 之间的一致性。

GTID 弥补协定的次要工作原理:

  • 在单个节点解体复原阶段,依据 Binlog File 构建 Binlog GTID 汇合;
  • 在单个节点解体复原阶段,依据 InnoDB GTID_EXECUTED 以及 TRANSACTION UNDO HISTORY 构建 InnoDB GTID 汇合
  • 构建汇合的差集,应用 Binlog Event 进行弥补 InnoDB 失落的事务,复原单个节点
  • 实现单个节点的弥补后,XA 组件开始分布式集群的两阶段提交事务的解体复原

高性能数据同步

高吞吐的日志传输

X-Paxos针对高提早网络做了大量的协定优化尝试和测试,并联合学术界现有的实践成绩通过正当的Batching和Pipelining,设计并实现了一整套自适应的针对高提早高吞吐和低提早高吞吐网络的通信模式,极大地晋升了X-Paxos的性能。

Batching是指将多个日志合并成单个音讯进行发送;Batching能够无效地升高音讯粒度带来的额定损耗,晋升吞吐。然而过大Batching容易造成单申请的提早过大,导致并发申请数过高,继而影响了吞吐和申请提早。
Pipelining是指在上一个音讯返回后果以前,并发地发送下一个音讯到对应节点的机制,通过进步并发发送音讯数量(Pipelining数量),能够无效的升高并发单申请提早,同时在transmission delay小于propagation delay的时候(高提早高吞吐网络),无效晋升性能。

R为网络带宽,D为网络流传提早(propagation delay,约为RTT/2),经推导可知 Batching(音讯大小:M)和Pipeling(音讯并发:P)在M/R * P = D关系下,达到最高吞吐。

X-Paxos联合以上实践,通过内置探测,针对不同节点的部署提早,自适应地调整针对每个节点的Batching和Pipeling参数,达到整体的最大吞吐。因Pipeling的引入,须要解决日志的乱序问题,特地是在异地场景下,window加大,加大了乱序的概率。X-Paxos实现了一个高效的乱序解决模块,能够对底层日志实现屏蔽乱序问题,实现高效的乱序日志存储。

高效的数据传输

因为Paxos的外部状态简单,实现高效的单实例多线程的Paxos变成一个十分大的挑战。比方开源产品phxpaxos、Oracle MySQL Group Replication中应用的xcom,都是单线程的实现。phxpaxos采纳了单调配单线程,多实例聚合的形式晋升总吞吐,然而对单分区的性能十分的无限;xcom是一个基于协程的单线程实现。单线程的Paxos实现,在解决序列化/反序列化,散发、发包等逻辑的时候都为串行执行,性能瓶颈显著。

X-Paxos齐全基于多线程实现,能够在单个分区Paxos中齐全地应用多线程的能力,所有的工作都由通用的worker来运行,打消了CPU的瓶颈。依赖于服务层的多线程异步框架和异步网络层,X-Paxos除了必要的协定串行点外,大部分操作都能够并发执行,并且局部协定串行点采纳了无锁设计,能够无效利用多线程能力,实现了Paxos的单分片多线程能力,单分区性能远超竞品,甚至超过了竞品的多实例性能。

交融的日志模块

X-Paxos和现有的大部分Paxos库很大的不同点就是X-Paxos反对可插拔的日志模块。日志模块是Paxos中一个重要的模块,它的长久化关系到数据的一致性,它的读写性能很大水平上会影响协定整体的读写性能。以后大部分独立Paxos库都是内置日志模块,并且不反对插拔的。这会带来2个弊病:

  • 默认的日志模块提供通用的性能,很难联合具体的零碎做针对性的优化
  • 现有的零碎往往曾经存在了WAL(Write Ahead Log),而Paxos协定中须要再存一份。这使得
  • 单次commit本地须要sync 2次,影响性能
  • 双份日志节约了大量的存储,减少了老本

PolarDB-X存储节点整合了binary log和relay log,实现了对立的consensus log,既节俭了日志存储的老本,又进步了性能。日志交融的理论改变,后面强一致性保障中曾经详细描述,这里不再开展。

灵便的运维容灾

在线增加节点/删除节点/切主

X-Paxos在规范Multi-Paxos的根底上,反对在线增加/删除多种角色的节点,反对在线疾速将leadership节点转移到其余节点(有主选举)。这样的在线运维能力,将会极大中央便分布式节点的有计划性的运维工作,将RTO升高到最低。

策略化多数派/权重化选主

目前阿里多地架构会有核心机房的诉求,比方:利用因其部署的特点,往往要求在未产生城市级容灾的状况下,仅在核心写入数据库,数据库的leader节点在失常状况下只在核心地区;同时又要求在产生城市级容灾的时候(同一个城市的多个机房全副不可用),能够在齐全不失落任何数据的状况下,将leader点切换到非核心。

而经典的Multi-Paxos并不能满足这些需要。经典实践中,多数派强同步当前即可实现提交,而多数派是非特定的,并不能保障某个/某些节点肯定能失去残缺的数据,并激活服务。在理论实现中,往往地理位置较近的节点会领有强统一的数据,而地理位置较远的节点,始终处于非强统一节点,在容灾的时候永远无奈激活为主节点,形同虚设。 同时当核心单节点呈现故障须要容灾的时候,往往须要将主节点就近切换到同核心的另外一个节点,而经典实践中同样没有相似的性能。

PolarDB-X在X-Paxos协定中实现了策略化多数派和权重化选主:

  • 基于策略化多数派,用户能够通过动静配置,指定某个/某些节点必须保有强统一的数据,在呈现容灾需要的时候,能够立刻激活为主节点
  • 基于权重化选主,用户能够指定各个节点的选主权重,只有在高权重的节点全副不可用的时候,才会激活低权重的节点

低成本的数据存储

在经典的Multi-Paxos实现中,个别每个节点都蕴含了Proposer/Accepter/Learner三种性能,每一个节点都是全功能节点。然而某些状况下咱们并不需要所有节点都领有全副的性能,例如: 1. 经典的三个正本部署中,咱们能够裁剪其中一个节点的状态机,只保留日志(无数据的纯日志节点,然而在同步中作为多数派计算),此时咱们须要裁剪掉协定中的Proposer性能(被选举权),保留Accepter和Learner性能。 2. 咱们心愿能够有若干个节点能够作为上游,订阅/生产协定产生的日志流,而不作为集群的成员(不作为多数派计算,因为这些节点不保留日志流),此时咱们裁剪掉协定的Proposer/Accepter性能,只保留Learner性能。

多正本的技术尽管比主备同步的形式更加高性能和高可用,但多正本自身引入的多份数据存储开销难以避免的痛点。PolarDB-X多正本存储引擎深入研究了解协定发现,在经典的Multi-Paxos实现中,个别每个节点都蕴含了Proposer/Accepter/Learner三种性能,每一个节点都是全功能节点。然而某些状况下咱们并不需要所有节点都领有全副的性能,例如:

  • 经典的三个正本部署中,咱们能够裁剪其中一个节点的状态机,只保留日志(无数据的纯日志节点,然而在同步中作为多数派计算),此时咱们须要裁剪掉协定中的Proposer性能(被选举权),保留Accepter和Learner性能。
  • 咱们心愿能够有若干个节点能够作为上游,订阅/生产协定产生的日志流,而不作为集群的成员(不作为多数派计算,因为这些节点不保留日志流),此时咱们裁剪掉协定的Proposer/Accepter性能,只保留Learner性能。

PolarDB-X翻新地引入Learner/Logger角色正本,通过对节点角色的定制化组合,咱们能够开发出很多的定制性能节点,既节约了老本,又丰盛了性能。

典型的三节点复制模式如下图所示。通过对节点角色的定制化组合,在三正本部署,一个节点持续作为全功能正本Leader,一个节点持续作为Follower,另外一个Follower节点配置为仅做Logger角色,这样能够将三正本的三份数据老本优化为只有两份,同时不影响高可用的保障。再借助PolarDB-X残缺兼容的MySQL Binlog,能够无缝兼容OSS、DTS、Canal等业内罕用的Binlog增量订阅工具,实现数据的异地低成本备份。

作者:冷香、严华

点击立刻收费试用云产品 开启云上实际之旅!

原文链接

本文为阿里云原创内容,未经容许不得转载。