金石原创 |【分布式技术专题】「分布式技术架构」一文带你厘清分布式事务协议及分布式一致性协议的算法原理和核心流程机制(Paxos篇)

简介: 金石原创 |【分布式技术专题】「分布式技术架构」一文带你厘清分布式事务协议及分布式一致性协议的算法原理和核心流程机制(Paxos篇)

概念简介

Paxos是一种基于消息传递具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。

发展历史

Paxos算法的发展历史追溯到古希腊,当时有一个名为“Paxos“的小岛, 岛上采用一会的形式通过法令, 议会中议员通过信使进行消息传递,议员与信使都是兼职的,他们随时都有可能会离开议会,并且信使有可能传递重复的信息,也有可能一去不复返,因此议会要保证在这种情况下法令仍然能够正确的产生,并且不会起冲突。

Paxos算法分析

对于Paxos算法而言要解决上述信息传递的一致性问题,那么要保证一下几点:

  • 在这些提案中,只有一个被选定
  • 如果没有提案被提出,就不会有选定的提案
  • 当提案被选定以后,进程应该可以获取被选定的提案信息

对于一致性来说,安全性需求如下

  • 只有被提出的提案才能被选定
  • 只有一个提案被选定
  • 如果某个进程认为某个提案被选定了,那么这个提案必须是真的被选定的那个

三种参与角色

  • Proposer(提议者)
  • Acceptor(决策者)
  • Leamner(最终决策学习者)
问题场景分析

一个元素参与者可能扮演多个角色 (Proposer | Acceptor | Leamner) ,假设不同的参与者之间可以通过收发消息来进行通信。每个参与者以任意的速度执行,可能会因为出错而停止,也可能会重启,消息在传输过程中可能会出现不可预知的延迟,也有可能会重复或者丢失,但消息不会被损坏,即消息内容不能被篡改。

Paxos算法场景问题分析

首先,我们采用将建立角色处理模式的场景化分析,先从Acceptor的模式开始处理和分析,分析对应的执行流程以及对应的问题。

单个Acceptor模式

在处于单Acceptor模式下的时候,如以下图所示。



最简单的选定方式是只有一个Acceptor, Proposer发送给该Acceptor提案以后, Acceptor直接选择第一个提案为被选定的提案。但这种做法一旦Acceptor出问题, 整个系统将无法正常工作。

多个Acceptor模式

Proposer向多个Acceptor集合发送提案, 每个Acceptor都可能会批准(Accept) 该提案, 当足够多个Acceptor批准这个提案的时候, 我们就认为该提案被选定了。


实现一致性的条件约束(1)

在没有失败和消息丢失的情况下,如果我们希望即使只有一个提案被提出,仍然可以选出一个提案,1个Acceptor必须批准他收到的第一个提案。

该条件约束所出现的问题

如果多个提案被不同的Proposer同时提出, 这可能会导致虽然每个Acceptor都批准了他收到的第一个提案, 但是没有一个提案是多个人批准的,也就是没有多数的Acceptor集合,如下图所示。



为了解决此问题所以引入了【实现一致性的条件约束(2)】进行数据控制。

实现一致性的条件约束(2)

一个提案被选定需要被半数以上的Acceptor接受。

它是在【实现一致性的条件约束(1)】的基础上, 一个Acceptor能够批准不止一个提案。我们使用全局的编号来唯一的标识每一个Acceptor批准的提案, 当一个具有某Value的提案被半数以上的Acceptor批准以后, 我们就认为该Value被选定。

注意:提案和value不是一个概念, 提案是由一个编号与value组成的结构体, 因此我们用【编号,Value】来表示一个提案。

提案的结构体分析

提案的信息数据结构体主要有:提案编号+value两部分组成。

  • 提案编号:给每个提案加上一个提案编号,表示提案被提出的顺序,不同的编号可以有相同的内容。
  • value:提案的内容
该条件约束所出现的问题

虽然允许多个提案被选定, 但必须保证所有被选定的提案都具有相同的value值,否则又会出现不一致。

为了解决此问题所以引入了【实现一致性的条件约束(3)】进行数据控制。

实现一致性的条件约束(3)

如果提案编号为M, Value为V的提案(即【M,V】)被选定了,那么所有比M_编号更高的, 且被选定的提案, 其Value值必须也是V。

因为提案编号是全序的, 【实现一致性的条件约束(3)】就保证了只有一个Value值被选定这一关键安全性属性。同时,一个提案被选定,其首先必须被至少一个Acceptor批准, 因此我们可以通过满足如下条件来满足【实现一致性的条件约束(3)】。

案例推荐

假设总的有5个Acceptor,Proposer2提出 [M1,V1]  的提案,Acceptor25(半数以上)均接受了该提案,于是对于Acceptor 25和Proposer2来讲, 它们都认为V1被选定。

Acceptor1刚刚从宕机状态恢复过来(之前Acceptor1没有收到过任何提案) , 此时Proposer1向Acceptor1发送了[M2, V2] 的提案(V2且M2>M1) ,对于Acceptorl来讲, 这是它收到的第一个提案。根据【实现一致性的条件约束(1)】(一个Acceptor必须接受它收到的第一个提案) ,从而Acceptor1必须接受该提案!同时Acceptor1认为V2被选定,这就出现了两个问题。

问题分析
  1. Acceptor1认为V2被选定,Acceptor2~5和Proposer2认为V1被选定,出现了不一致。
  2. V1被选定了,但是编号更高的被Acceptor1接受的提案[M2,V2] 的value为V2,且V2不等于V1。且V2的编号还高于V1。



实现一致性的条件约束(4)

如果一个提案【M,V】被选定后, 那么之后任何Proposer产生的编号更高的提案, 其Value的值都为V。

问题分析

如何确保在某个Value为V的提案被选定后, Proposer 提出的编号更高的提案的Value都是V呢?

实现分析

任意的N和V, 如果提案 [ N,V ] 被提出,那么存在一个半数以上的Acceptor组成的集合S,需要执行以下两个操作步骤:

  • 集合S内的每个Acceptor都没有批准过编号小于N的提案。
  • 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案。

Proposer生成提案

对于一个Proposer来说, 获取那些已经通过的提案远比预测未来可能会通过的提案来的简单。因此Proposer在产生一个编号为M的提案时, 必须要知道当前某一个将要或已经被半数以上Acceptor批准的编号小于M但未最大的编号的提案。并且,Proposer会要求所有Acceptor都不要批准任何编号小于M的提案。

Proposer生成提案之前(Prepare阶段)

应该先去学习已经被选定或者可能被选定的value,然后以该value作为自己提出的提案的value。如果没有value被选定, Proposer才可以自己决定value的值。这样才能达成一致。这个学习的阶段是通过一个 【Prepare阶段】 请求实现的。

  • 向Proposer承诺保证不再接受任何编号小于N的提案
  • 如果Acceptor已经接受过提案,那么就向Proposer响应已经接受过的编号小于N的最大编号的提案

提案生成算法

如果Proposer收到了平数以上的Acceptor的响应, 那么它就可以生成编号为N, Value为V的提案[N,V] 。这里的V是所有的响应中编号最大的提案的Value。如果所有的响应中都没有提案, 那么此时V就可以由Proposer自己选择。

Proposer生成提案之后(Accept请求)

Proposer将该提案发送给半数以上的Acceptor集合, 并期望这些Acceptor能接受该提案。我们称该请求为Accept请求。

注意:此时接受Accept请求的Acceptor集合不一定是之前响应Prepare请求的Acceptor集合

Acceptor批准提案

  • Acceptor可以忽略任何请求(包括Prepare请求和Accept请求) 而不用担心破坏算法的安全性。因此, 我们这里要讨论的是什么时候Acceptor可以响应一个请求。
  • 一个Acceptor只要尚未响应过任何编号大于N的Prepare请求, 那么他就可以接受这个编号为N的提案。

算法总结

阶段一

  1. Proposer选择一个提案编号M, 然后向Acceptor的某个超过半数的子集成员发送编号为M的Prepare请求。
  2. 如果一个Acceptor收到一个编号为M的Prepare请求, 且编号M大于该Acceptor已经响应的所有Prepare请求的编号, 那么它就会把已经批准过的最大的编号的提案作为相应反馈给Proposer, 同时该Acceptor会承诺不会在批准任何编号小于M的提案。

阶段二

  1. 如果Proposer收到来自半数以上的Acceptor对于其发出的编号为M的Prepare请求的响应,那么它就会发送一个针对【M,V】提案的Accept请求给Acceptor。

注意:V的值就是收到的响应中编号最大的提案的值,如果响应中不包含任何提案,那么他就是任意值

  1. 如果Acceptor收到的这个针对【M, V】的提案的Accept请求, 只要该Acceptor尚未对编号大于M的Prepare请求作出响应, 他就可以通过这个提案。

看到这里是不是觉得和我们分布式事务中的2PC的思路和流程差不多啊!

通知学习Learner的方案

方案1

一旦Acceptor批准了一个提案, 就将该提案发送给所有的Leamer

方案2

让所有的Acceptor将它们对提案的批准情况, 统一发送给一个Learner, 再由它通知其他的Learner

方案3

方案2的主节点存在单点问题, 可以将主Leaner的范围扩大, 即Acceptor可以将批准信息发送给一个特定的Learner集合, 该集合中每个Leamer都可以在一个提案被选定后通知其他Leaner。

给你们的问题

  1. 设置多少个Acceptor最为合适?
  2. 如何控制每个Acceptor最多只能批准一个提案?
相关文章
|
12月前
|
存储 缓存 安全
某鱼电商接口架构深度剖析:从稳定性到高性能的技术密码
某鱼电商接口架构揭秘:分层解耦、安全加固、性能优化三维设计,实现200ms内响应、故障率低于0.1%。详解三层架构、多引擎存储、异步发布、WebSocket通信与全链路防护,助力开发者突破电商接口“三难”困境。
|
12月前
|
存储 运维 监控
120_检查点管理:故障恢复 - 实现分布式保存机制
在大型语言模型(LLM)的训练过程中,检查点管理是确保训练稳定性和可靠性的关键环节。2025年,随着模型规模的不断扩大,从百亿参数到千亿参数,训练时间通常长达数周甚至数月,硬件故障、软件错误或网络中断等问题随时可能发生。有效的检查点管理机制不仅能够在故障发生时快速恢复训练,还能优化存储使用、提高训练效率,并支持实验管理和模型版本控制。
761 5
120_检查点管理:故障恢复 - 实现分布式保存机制
|
12月前
|
人工智能 自然语言处理 安全
AI助教系统:基于大模型与智能体架构的新一代教育技术引擎
AI助教系统融合大语言模型、教育知识图谱、多模态交互与智能体架构,实现精准学情诊断、个性化辅导与主动教学。支持图文语音输入,本地化部署保障隐私,重构“教、学、评、辅”全链路,推动因材施教落地,助力教育数字化转型。(238字)
1881 23
|
12月前
|
Java Linux 虚拟化
【Docker】(1)Docker的概述与架构,手把手带你安装Docker,云原生路上不可缺少的一门技术!
1. Docker简介 1.1 Docker是什么 为什么docker会出现? 假定您在开发一款平台项目,您的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。 您正在开发的应用依赖于您当前的配置且还要依赖于某些配置文件。 您的企业还拥有标准化的测试和生产环境,且具有自身的配置和一系列支持文件。 **要求:**希望尽可能多在本地模拟这些环境而不产生重新创建服务器环境的开销 问题: 要如何确保应用能够在这些环境中运行和通过质量检测? 在部署过程中不出现令人头疼的版本、配置问题 无需重新编写代码和进行故障修复
865 2
|
Cloud Native API 开发者
Gemini 2.5 Flash 技术拆解:从 MoE 架构到阿里云生态落地指南
2025年9月,谷歌Gemini 2.5 Flash发布,性能提升5%、成本降24%,引发行业关注。其MoE架构、百万上下文与“思考”范式,助力阿里云开发者高效构建云原生应用。本文解析技术内核,结合汽车、物流等案例,提供落地指南与避坑建议,展望大模型与流计算融合前景。
1302 6
|
12月前
|
存储 人工智能 搜索推荐
拔俗AI助教系统:基于大模型与智能体架构的新一代教育技术引擎
AI助教融合大语言模型、教育知识图谱、多模态感知与智能体技术,重构“教、学、评、辅”全链路。通过微调LLM、精准诊断错因、多模态交互与自主任务规划,实现个性化教学。轻量化部署与隐私保护设计保障落地安全,未来将向情感感知与教育深度协同演进。(238字)
1350 0
|
12月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
906 0
|
12月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
546 2
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
465 3

热门文章

最新文章