PolarDB-X 一致性共识协议 (X-Paxos)

 

凌云时刻 · 技术

导读:近几年 NewSQL 和云原生数据库的不断兴起,极大地推动了关系数据库和一致性协议的结合,PolarDB-X 也是在这样的背景下应运而生。

作者七锋

来源|阿里云数据库

背景

分布式一致性算法(Consensus Algorithm)是一个分布式计算领域的基础性问题,其最基本的功能是为了在多个进程之间对某个(某些) 值达成一致(强一致),进而解决分布式系统的可用性(高可用)。Paxos 是最重要的分布式一致性算法,很多人都把它作为“分布式一致性协议”的代名词(Mike Burrows, inventor of the Chubby service at Google, says that"there is only one consensus protocol, and that's Paxos")。

回顾 Paxos 的理论从 1990 年提出到现在已经有近 30 年了,但是真正工业级、独立的 Paxos 基础库还是相当的少见。Google 并没有开源其任何 Paxos 基础库(连包含 Paxos 的项目都没有开源过);Facebook 也没有公布过包含 Paxos 的产品;Apache 有 Zookeeper,但是其协议并不能支持一个高吞吐的状态机复制,且并没有提供独立的第三方库,可供快速接入;在 Github 上能找到的 Paxos 的独立库,star 数最高是腾讯云开源的 phxpaxos 库,18 年之后也基本没有更新。

近几年 NewSQL 和云原生数据库的不断兴起,极大地推动了关系数据库和一致性协议的结合,PolarDB-X 也是在这样的背景下应运而生。

X-Paxos 诞生和发展

2014 年,阿里随着业务的高速增长,同城主备部署的方式已经无法满足阿里对可扩展的部署、国际化、以及容灾方面的需求,“异地多活”成为了公司应用的新标准。基于这样的业务背景驱动,PolarDB-X 早期,在阿里集团 MySQL 设计了分布式一致性协议模块,并把它独立命名为 X-Paxos,基于单机 MySQL 实现了一致性能力,配合 TDDL 分库分表的模式部分解决了业务诉求。随着技术的不断发展和演进,以及面向云的时代的全面普及,我们 PolarDB-X 2.0 中融合了分布式 SQL 引擎和基于 X-Paxos 的数据库存储技术,提供全新的云原生分布式数据库。

在 PolarDB-X 2.0 中,我们也进一步扩展了分布式和 Paxos 的协同,比如多副本的一致性读、副本的动态迁移和管理能力等。反过来,PolarDB-X 有了 X-Paxos 的加持,可以做到金融级数据库的高可用和容灾能力,做到 RPO=0 的生产级别可用性。Paxos 协议对于面向云的架构是非常必要的,云的本质是虚拟化和资源池化,节点的变化和弹性是一个常规操作,我们需要解决面向用户透明运维的能力,任何情况下数据都不能丢、不能错。

除此以外,X-Paxos 除了为数据库解决了分布式一致性问题,同样可以快速赋予其他系统分布式一致性能力。我们把 Paxos 的能力独立成一个基础库,希望能够把这个能力带给更多的其他系统。ps. 我们也做过快速的尝试,把 X-Paxos 融入到单机 KV 数据库 RocksDB 中,就可以很快速实现了一个分布式 KV 引擎。

Google 的论文《Paxos made live》中有一段话说的很好,大意是说:Paxos 从理论到现实世界的实现之间有巨大的鸿沟,在真正实现一个 Paxos 的时候,往往需要对 Paxos 的经典理论做一些扩展,(尤其是在实现一个高性能的 Paxos 的时候,扩展点就更多了,可以参考后文的功能增强和性能优化),这往往会导致真正的 Paxos 实现其实都是基于一个未被完全证明的协议。这也就是传说中,理论证明一个 Paxos 的实现,比实现这个 Paxos 还要难的原因了。因此一个成熟的 Paxos 实现很难独立产生,往往需要和一个系统结合在一起,通过一个或者多个系统来验证其的可靠性和完备性。这也是为什么大部分成熟的 Paxos 案例都是和分布式数据库相结合的,例如最早的 Paxos 实现(Chubby),当前的主要 Paxos 案例(Google 的 MegaStore、Spanner,AWS 的 DynamoDB、S3 等)。而 X-Paxos 正是依托于 PolarDB-X 验证了其可靠性和完备性。

X-Paxos 整体架构

X-Paxos 的整体架构如上图所示,主要可分为网络层、服务层、算法模块、日志模块 4 个部分。

 网络层

网络层基于 libeasy 网络库实现。libeasy 的异步框架和线程池非常契合我们的整体异步化设计,同时我们对 libeasy 的重连等逻辑进行了修改,以适应分布式协议的需求。

 服务层

服务层是驱动整个 Paxos 运行的基础,为 Paxos 提供了事件驱动,定时回调等核心的运行功能。每一个 paxos 实现都有一个与之紧密相关的驱动层,驱动层的架构与性能和稳定性密切相关。

X-Paxos 的服务层是一个基于 C++11 特性实现的多线程异步框架。常见的状态机/回调模型以其开发效率低,可读性差等缺点,一直被开发者所诟病;而协程又因其单线程的瓶颈,而使其应用场景受到限制。C++11 以后的新版本提供了完美转发(argument forwarding)、可变模板参数(variadic templates)等特性,为我们能够实现一种全新的异步调用模型提供了可能。

例如这是 X-Paxos 内实际的一行创建单次定时任务的代码:

new ThreadTimer(srv_->getThreadTimerService(), srv_, electionTimeout_, ThreadTimer::Oneshot,
                &Paxos::checkLeaderTransfer, this, targetId, currentTerm_.load(), log_->getLastLogIndex());

以上一行程序,包含了定时器的创建,任意回调函数的设置,回调函数参数的转发,并保证在回调触发后(Oneshot)内存的自动回收。

 算法模块

X-Paxos 当前的算法基于强 leadership 的 multi-paxos [3]实现,大量理论和实践已经证明了强 leadership 的 multi-paxos,性能好于 multi-paxos/basic paxos,当前成熟的基于 paxos 的系统,都采用了这种方式。

算法模块的基础功能部分本文不再重复,感兴趣的同学可以参考相关论文[1,2,4]。在基础算法的基础上,结合阿里业务的场景以及高性能和生态的需求,X-Paxos 做了很多的创新性的功能和性能的优化,使其相对于基础的 multi-paxos,功能变的更加丰富,性能也有明显的提升。后面将对这些优化进行详细的介绍。

 日志模块

日志模块本是算法模块的一部分,但是出于对极致性能要求的考虑,我们把日志模块独立出来,并实现了一个默认的高性能的日志模块;有极致性能以及成本需求的用户,可以结合已有的日志系统,对接日志模块接口,以获取更高的性能和更低的成本。这也是 X-Paxos 作为高性能独立库特有的优势,后面也会对这块进行详细介绍。

X-Paxos 特色功能

 在线添加/删除节点,在线转让 leader

X-Paxos 在标准 multi-paxos 的基础上,支持在线添加/删除多种角色的节点,支持在线快速将 leadership 节点转移到其他节点(有主选举)。这样的在线运维能力,将会极大地方便分布式节点的有计划性的运维工作,将 RTO 降低到最低。

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

阿里目前多地架构会有中心机房的诉求,比如:应用因其部署的特点,往往要求在未发生城市级容灾的情况下,仅在中心写入数据库,数据库的 leader 节点在正常情况下只在中心地域;同时又要求在发生城市级容灾的时候(同一个城市的多个机房全部不可用),可以完全不丢失任何数据的情况下,将 leader 点切换到非中心。

而经典的 multi-paxos 并不能满足这些需求。经典理论中,多数派强同步以后即可完成提交,而多数派是非特定的,并不能保证某个/某些节点一定能得到完整的数据,并激活服务。在实际实现中,往往地理位置较近的节点会拥有强一致的数据,而地理位置较远的节点,一直处于非强一致节点,在容灾的时候永远无法激活为主节点,形同虚设。

同时当中心单节点出现故障需要容灾的时候,往往需要将主节点就近切换到同中心的另外一个节点,而经典理论中同样没有类似的功能。

X-Paxos 在协议中实现了策略化多数派权重化选主

1. 基于策略化多数派,用户可以通过动态配置,指定某个/某些节点必须保有强一致的数据,在出现容灾需求的时候,可以立即激活为主节点。

2. 基于权重化选主,用户可以指定各个节点的选主权重,只有在高权重的节点全部不可用的时候,才会激活低权重的节点。

 节点角色定制化(Proposer/Accepter/Learner 的独立配置)

在经典的 multi-paxos 实现中,一般每个节点都包含了 Proposer/Accepter/Learner 三种功能,每一个节点都是全功能节点。但是某些情况下我们并不需要所有节点都拥有全部的功能,例如:

1. 经典的三个副本部署中,我们可以裁剪其中一个节点的状态机,只保留日志(无数据的纯日志节点,但是在同步中作为多数派计算),此时我们需要裁剪掉协议中的 Proposer 功能(被选举权),保留 Accepter 和 Learner 功能。

2. 我们希望可以有若干个节点可以作为下游,订阅/消费协议产生的日志流,而不作为集群的成员(不作为多数派计算,因为这些节点不保存日志流),此时我们裁剪掉协议的 Proposer/Accepter 功能,只保留 Learner 功能。

当然还有其他的组合方式,通过对节点角色的定制化组合,我们可以开发出很多的定制功能节点,即节约了成本,又丰富了功能。比如下面的三副本部署,其中一个 Follower 节点配置为仅做 logger 模式(参与多数派投票,但不存储数据),这样可以将三副本的 3 份数据成本优化为只有 2 份:

 Witness SDK

基于上节节点角色定制化中的单独 Learner 角色的功能,引发了无穷的想象力。Learner 角色,可以抽象成一个数据流订阅者(Witness Node),整个集群中可以加入无数个订阅者,当有新的日志被提交的时候,这些订阅者会收到其关心的日志流,基于订阅者功能,我们可以让一个集群很容易的实现下游订阅消费,日志即时备份,配置变更推送等等的功能。

因此我们把 Learner 角色单独封装成了一个 SDK。基于这个 SDK,用户可以快速的为自己的集群添加,订阅注册,流式订阅定功能;结合特定的用途打造一个完成的生态。采用了 X-Paxos 也可以利用 Witness SDK 快速实现分布式系统和下游的其他系统的对接,形成一个完整的生态。

 Leader 主动回切

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

 多连接

传统方式 leader 和 learner 之间采用单连接同步数据,在跨 IDC 场景中,网络延时往往比较大,会导致 leader 和 learner 之间的数据差异较大。leader 和 learner 之间通过多连接并发的发送数据,可以有效提升吞吐,减少数据差异,在弱一致的模式下,可以更好地对外提供读能力。同时在单 IDC 出现完全不可用的情况下,提供更好的灾备能力。

X-Paxos 性能优化

 Batching & Pipelining

X-Paxos 除了设计之初的强一致和高可用以外,其高性能也是至关重要的,尤其是应用于 PolarDB-X 分布式数据库,对协议的吞吐和延迟都提出了很高的要求。同时作为可全球部署的分布式一致性协议,在高延迟下的性能挑战变得尤为重要。

X-Paxos 针对高延迟网络做了大量的协议优化尝试和测试,并结合学术界现有的理论成果[5,6,7]通过合理的 Batching 和 Pipelining,设计并实现了一整套自适应的针对高延迟高吞吐和低延迟高吞吐网络的通信模式,极大地提升了 X-Paxos 的性能。

1. Batching 是指,将多个日志合并成单个消息进行发送;Batching 可以有效的降低消息粒度带来的额外损耗,提升吞吐。但是过大 Batching 容易造成单请求的延迟过大,导致并发请求数过高,继而影响了吞吐和请求延迟。

2. 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 的内部状态复杂,实现高效的单实例多线程的 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 个弊端:

1. 默认的日志模块提供通用的功能,很难结合具体的系统做针对性的优化。

2. 现有的系统往往已经存在了 WAL(Write Ahead Log),而 Paxos 协议中需要再存一份。这使得 a) 单次 commit 本地需要 sync 2 次(影响性能);b) 双份日志浪费了大量的存储。

例如:phxpaxos 内置的日志模块采用 LevelDB,作为日志系统其操作大量冗余,无针对优化;同时采用 phxpaxos 的 phxsql 单节点需要即保存 binlog,又保存 paxos log(在独立的 phxbinlogsvr 中),会有性能性能、以及浪费存储空间。而采用 X-Paxos 的 MySQL 存储引擎可直接改造现有的 binlog 模块,对接到 X-Paxos 的日志模块,单节点仅一份日志,既降低了存储,又提高了性能。

X-Paxos 正确性验证

《Paxos made live》中有过一个说法,证明一个 Paxos 实现是正确的,比实现这个 Paxos 本身会更难。因此我们在设计和实现 X-Paxos 的时候,投入了大量的精力在 Paxos 的原理证明和实现验证。

 Jepsen

Jepsen 是开源社区比较公认的分布式数据库的测试框架。Jepsen 验证过包括 VoltDB、CockroachDB、Galera、MongoDB、etcd 在内的几乎所有的主流分布式数据库/系统,检验出了不少的问题。

X-Paxos 完成了和 Jepsen 的对接,并验证了各个分布式数据库已有的 case。

 TLA+

TLA+ 是 Paxos 创始人、图灵奖获得者 Leslie Lamport 老爷子发明的一种形式化规约语言。TLA+ 专用于设计、建模和验证分布式并发系统。Amazon DynamoDB/S3/EBS 和 Microsoft Cosmos DB 都通过 TLA+ 的模型验证发现了不少问题。

X-Paxos 目前已经通过了 TLA+ 的模型验证。

 随机异常系统

我们搭建了一套自动随机异常验证系统,可以自动化验证各种异常场景下的协议正确性和稳定性。验证 X-Paxos 在模拟网络丢包、闪断、隔离,磁盘故障等情况下的功能正确和数据一致。

 异常回归系统

X-Paxos 拥有一套异常 case 回归系统,对于曾经出现过或者预期的并发异常 case,都会加到异常 case 库中,进行日常回归验证。同时异常 case 库也在不断的丰富中。

未来

Paxos 是分布式系统的基石,即使是近几年,学术界关于 Paxos 的文章,新的演进方向一直在不断的涌现,我们的 PolarDB-X 分布式数据库也会在 X-Paxos 的基础上不停的发展,比如多分区 Paxos、基于 Paxos 多副本的 HTAP 架构以及 Geo-Partition 的特性等。

参考文档

[1] The part-time parliament

[2] The Chubby lock service for loosely-coupled distributed systems

[3] Paxos Made Simple

[4] Paxos Made Live - An Engineering Perspective

[5] Everything You Ever Wanted to Know About Message Latency

[6] Adaptive Batching for Replicated Servers

[7] Tuning Paxos for high-throughput with batching and pipelining

[8] The Totem single-ring ordering and membership protocol

[9] Group Replication: A Journey to the Group Communication Core

[10] Mencius: Building Efficient Replicated State Machines for WANs

END

新年礼物第四弹,精品机械键盘抽奖中!!

邀请伙伴助力中奖几率翻倍

开奖时间:2021 年 1 月 25 日

赶紧转发至朋友圈,呼唤好友一起

抽  奖 吧 !


长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

相关推荐