一致性的艺术:深度剖析Paxos在分布式事务模型中的精妙设计

news2025/1/31 11:06:07

关注微信公众号 “程序员小胖” 每日技术干货,第一时间送达!

引言

在数字化浪潮的推动下,分布式系统已经成为现代IT架构的基石。它们支撑着我们日常使用的在线服务,从电商购物到金融交易,从社交网络到云计算平台。然而,随着系统的分布式特性越来越明显,一个关键问题也日益凸显——如何确保在不同节点、不同数据库、甚至不同服务之间,数据的一致性?

数据一致性算法

分布式事务模型和数据一致性算法在分布式系统中扮演着至关重要的角色,是构建可信赖的分布式系统的基础,它们确保了在分布式环境中数据的准确性、可靠性和完整性。

Paxos算法

Paxos算法是一种用于分布式系统中实现一致性的协议,由Leslie Lamport在1990年提出。它允许在分布式系统中的多个节点之间就某个值达成一致性,即使在面对节点故障和网络延迟等问题时也能保持系统的一致性。

Paxos算法的应用

Paxos算法被广泛应用于分布式数据库、分布式存储系统、分布式事务处理和分布式协调服务等场景。它通过确保分布式系统中的节点能够就一系列操作或值达成一致,从而保障了数据的一致性和系统的可靠性。

Paxos算法的核心原理

Paxos算法的基本思想是通过多个阶段的消息交换和投票来达成一致性。算法中的节点分为三种角色:提议者(Proposer)、接受者(Acceptor)和学习者(Learner)。

  • Proposer 提案者:提出提案 (Proposal)。Proposal信息包括提案编号 (Proposal ID) 和提议的值 (Value)。
  • Acceptor 批准者(接受者):参与决策,回应Proposers的提案。在集群中,Acceptor 有 N 个,Acceptor 之间完全对等独立,Proposer 提出的 value 必须获得超过半数(N/2+1)的 Acceptor 批准后才能通过。
  • Learner 学习者:不参与决策,从Proposers/Acceptors学习最新达成一致的提案(Value)Proposer 和 Acceptor 是算法核心角色,Paxos 描述的就是在一个由多个 Proposer 和多个 Acceptor构成的系统中,如何让多个 Acceptor 针对 Proposer 提出的多种提案达成一致的过程,而 Learner 只是“学习”最终被批准的提案。

Paxos 选举过程

选举过程可以分为两个部分,准备阶段和选举阶段。

Phase 1 准备阶段

Proposer 生成全局唯一且递增的 ProposalID,向 Paxos 集群的所有机器发送 Prepare 请求,这里不携带 value,只携带 N 即 ProposalID。Acceptor 收到 Prepare 请求后,判断收到的 ProposalID 是否比之前已响应的所有提案的 N 大,如果
是,则:

  • 在本地持久化 N,可记为 Max_N;
  • 回复请求,并带上已经 Accept 的提案中 N 最大的 value,如果此时还没有已经 Accept 的提案,则返回 value 为空;
  • 做出承诺,不会 Accept 任何小于 Max_N 的提案。
    如果否,则不回复或者回复 Error。

Phase 2 选举阶段

为了方便描述,我们把 Phase 2 选举阶段继续拆分为 P2a、P2b 和 P2c。

P2a:Proposer 发送 Accept

经过一段时间后,Proposer 收集到一些 Prepare 回复,有下列几种情况:

  • 若回复数量 > 一半的 Acceptor 数量,且所有回复的 value 都为空时,则 Porposer 发出 accept 请求,并带上自己指定的 value。
  • 若回复数量 > 一半的 Acceptor 数量,且有的回复 value 不为空时,则 Porposer 发出 accept 请求,并带上回复中 ProposalID 最大的 value,作为自己的提案内容。
  • 若回复数量 <= 一半的 Acceptor 数量时,则尝试更新生成更大的 ProposalID,再转到准备阶段执行。

P2b:Acceptor 应答 Accept

Accpetor 收到 Accpet 请求 后,判断:

  • 若收到的 N >= Max_N(一般情况下是等于),则回复提交成功,并持久化 N 和 value;
  • 若收到的 N < Max_N,则不回复或者回复提交失败。

P2c: Proposer 统计投票

经过一段时间后,Proposer 会收集到一些 Accept 回复提交成功的情况,比如:

  • 当回复数量 > 一半的 Acceptor 数量时,则表示提交 value 成功,此时可以发一个广播给所有的 Proposer、Learner,通知它们已 commit 的 value;
  • 当回复数量 <= 一半的 Acceptor 数量时,则尝试更新生成更大的 ProposalID,转到准备阶段执行。

当收到一条提交失败的回复时则尝试更新生成更大的ProposalID也会转到准备阶段执行。

这里准备了一个简化版的Paxos算法代码示例,展示了基本的提案准备和接受过程:

// Proposer类
class Proposer {
    private Acceptor[] acceptors;
    private int proposalId;

    public Proposer(Acceptor[] acceptors) {
        this.acceptors = acceptors;
        this.proposalId = 0;
    }

    public boolean propose(int value) {
        this.proposalId++;
        // 发送Prepare请求
        for (Acceptor acceptor : acceptors) {
            acceptor.prepare(this.proposalId);
        }
        // 检查多数是否同意
        boolean majorityAccepted = checkMajority();
        if (majorityAccepted) {
            // 发送Accept请求
            for (Acceptor acceptor : acceptors) {
                acceptor.accept(this.proposalId, value);
            }
            return true;
        }
        return false;
    }

    private boolean checkMajority() {
        // 实现检查逻辑,返回是否获得多数Acceptor的同意
        return false;
    }
}

// Acceptor类
class Acceptor {
    private int lastPromisedId;
    private Integer acceptedValue;

    public Acceptor() {
        this.lastPromisedId = 0;
        this.acceptedValue = null;
    }

    public void prepare(int proposalId) {
        if (proposalId > this.lastPromisedId) {
            this.lastPromisedId = proposalId;
            // 承诺不会接受更小编号的提案
        }
    }

    public void accept(int proposalId, int value) {
        if (proposalId > this.lastPromisedId) {
            this.lastPromisedId = proposalId;
            this.acceptedValue = value;
            // 持久化接受的值
        }
    }
}

Paxos算法的实现比较复杂,主要难点在于:

  • 活锁问题:多个提案者可能相互等待,导致没有一个提案能够获得多数票。
  • 容错性:算法需要在面对节点故障和网络问题时依然能够保证一致性。
  • 效率:在高并发情况下,算法需要尽可能高效地达成共识。

在实际应用中,通常使用的是Multi-Paxos,它是Paxos算法的一种扩展,可以就一系列值达成共识,而不是单个值。

Multi-Paxos

Multi-Paxos算法是Paxos算法的一种扩展,它允许分布式系统中的多个节点就一系列值达成一致,而不仅仅是单个值。Multi-Paxos算法通过执行多个Basic Paxos实例来实现这一目标,每个实例对应于需要达成共识的一个值。

应用场景

Multi-Paxos广泛应用于分布式数据库、分布式锁服务(如ZooKeeper)以及其他需要强一致性的分布式系统中。

核心原理

  • Leader选举:在Multi-Paxos中,通常会选举一个Leader(领导者),该Leader负责提出所有的提案,从而避免了多个Proposer之间可能发生的冲突。
  • 提案编号:每个提案都有一个唯一的编号,编号高的提案优先级更高。
  • 日志索引:在Multi-Paxos中,每个提案都关联到一个日志索引,这样每个值的提案都对应于日志中的一个特定位置。
  • 两阶段提交:每个值的确定仍然通过Paxos算法的两阶段提交来完成:Prepare阶段和Accept阶段。
  • 连续提案:一旦Leader确定了某个值,它就可以继续提出下一个值的提案,而无需等待当前提案的完成。
  • 容错性:Multi-Paxos算法能够在一定数量的节点故障的情况下继续工作,保持系统的一致性和可用性。

Multi-Paxos算法的实现相当复杂,提供一个简化的Java代码示例,展示Leader如何提出一个提案:

public class MultiPaxosLeader {

    private Acceptor[] acceptors;
    private int leaderId;
    private int maxProposalId;

    public MultiPaxosLeader(Acceptor[] acceptors, int leaderId) {
        this.acceptors = acceptors;
        this.leaderId = leaderId;
        this.maxProposalId = 0;
    }

    public boolean propose(int index, String value) {
        int proposalId = ++maxProposalId;
        boolean accepted = true;

        // 发送Prepare请求
        for (Acceptor acceptor : acceptors) {
            if (!acceptor.prepare(proposalId, index)) {
                accepted = false;
                break;
            }
        }

        if (accepted) {
            // 发送Accept请求
            for (Acceptor acceptor : acceptors) {
                if (!acceptor.accept(proposalId, index, value)) {
                    accepted = false;
                    break;
                }
            }
        }

        return accepted;
    }
}

class Acceptor {
    // 每个Acceptor维护了一个提案日志
    private Map<Integer, String> acceptedValues;

    public Acceptor() {
        this.acceptedValues = new HashMap<>();
    }

    public boolean prepare(int proposalId, int index) {
        // 如果proposalId更大,则接受Prepare请求
        String prevValue = acceptedValues.get(index);
        if (prevValue == null || proposalId > prevValue.hashCode()) {
            acceptedValues.put(index, value);
            return true;
        }
        return false;
    }

    public boolean accept(int proposalId, int index, String value) {
        // 如果proposalId未变化,则接受Accept请求
        String acceptedValue = acceptedValues.get(index);
        if (acceptedValue != null && acceptedValue.equals(value)) {
            // 这里应该包含持久化操作
            return true;
        }
        return false;
    }
}

在实际应用中,通常使用的是Multi-Paxos,它是Paxos算法的一种扩展,可以就一系列值达成共识,而不是单个值。Multi-Paxos通过选出一个全局领导者(Leader)来简化提案过程,从而提高效率。

Multi-Paxos首先需要选举出一个Leader,然后由Leader来提交提案给Acceptors进行表决。这样可以避免多个Proposer竞争导致的活锁问题,并且因为只有一个Leader,可以将两阶段提交过程优化为一阶段,提高效率。

结语

Multi-Paxos和Paxos算法是分布式系统中实现数据一致性的关键技术。它通过在多个节点之间就一系列值达成共识,为构建高可用和高一致性的分布式系统提供了理论基础。虽然Multi-Paxos和Paxos算法的实现相对复杂,但它为许多现代分布式系统提供了强大的一致性保证。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1671888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rmallox勒索病毒肆虐,如何保护网络安全?

rmallox勒索病毒与网络安全的关系可以从以下几个方面来阐述&#xff1a; 一、rmallox勒索病毒的特性 rmallox勒索病毒是一种极具破坏性的计算机病毒&#xff0c;它具有多个显著特性&#xff0c;这些特性使得该病毒对网络安全构成了严重威胁。具体来说&#xff0c;rmallox病毒具…

制造业如何挖掘数据价值,附数据分析处理软件推荐

制造业如何挖掘和利用数据价值&#xff1f; 在信息化、智能化高速发展的今天&#xff0c;制造业正迎来一场由数据驱动的深刻变革。数据&#xff0c;作为这场变革的核心驱动力&#xff0c;正被制造业企业深度挖掘和利用&#xff0c;以实现更高效、更智能的生产模式。 制造业在利…

基于Springboot的实习生管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的实习生管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…

具身触觉社区| “大咖面对面”第一期活动顺利举行

4月27日&#xff0c;由中国人工智能学会认知系统与信息处理专委会组织的“具身触觉社区”第一期“大咖面对面”分享活动顺利举行&#xff0c;我们邀请到了美国麻省理工学院&#xff08;MIT&#xff09;博士、视触觉传感器的奠基人、GelSight指尖传感器发明人李瑞老师为社区带来…

Linux 第三十章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

CSS学习笔记之中级教程(一)

1、CSS 布局 - display 属性 1.1 display 属性 display 属性是用于控制布局的最重要的 CSS 属性。 display 属性规定是否/如何显示元素。 每个 HTML 元素都有一个默认的 display 值&#xff0c;具体取决于它的元素类型。大多数元素的默认 display 值为 block 或 inline。 …

Hbase基础操作Demo(Java版)

一、前置条件 HBase服务&#xff1a;【快捷部署】023_HBase&#xff08;2.3.6&#xff09;开发环境&#xff1a;Java&#xff08;1.8&#xff09;、Maven&#xff08;3&#xff09;、IDE&#xff08;Idea 或 Eclipse&#xff09; 二、相关代码 代码结构如上图中①和② pom.x…

CNN实现fashion_mnist数据集分类(tensorflow)

1、查看tensorflow版本 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、加载fashion_mnist数据与预处理 import numpy as np (train_images,train_labels),(test_images,test_labels) tf.keras.d…

2024年5月树莓集团快讯

树莓集团近期快讯 1 园区专场招聘会进校园 国际数字影像产业园联合四川城市职业学院的专场招聘会成功召开&#xff0c;共计提供400余个工作岗位。 2 园区硬件优化再升级 园区硬件优化再升级&#xff0c;智能门禁系统及人脸识别系统下周投入使用。 3 基地短剧合作交流 天府…

第10篇:创建Nios II工程之控制单个七段数码管

Q&#xff1a;还记得之前使用Verilog case语句来描述实现七段数码管的逻辑功能。本期我们创建Nios II工程用C语言代码实现相同的功能。 A&#xff1a;基本原理&#xff1a;一个七段数码管由7个发光二极管LED组成&#xff0c;所以控制一个数码管的显示即控制7个LED。我们在之前…

江门水文分局开展防灾减灾主题宣传活动

5月11日&#xff0c;第16个全国防灾减灾日到来之际&#xff0c;广东省水文局江门水文分局联合江门市五邑义工联合会直属义工服务总队&#xff08;亲子服务队&#xff09;在江门市万达广场举办了一场别开生面的防灾减灾主题宣传活动&#xff0c;进一步培育孩子们的防灾减灾的意识…

[ACTF新生赛2020]SoulLike

没见过的错误&#xff1a; ida /ctg目录下的hexrays.cfg文件中的MAX_FUNCSIZE64 改为 MAX_FUNCSIZE1024 然后就是一堆数据 反正就是12个字符 from pwn import * flag"actf{" k0 for n in range(12):for i in range(33,127):pprocess("./SoulLike")_flag…

调剂”小清华“、不保护一志愿?——兰州大学25计算机考研考情分析

兰州大学&#xff08;Lanzhou University&#xff09;&#xff0c;简称“兰大”&#xff0c;是中华人民共和国教育部直属 全国重点大学&#xff0c;中央直管副部级建制&#xff0c;位列国家首批“双一流(A 类)”、“211 工 程”、“985 工程”大学行列&#xff0c;入选国家“珠…

asp.net core mvc razor动态编译

开发mvc过程中razor页面需要重启才能编译&#xff0c;非常麻烦&#xff0c;能否实现动态编译&#xff0c;微软官方提供了一个包能实现 新建.net 6 mvc项目 安装Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 修改csproj <Project Sdk"Microsoft.NET.Sdk.Web…

拉链表实现过程+案例

第一种 1.从ODS层获取增量数据(上一天新增和更新的数据) 2.拿着DWD原始拉链表数据 left join 增量数据 ,修改原始拉链中历史数据的结束时间 3.拿着left join 的结果集 union all 增量数据 4.把最新的拉链数据优先保存到DWD对应的临时表中 5.使用insertselect 方式把临时表中…

宝塔纯净版 7.6.0版本无需手机登录 [稳定版本/推荐]

下载地址&#xff1a;宝塔纯净版 7.6.0版本无需手机登录.zip 宝塔纯净版介绍 无需手机登录&#xff1a;不再有手机登录提示&#xff0c;或按照提示输入任意手机号密码即可模拟绑定&#xff1b; 安全&#xff1a;剥离了所有与宝塔官方的通信、上报、下发&#xff1b;并且不与…

栈和队列经典OJ题详解

目录 一、用栈实现队列 1.1 题目 1.2 思路 1.3 C语言题解 1.3.1 栈接口 1.3.2 代码实现 二、用队列实现栈 2.1 题目 2.2 思路 2.2.1 如何设计出栈 2.2.2 如何设计入栈 2.3 C语言题解 2.3.1 队列接口 2.3.2 代码实现 三、括号匹配问题 3.1 题目 3.2 思路 3.3 …

【C++】继承与多态的一些练习题

学习完了继承与多态&#xff0c;当然要来点练习题啦~ 第一题&#xff1a; class Base1 { public: int _b1; }; class Base2 { public: int _b2; }; class Derive : public Base1, public Base2 { public: int _d; }; int main(){ Derive d; Base1* p1 &d; Base2* p2…

Ubuntu22.04怎么安装cuda11.3

环境&#xff1a; WSL2 Ubuntu22.04 问题描述&#xff1a; Ubuntu22.04怎么安装cuda11.3 之前是11.5 解决方案&#xff1a; 在Ubuntu 22.04上安装CUDA 11.3需要一些步骤&#xff0c;因为CUDA 11.3不是为Ubuntu 22.04官方支持的版本。但是&#xff0c;您仍然可以通过以下步…

Linux提权--定时任务--打包配合 SUID(本地)文件权限配置不当(WEB+本地)

免责声明:本文仅做技术交流与学习... 目录 定时任务 打包配合 SUID-本地 原理: 背景: 操作演示: 分析: 实战发现: 定时任务 文件权限配置不当-WEB&本地 操作演示: 定时任务 打包配合 SUID-本地 原理: 提权通过获取计划任务执行文件信息进行提权 . 1、相对路径和…