分布式理解

news2025/1/27 8:03:08

分布式

如何理解分布式

狭义的分布是指,指多台PC在地理位置上分布在不同的地方。

分布式系统

分布式系**统:**多个能独立运行的计算机(称为结点)组成。各个结点利用计算机网络进行信息传递,从而实现共同的“目标或者任务”。

分布式程序: 运行在分布式系统上的计算机程序。

分布式计算:利用分布式系统解决来计算问题。在分布式计算里,一个问题被细化成多个任务,每个任务可以被一个或者多个计算机来完成。

区分分布式计算和并行计算:共同点都是大任务划分为小任务。不同点: 分布式计算:基于多台PC,每台PC完成同一任务中的不同部分。分布式的计算被分解后的小任务互相之间有独立性,节点之间的结果几乎不互相影响,实时性要求不高。并行计算:基于同一个台PC,利用CPU的多核共同完成一个任务。

  • 分布式操作系统:负责管理分布式处理系统资源和控制分布式程序运行。它和集中式操作系统的区别在于资源管理、进程通信和系统结构等方面

  • 分布式文件系统:分布式文件系统具有执行远程文件存取得能力,并以透明方式对分布在网络上得文件进行管理和存取

  • 分布式程序设计和编译解释系统

分布式事务

事务 事务提供一种“要么什么都不做,要么做全套(All or Nothing)”的机制,她有ACID四大特性 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态是指数据库中的数据应满足完整性约束。除此之外,一致性还有另外一层语义,就是事务的中间状态不能被观察到(这层语义也有说应该属于原子性)。 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行,如同只有这一个操作在被数据库所执行一样。 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。在事务结束时,此操作将不可逆转。 单机事务 以mysql的InnoDB存储引擎为例,来了解单机事务是如何保证ACID特性的。

分布式事务 单机事务是通过将操作限制在一个会话内通过数据库本身的锁以及日志来实现ACID,那么分布式环境下该如何保证ACID特性那? 2.2.1 XA协议实现分布式事务

2.2.1.1 XA描述 X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 是X/Open 这个组织定义的一套分布式事务的标准,也就是了定义了规范和API接口,由各个厂商进行具体的实现。 X/Open DTP 定义了三个组件: AP,TM,RM

2PC

二阶段提交

二阶段提交是一种强一致性设计,2PC引入一个事务协调者的角色来协调管理各参与者(各本地资源)的提交和回滚,二阶段分别指的是准备和提交两个阶段

准备阶段:协调者会给各参与者发送准备命令,可以把准备命令理解成除了提交事务之外的事都做完了

同步等待所有资源的响应之后就进入第二阶段即提交阶段(提交阶段不一定是提交事务,也可能是回滚事务)

假如在第一阶段所有参与者都返回准备成功,那么协调者则向所有参与者发送提交事务命令,然后等待所有事务都提交成功之后,返回事务执行成功。

假如在第一阶段有一个参与者返回失败,那么协调者就会向所有参与者发送回滚事务的请求,即分布式事务执行失败

如果第二阶段提交失败

第一种情况:第二阶段执行的是回滚事务操作,那么就是不断重试,直到所有参与者都回滚了。不然那些在第一阶段准备成功的参与者会一直阻塞着

第二种情况:第二阶段执行的是提交事务操作,也是不断重试,因为有可能一些参与者的事务已经提交成功了,这个时候只有一条路,就是不断的重试,直到提交成功。

2PC是一个同步阻塞协议,像第一阶段协调者会等待所有参与者响应了才会进行下一步操作,当然第一阶段的协调者有超时机制,假设因为网络原因没有收到某参与者的响应或某参与者挂了,那么超时之后就会判断事务失败,向所有参与者发送回滚命令

协调者故障分析

协调者是一个单点,存在单点故障问题

假设协调者在发送准备命令之前挂了,就等于事务还没开始

假设协调者在发送准备命令之后挂了,参与者等于都执行了处于事务资源锁定的状态。不仅事务执行不下去,还会因为锁定了一些公共资源而阻塞系统其他操作

假设协调者在发送回滚事务命令之前挂了,事务无法执行,且在第一阶段那些准备成功参与者都阻塞着

假设协调者在发送回滚事务命令之后挂了,至少命令发出去了,很大的概率都会回滚成功,资源都会释放,但是 如果出现网络分区的问题,某些参与者将因为收不到命令而阻塞着。

假设协调者在发送提交事务命令之前挂了,这下所有资源都阻塞了

假设协调者在发送提交事务命令之后挂了,至少命令发出去了,很大概率都会提交成功,然后释放资源,但是如果出现网络分区问题某些参与者将因为收不到命令而阻塞着

协调者故障,通过选举得到新协调者

因为协调者单点问题,因此我们可以通过选举等操作选出一个新协调者来顶替。

如果处于第一阶段,其实影响不大都回滚好了,在第一阶段事务肯定还没提交。

如果处于第二阶段,假设参与者都没挂,此时新协调者可以向所有参与者确认它们自身情况来推断下一步的操作。

假设有个别参与者挂了!这就有点僵硬了,比如协调者发送了回滚命令,此时第一个参与者收到了并执行,然后协调者和第一个参与者都挂了。

此时其他参与者都没收到请求,然后新协调者来了,它询问其他参与者都说OK,但它不知道挂了的那个参与者到底O不OK,所以它傻了。

问题其实就出在每个参与者自身的状态只有自己和协调者知道,因此新协调者无法通过在场的参与者的状态推断出挂了的参与者是什么情况。

虽然协议上没说,不过在实现的时候我们可以灵活的让协调者将自己发过的请求在哪个地方记一下,也就是日志记录,这样新协调者来的时候不就知道此时该不该发了?

但是就算协调者知道自己该发提交请求,那么在参与者也一起挂了的情况下没用,因为你不知道参与者在挂之前有没有提交事务。

如果参与者在挂之前事务提交成功,新协调者确定存活着的参与者都没问题,那肯定得向其他参与者发送提交事务命令才能保证数据一致。

如果参与者在挂之前事务还未提交成功,参与者恢复了之后数据是回滚的,此时协调者必须是向其他参与者发送回滚事务命令才能保持事务的一致。

所以说极端情况下还是无法避免数据不一致问题

协调者:
    write START_2PC to local log; //开始事务
    multicast VOTE_REQUEST to all participants; //广播通知参与者投票
    while not all votes have been collected {
        wait for any incoming vote;
        if timeout { //协调者超时
            write GLOBAL_ABORT to local log; //写日志
            multicast GLOBAL_ABORT to all participants; //通知事务中断
            exit;
        }
        record vote;
    }
    //如果所有参与者都ok
    if all participants sent VOTE_COMMIT and coordinator votes COMMIT {
        write GLOBAL_COMMIT to local log;
        multicast GLOBAL_COMMIT to all participants;
    } else {
        write GLOBAL_ABORT to local log;
        multicast GLOBAL_ABORT to all participants;
    }
参与者:
​
    write INIT to local log; //写日志
    wait for VOTE_REQUEST from coordinator;
    if timeout { //等待超时
        write VOTE_ABORT to local log;
        exit;
    }
    if participant votes COMMIT {
        write VOTE_COMMIT to local log; //记录自己的决策
        send VOTE_COMMIT to coordinator;
        wait for DECISION from coordinator;
        if timeout {
            multicast DECISION_REQUEST to other participants; //超时通知
            wait until DECISION is received;  /* remain blocked*/
            write DECISION to local log;
        }
        if DECISION == GLOBAL_COMMIT
            write GLOBAL_COMMIT to local log;
        else if DECISION == GLOBAL_ABORT
            write GLOBAL_ABORT to local log;
    } else {
        write VOTE_ABORT to local log;
        send VOTE_ABORT to coordinator;
    }
​
每个参与者维护一个线程处理其它参与者的DECISION_REQUEST请求:
​
    while true {
        wait until any incoming DECISION_REQUEST is received;
        read most recently recorded STATE from the local log;
        if STATE == GLOBAL_COMMIT
            send GLOBAL_COMMIT to requesting participant;
        else if STATE == INIT or STATE == GLOBAL_ABORT;
            send GLOBAL_ABORT to requesting participant;
        else
            skip;  /* participant remains blocked */
    }
​

2PC是一种尽量保证强一致性的分布式事务,因此他是同步阻塞的,而同步阻塞就导致长久的资源锁定问题,总体而言效率低,并且存在单点故障问题,在极端条件下存在数据不一致的风险

3PC

相比于2PC它在参与者中也引入了超时机制,并且新增了一个阶段使得参与者可以利用这一个阶段统一各自的状态

三个阶段:准备阶段、预提交阶段和提交阶段

准备阶段 不会直接执行事务,而是先询问此时的参与者是否有条件接这个任务,因此不会一来就干活直接锁资源,使得在某些资源不可用的情况下所有参与者都阻塞着

预提交阶段的引入起到了一个统一状态的作用,它像一道栅栏,表明在预提交阶段前所有参与者其实还未都回应,在预处理阶段表明所有参与者都已经回应了

假如你是一位参与者,你知道自己进入了预提交状态那你就可以推断出来其他参与者也都进入了预提交状态。

但是多引入一个阶段也多一个交互,因此性能会差一些,而且绝大部分的情况下资源应该都是可用的,这样等于每次明知可用执行还得询问一次。

2PC 是同步阻塞的,上面我们已经分析了协调者挂在了提交请求还未发出去的时候是最伤的,所有参与者都已经锁定资源并且阻塞等待着。

那么引入了超时机制,参与者就不会傻等了,如果是等待提交命令超时,那么参与者就会提交事务了,因为都到了这一阶段了大概率是提交的,如果是等待预提交命令超时,那该干啥就干啥了,反正本来啥也没干。

然而超时机制也会带来数据不一致的问题,比如在等待提交命令时候超时了,参与者默认执行的是提交事务操作,但是有可能执行的是回滚操作,这样一来数据就不一致了。 3PC 的引入是为了解决提交阶段 2PC 协调者和某参与者都挂了之后新选举的协调者不知道当前应该提交还是回滚的问题。

新协调者来的时候发现有一个参与者处于预提交或者提交阶段,那么表明已经经过了所有参与者的确认了,所以此时执行的就是提交命令。

所以说 3PC 就是通过引入预提交阶段来使得参与者之间的状态得到统一,也就是留了一个阶段让大家同步一下。

但是这也只能让协调者知道该如果做,但不能保证这样做一定对,这其实和上面 2PC 分析一致,因为挂了的参与者到底有没有执行事务无法断定。

所以说 3PC 通过预提交阶段可以减少故障恢复时候的复杂性,但是不能保证数据一致,除非挂了的那个参与者恢复。

让我们总结一下, 3PC 相对于 2PC 做了一定的改进:引入了参与者超时机制,并且增加了预提交阶段使得故障恢复之后协调者的决策复杂度降低,但整体的交互过程更长了,性能有所下降,并且还是会存在数据不一致问题。

所以 2PC 和 3PC 都不能保证数据100%一致,因此一般都需要有定时扫描补偿机制。

提交阶段和2PC的一样

无论哪一个阶段有参与者返回失败都会宣布事务失败

TCC

2PC和3PC都是数据库层面的,而TCC是业务层面的分布式事务

TCC指的是Try confirm Cancel

  • try指的是预留,即资源的预留和锁定

  • confirm 指的是确认操作,这一步其实就是真正的执行了

  • cancel指的是撤销操作,可以理解为把预留阶段的的动作撤销了

其实从思想上看和 2PC 差不多,都是先试探性的执行,如果都可以那就真正的执行,如果不行就回滚。

比如说一个事务要执行A、B、C三个操作,那么先对三个操作执行预留动作。如果都预留成功了那么就执行确认操作,如果有一个预留失败那就都执行撤销动作。

TCC对业务的侵入比较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作

撤销和确认操作的执行可能需要重试,因此还需要保证操作的幂

相对于 2PC、3PC ,TCC 适用的范围更大,但是开发量也更大,毕竟都在业务上实现,而且有时候你会发现这三个方法还真不好写。不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务

本地消息表

本地消息表其实就是利用了 各系统本地的事务来实现分布式事务。

本地消息表顾名思义就是会有一张存放本地消息的表,一般都是放在数据库中,然后在执行业务的时候 将业务的执行和将消息放入消息表中的操作放在同一个事务中,这样就能保证消息放入本地表中业务肯定是执行成功的。

然后再去调用下一个操作,如果下一个操作调用成功了好说,消息表的消息状态可以直接改成已成功。

如果调用失败也没事,会有 后台任务定时去读取本地消息表,筛选出还未成功的消息再调用对应的服务,服务更新成功了再变更消息的状态。

这时候有可能消息对应的操作不成功,因此也需要重试,重试就得保证对应服务的方法是幂等的,而且一般重试会有最大次数,超过最大次数可以记录下报警让人工处理。

可以看到本地消息表其实实现的是最终一致性,容忍了数据暂时不一致的情况。

消息事务

RocketMQ就很好的支持了消息事务

第一步先给Broker发送事务消息即半消息,半消息不是说一般消息,而是这个消息对消费者来说不可见,然后发送成功后发送方在执行本地事务

再根据本地事务的结果向Broker发送Commit或者RollBack命令

并且RocketMQ的发送方会提供一个反查事务状态接口,如果一段时间内半消息没有收到任何操作请求,那么Broker会通过反查接口得知发送方事务是否执行成功,然后执行Commit或者RollBack命令

如果是Commit那么订阅方就能收到这条消息,然后再做对应的操作,做完了之后再消费这条消息即可

如果是RollBack那么订阅方收不到这条消息,等于事务就没执行过

可以看到通过 RocketMQ 还是比较容易实现的,RocketMQ 提供了事务消息的功能,我们只需要定义好事务反查接口即可。

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

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

相关文章

macOS使用LLVM官方发布的tar.xz来安装Clang编译器

之前笔者写过一篇博文ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器介绍了Ubuntu下使用官方发布的tar.xz包来安装Clang编译。官方发布的版本中也有MacOS版本的tar.xz,那MacOS应该也是可以安装的。 笔者2015款MBP笔记本,CPU是intel的,出厂…

ppp综合实验

IP地址 r1 r2 r3 r4 hdlc封装 pap认证 r2 r3 chap认证 r2 r4 MGRE 主认证 [r1]int Tunnel 0/0/0 [r1-Tunnel0/0/0]ip add 192.168.4.1 24 [r1-Tunnel0/0/0]tunnel-protocol gre p2mp [r1-Tunnel0/0/0]source 12.1.1.1 [r1-Tunnel0/0/0]nhrp entry multicast dynamic [r1-Tu…

HBuilderX构建Vue项目

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl HBuilderX概述 HBuilderX是一款专为开发者设计的高效开发工具,致力于提升开发者的编码效率和体验。HBuilderX既适合追求极致效率的极客,也适合希望简…

基于微信小程序的英语学习交流平台设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

使用 Confluent Cloud 的 Elasticsearch Connector 部署 Elastic Agent

作者:来自 Elastic Nima Rezainia Confluent Cloud 用户现在可以使用更新后的 Elasticsearch Sink Connector 与 Elastic Agent 和 Elastic Integrations 来实现完全托管且高度可扩展的数据提取架构。 Elastic 和 Confluent 是关键的技术合作伙伴,我们很…

JDK17 HashMap

HashMap ArrayList用动态数组存放元素,而HashMap用动态数组(桶)存储键值对。 如果两个键值对映射到桶同一个索引,则称为散列冲突。HashMap采用拉链法解决冲突,即桶中每个索引指向一个链表或者红黑树,多个键…

ansible自动化运维实战--通过role远程部署nginx并配置(8)

文章目录 1、准备工作2、创建角色结构3、编写任务4、准备配置文件(金甲模板)5、编写变量6、编写处理程序7、编写剧本8、执行剧本Playbook9、验证-游览器访问每台主机的nginx页面 在 Ansible 中,使用角色(Role)来远程部…

Python网络自动化运维---用户交互模块

文章目录 目录 文章目录 前言 实验环境准备 一.input函数 代码分段解析 二.getpass模块 前言 在前面的SSH模块章节中,我们都是将提供SSH服务的设备的账户/密码直接写入到python代码中,这样很容易导致账户/密码泄露,而使用Python中的用户交…

计算机的错误计算(二百二十二)

摘要 利用大模型化简计算 实验表明,虽然结果正确,但是,大模型既绕了弯路,又有数值计算错误。 与前面相同,再利用同一个算式看看另外一个大模型的化简与计算能力。 例1. 化简计算摘要中算式。 下面是与一个大模型的…

mybatis(78/134)

前天学了很多&#xff0c;关于java的反射机制&#xff0c;其实跳过了new对象&#xff0c;然后底层生成了字节码&#xff0c;创建了对应的编码。手搓了一遍源码&#xff0c;还是比较复杂的。 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE …

数据分箱 baggingboosting onehot独热编码 woe编码 sklearn的ensemble(集成学习)

目录 数据分箱就是将连续变量离散化。 bagging&boosting onehot独热编码 独热编码的结果如下&#xff1a; woe编码 WOE编码的基本原理 步骤一&#xff1a;计算WOE 步骤二&#xff1a;应用WOE WOE编码的优点 示例 数据示例 步骤一&#xff1a;计算每个类别的违约…

企业微信开发010_使用WxJava企业微信开发框架_封装第三方应用企业微信开发003_并且实现多企业授权访问---企业微信开发012

继续来看吧,上一节,已经把config部分,代码都拿过来了: 并且把企业微信第三方应用开发部分,对应的config的配置,mutiltp 代码拿过来了,并且把yml中的配置也给出了. 然后,这里说一下config中的内容,到时候自己看也可以看懂 其实就是封装了,当系统启动,加载企微模块,这个时候,会…

Office2021下载与安装保姆级教程【Office Tool Plus】

Office Tool Plus安装Office2021 下载Office Tool Plus安装OfficeⅠ. 清除旧版本Ⅱ. 配置安装参数Ⅲ. 安装许可证Ⅳ. 激发&#xff08;JH&#xff09;Office 本文介绍使用Office Tool Plus工具下载、安装、部署Office 2021全过程。 下载Office Tool Plus OfficeToolPlus是一个…

Unity在WebGL中拍照和录视频

原工程地址https://github.com/eangulee/UnityWebGLRecoder Unity版本2018.3.6f1&#xff0c;有点年久失修了 https://github.com/xue-fei/Unity.WebGLRecorder 修改jslib适配了Unity2021 效果图 录制的视频 Unity在WebGL中拍照和录视频

【外文原版书阅读】《机器学习前置知识》1.线性代数的重要性,初识向量以及向量加法

目录 ​编辑 ​编辑 1.Chapter 2 Why Linear Algebra? 2.Chapter 3 What Is a Vector? 个人主页&#xff1a;Icomi 大家好&#xff0c;我是Icomi&#xff0c;本专栏是我阅读外文原版书《Before Machine Learning》对于文章中我认为能够增进线性代数与机器学习之间的理解的…

SpringBoot开发(二)Spring Boot项目构建、Bootstrap基础知识

1. Spring Boot项目构建 1.1. 简介 基于官方网站https://start.spring.io进行项目的创建. 1.1.1. 简介 Spring Boot是基于Spring4框架开发的全新框架&#xff0c;设计目的是简化搭建及开发过程&#xff0c;并不是对Spring功能上的增强&#xff0c;而是提供了一种快速使用Spr…

【PyTorch】4.张量拼接操作

个人主页&#xff1a;Icomi 在深度学习蓬勃发展的当下&#xff0c;PyTorch 是不可或缺的工具。它作为强大的深度学习框架&#xff0c;为构建和训练神经网络提供了高效且灵活的平台。神经网络作为人工智能的核心技术&#xff0c;能够处理复杂的数据模式。通过 PyTorch&#xff0…

新电脑安装系统找不到硬盘原因和解决方法来了

有不少网友反馈新电脑采用官方u盘方式装win10或win100出现找不到硬盘是怎么回事&#xff1f;后来研究半天发现是bios中开启了rst(vmd)模式。如果关闭rst模式肯定是可以安装的&#xff0c;但这会影响硬盘性能&#xff0c;有没有办法解决开启rst模式的情况安装win10或win11呢&…

「 机器人 」仿生扑翼飞行器中的“被动旋转机制”概述

前言 在仿生扑翼飞行器的机翼设计中,模仿昆虫翼的被动旋转机制是一项关键技术。其核心思想在于:机翼旋转角度(攻角)并非完全通过主动伺服来控制,而是利用空气动力和惯性力的作用,自然地实现被动调节。以下对这种设计的背景、原理与优势进行详细说明。 1. 背景:昆虫的被动…

Android GLSurfaceView 覆盖其它控件问题 (RK平台)

平台 涉及主控: RK3566 Android: 11/13 问题 在使用GLSurfaceView播放视频的过程中, 增加了一个播放控制面板, 覆盖在视频上方. 默认隐藏setVisibility(View.INVISIBLE);点击屏幕再显示出来. 然而, 在RK3566上这个简单的功能却无法正常工作. 通过缩小视频窗口可以看到, 实际…