一文了解分布式一致性算法EPaxos

简介: 分布式系统一个核心的问题就是数据的一致性。Paxos算法是分布式一致性中的经典算法,用来解决一个分布式系统如何就某个值(决议)达成一致的问题。本文从Paxos的问题引出EPaxos,介绍EPaxos的基本概念与直观理解。阅读本文需要一些Paxos或Raft等分布式一致性算法背景。

image.png

引言

EPaxos(Egalitarian Paxos)作为工业界备受瞩目的下一代分布式一致性算法,具有广阔的应用前景。但纵观业内,至今仍未出现一个EPaxos的工程实现,甚至都没看到一篇能把EPaxos讲的通俗一点的文章。EPaxos算法理论虽好,但由于其实在晦涩难懂,工程实现上也有很多挑战,实际应用落地尚未成熟。

本文旨在通俗易懂地介绍EPaxos算法,由浅入深、一步一步的让只有Paxos或Raft等分布式一致性算法基础的同学都能轻易看懂EPaxos,真正将晦涩难懂的EPaxos,变的平易近人,带入千万家。

Paxos的问题

一切还要从Paxos说起。Paxos是分布式一致性算法的鼻祖,在2F+1个副本中可以容忍F个副本同时失效。

Paxos正常情况下达成一次决议需要两个阶段:Prepare阶段和Accept阶段。

Prepare阶段各副本竞争提议权,Accept阶段竞争到提议权的副本发起提议,让议案在各副本间达成一致。

使用Paxos对一系列值达成一致的流程如图1所示。三个副本,以不同颜色标识,A、B、C、D是它们提议的值。它们竞争每个Instance,提议自己的值:

image.png

Paxos独立的决定每个Instance的值。针对每个Instance,运行完整的Paxos两阶段流程,决定该Instance的值。

Paxos达成一次决议至少需要两次网络来回,在并发情况下可能需要更多的网络来回,极端情况下甚至可能形成活锁,效率低下。为了解决这些问题,Multi-Paxos应运而生。

Multi-Paxos在各副本中选举一个Leader,提议由Leader发起,没有竞争,解决了活锁问题。提议都由Leader发起的情况下,Prepare阶段可以跳过,将两阶段变为一阶段,提高效率。

使用Multi-Paxos对一系列值达成一致的流程如图2所示。三个副本,以不同颜色标识,首先进行Leader选举,绿色副本被选为Leader,然后连续提议A、B、C、D四个值:

image.png

Multi-Paxos首先选举Leader,Leader选出来后Instance的提议权都归Leader,无需竞争Instance的提议权,因此可以省略Prepare阶段,只需要一阶段。Leader的存在提高了达成决议的效率,但同时也成为了性能和可用性的瓶颈。

Leader需要处理比其它副本更多的消息,各副本负载不均衡,资源利用率不高。Leader宕机后系统不可用,直到新Leader被选举出来,才能恢复服务,降低了可用性。

Basic Paxos每个副本都能提议,可用性高,但因为竞争冲突导致效率低下;Multi-Paxos选举Leader避免冲突,提高效率,但同时又引入了Leader瓶颈,降低了可用性。效率和可用性能否兼顾?EPaxos正是为了解决此问题而提出。不同于Multi-Paxos引入Leader来避免冲突,EPaxos采用另一种思路,它直面冲突,试图解决冲突问题。

EPaxos的解决方案

EPaxos是一个Leaderless的一致性算法,任意副本均可发起提议,通常情况下,达成一次决议需要一次或两次网络来回。

EPaxos无Leader选举开销,一个副本不可用可立即访问其他副本,具有更高的可用性。各副本负载均衡,无Leader瓶颈,具有更高的吞吐量。客户端可选择最近的副本提供服务,在跨AZ跨地域场景下具有更小的延迟。

不同于Paxos,事先对所有Instance编号,然后再独立对每个Instance的值一一达成一致。EPaxos可并发的处理多个Instance,不事先对Instance编号,而是在运行时动态决定各Instance之间的顺序。

EPaxos不仅对每个Instance的值达成一致,还对Instance之间的相对顺序达成一致。EPaxos将不同Instance之间的相对顺序也作为一致性问题,在各个副本之间达成一致,因此各个副本可并发地在不同的Instance中发起提议,在这些Instance的值和相对顺序都达成一致后,各副本再对它们按照相对顺序重新排序,形成一致的顺序。

使用EPaxos对一系列值达成一致的流程如图3所示:三个副本,以不同颜色标识,各副本有自己的Instance空间,在各自的Instance中提议自己的值,A、B、C、D是它们提议的值。每个Instance不仅对值达成一致,还对与其它Instance之间的相对顺序达成一致。

image.png

EPaxos的Instance空间是二维的,每个副本拥有二维Instance空间中的一行,无需竞争Instance的提议权,各副本可并发的在各自的Instance空间中发起提议,同时维护Instance之间的相对顺序,对Instance的值和相对顺序都达成一致。最后各副本各自按照相对顺序对Instance进行确定性的重新排序,即对一系列值达成一致。

EPaxos引入依赖(deps)的概念,作为Instance的一个属性,以表示Instance之间的相对顺序。A ← B即B依赖A,表示A在B之前。每个Instance都有自己的依赖集合,EPaxos维护Instance之间的依赖,并让依赖集合与值一起在各副本之间达成一致,最后各副本按照依赖对Instance重新排序,得到一致的值序列。图3中的案例,最后各副本达成一致的一系列值为:A ← B ← C ← D。

将EPaxos的Instance看作图上的结点,Instance的依赖集合看作结点的出边,Instance的值和依赖集合达成决议后,图的结点和边就在各副本之间达成一致,因此各副本会看到到相同的图。

EPaxos对Instance重新排序的过程,类似于对图进行确定性的拓扑排序。但需要注意的是EPaxos的Instance之间的依赖可能形成环,即图中可能有环路,因此不完全是拓扑排序。

为了处理循环依赖,EPaxos对Instance重排序的算法需要先寻找图的强连通分量,环路都包含在了强连通分量中,所有强连通分量构成一个有向无环图(DAG),然后对强连通分量进行确定性的拓扑排序。

EPaxos对Instance重新排序的流程如图4所示,其中由背景色圈起来的是强连通分量:

image.png

寻找图的强连通分量一般使用Tarjan算法,它是一个递归算法,实际压测发现递归实现很容易爆栈,也给工程应用带来了一定的挑战。

不同强连通分量中的Instance按照确定性的拓扑顺序排序,同一强连通分量中的Instance是并发提议的,理论上可按任意确定性规则排序。EPaxos给出了一种方案,为每个Instance维护了一个seq序列号,seq的大小近似反映了Instance提议的顺序,期望全局唯一递增,同一强连通分量里面的Instance按照seq大小排序。实现的时候测试发现seq可能重复,EPaxos论文并未考虑到这一点,后续文章会更详细的介绍此问题与解决方案。

当有Instance达成决议,并且其依赖的所有Instance也都达成决议后,就可以开始一次排序过程。实际上,随着新的Instance不断的运行,旧的Instance可能依赖新的Instance,新的Instance又可能依赖更新的Instance,导致依赖链不断延伸,没有终结,排序过程一直无法进行,形成活锁。这也是EPaxos工程应用的一大挑战。

因为Instance排序算法是确定性的,各副本基于一致的依赖关系图对Instance重新排序后,得到一致的Instance序列,即对一系列值达成一致。

总结

EPaxos通过引入动态顺序,同时兼顾了效率和可用性,融合了Basic Paxos和Multi-Paxos的优点,具有广阔的应用前景。本文粗浅的介绍了EPaxos的基本概念和直观理解,希望能让读者对EPaxos有个整体印象。

思考

最后留下几个思考题,感兴趣的同学可以思考思考:

EPaxos的Instance没有事先编号,那Instance如何标识?

EPaxos如何确定Instance的依赖集合,又如何让依赖集合达成一致?
EPaxos的Instance之间的依赖为什么会形成环,什么情况下会形成循环依赖?

目录
相关文章
|
4天前
|
算法 关系型数据库 MySQL
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
在分布式系统中,确保每个节点生成的 ID 唯一且高效至关重要。Snowflake 算法由 Twitter 开发,通过 64 位 long 型数字生成全局唯一 ID,包括 1 位标识位、41 位时间戳、10 位机器 ID 和 12 位序列号。该算法具备全局唯一性、递增性、高可用性和高性能,适用于高并发场景,如电商促销时的大量订单生成。本文介绍了使用 Go 语言的 `bwmarrin/snowflake` 和 `sony/sonyflake` 库实现 Snowflake 算法的方法。
16 1
分布式唯一ID生成:深入理解Snowflake算法在Go中的实现
|
3月前
|
算法 Go
[go 面试] 雪花算法与分布式ID生成
[go 面试] 雪花算法与分布式ID生成
|
15天前
|
存储 缓存 算法
分布式缓存有哪些常用的数据分片算法?
【10月更文挑战第25天】在实际应用中,需要根据具体的业务需求、数据特征以及系统的可扩展性要求等因素综合考虑,选择合适的数据分片算法,以实现分布式缓存的高效运行和数据的合理分布。
|
16天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
1月前
|
算法
基于粒子群算法的分布式电源配电网重构优化matlab仿真
本研究利用粒子群算法(PSO)优化分布式电源配电网重构,通过Matlab仿真验证优化效果,对比重构前后的节点电压、网损、负荷均衡度、电压偏离及线路传输功率,并记录开关状态变化。PSO算法通过迭代更新粒子位置寻找最优解,旨在最小化网络损耗并提升供电可靠性。仿真结果显示优化后各项指标均有显著改善。
|
1月前
|
消息中间件 缓存 算法
分布式系列第一弹:分布式一致性!
分布式系列第一弹:分布式一致性!
|
1月前
|
算法 Java 关系型数据库
漫谈分布式数据复制和一致性!
漫谈分布式数据复制和一致性!
|
3月前
|
存储 算法 NoSQL
(七)漫谈分布式之一致性算法下篇:一文从根上儿理解大名鼎鼎的Raft共识算法!
Raft通过一致性检查,能在一定程度上保证集群的一致性,但无法保证所有情况下的一致性,毕竟分布式系统各种故障层出不穷,如何在有可能发生各类故障的分布式系统保证集群一致性,这才是Raft等一致性算法要真正解决的问题。
112 11
|
3月前
|
Oracle 关系型数据库
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决
|
3月前
|
消息中间件 存储 监控
消息队列在分布式系统中如何保证数据的一致性和顺序?
消息队列在分布式系统中如何保证数据的一致性和顺序?