当前位置: 首页 > news >正文

【分布式事务-01】分布式事务之2pc两阶段提交

redis系列整体栏目


内容链接地址
【一】分布式事务之2pc两阶段提交https://zhenghuisheng.blog.csdn.net/article/details/142406325

分布式事务之2pc两阶段提交

  • 一,分布式事务之2pc两阶段提交
    • 1,两阶段提交(2pc)
    • 2,2pc两阶段提交实现思路
    • 3,代码模拟两阶段提交
    • 4,两阶段提交的缺陷

一,分布式事务之2pc两阶段提交

在了解分布式事务之前,需要先了解什么事本地事务,本地事务指的是在单jvm进程下,不涉及到分布式场景下的事务。而在分布式场景下,如微服务架构,分库分表这些情况下,那么在一个方法中,就可能操作多个数据库,那么本地事务是不能解决多个事务的提交以及回滚的,因此就引入了分布式事务。

1,两阶段提交(2pc)

在解决分布式事务之前,先了解一下什么是两阶段提交。假设有一个场景:就是一个下单和扣减库存的场景,假设有两个库,一个是order订单表,一个是stock库存表 ,现在在分布式场景中,为了保证事务的原子性,要么同时成功,要么同时失败。

那么如果是让我们自定义区实现一个解决这种分布式方案的话,那么其实也很简单,其大概实现思路如下,首先拿到两个事务的预提交的状态,然后同时判断本地事务状态是否执行成功,执行成功则提交事务,有一个不成功则同时回滚事务

//订单创建和更新库存预提交
int orderStatus = order.prepare();
int stockStatus = stock.prepare();
//判断二者之间的状态是否都为1
if(orderStatus && stockStatus){//同时提交order.commit();stock.commit();
}else{//同时回滚order.rollback();stock.rollback();
}

其两阶段提交的本质也很好理解,就是分为两个阶段,一个是准备阶段,协调者会去每个本地事务拿到每个预提交的返回值,然后根据返回值进行判断是否都为ok,当都为ok时则执行commit操作,否则执行rollback操作

在这里插入图片描述

2,2pc两阶段提交实现思路

在介绍两阶段提交之前,需要先知道内部的一些名词

  • Coordinator :协调者,又被称为事务管理器,用于对所有本地事务进行收集,并用于控制所有本地事务进行准备操作、提交事务和回滚事务
  • Participants:参与者,又被称为资源管理器,用于管理所有的本地事务

在了解完本地名词之后,再来查看2pc的两阶段操作是如何执行的

  • 首先第一阶段就是协调者去通知各个参与者进行事务的预提交,参与者在接收到指令后开始预提交,随后向协调者发送应答,如果可以提交则返回ok肯定答复,如果出现其他情况则返回error否定答复
  • 第二阶段就是在协调者接收到全部的参与者的答复之后,根据返回的应答消息进行判断,如果返回的消息都是肯定的答复ok,那么就执行commit提交的操作,这样所有参与者的事务全部同时进行提交;如果返回的应答消息有一个给了否定,那么协调者则发起rollback回滚的操作,这样所有的参与者都得回滚

在这里插入图片描述

两阶段提交完全依赖与参与者的本地事务的acid,通过每个参与者的事务,从而保证所有事务的执行

3,代码模拟两阶段提交

接下来通过一段代码来模拟两阶段提交,先获取订单表的连接,然后获取XAResource资源实例,并且设置对应的事务id,让资源管理器绑定事务管理器,然后执行预提交操作,最后收集两个与提交的结果,通过判断结果的value值,在如果都是肯定答复的话,那么二者都执行commit提交操作,否则执行rollback回滚操作

public static void main(String[] args) throws SQLException {//true表示打印XA语句,,用于调试boolean logXaCommands = true;// 获得资源管理器操作接口实例 RM1Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_order", "root", "root");XAConnection xaConn1 = new MysqlXAConnection((com.mysql.jdbc.Connection) conn1, logXaCommands);XAResource rm1 = xaConn1.getXAResource();// 获得资源管理器操作接口实例 RM2Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_storage", "root", "root");XAConnection xaConn2 = new MysqlXAConnection((com.mysql.jdbc.Connection) conn2, logXaCommands);XAResource rm2 = xaConn2.getXAResource();// AP请求TM执行一个分布式事务,TM生成全局事务idbyte[] gtrid = "g12345".getBytes();int formatId = 1;try {// ==============分别执行RM1和RM2上的事务分支====================// TM生成rm1上的事务分支idbyte[] bqual1 = "b00001".getBytes();Xid xid1 = new MysqlXid(gtrid, bqual1, formatId);// 执行rm1上的事务分支rm1.start(xid1, XAResource.TMNOFLAGS);//One of TMNOFLAGS, TMJOIN, or TMRESUME.PreparedStatement ps1 = conn1.prepareStatement("INSERT into order_tbl(user_id,commodity_code,count,money,status) VALUES (1001,2001,2,10,1)");ps1.execute();rm1.end(xid1, XAResource.TMSUCCESS);// TM生成rm2上的事务分支idbyte[] bqual2 = "b00002".getBytes();Xid xid2 = new MysqlXid(gtrid, bqual2, formatId);// 执行rm2上的事务分支rm2.start(xid2, XAResource.TMNOFLAGS);PreparedStatement ps2 = conn2.prepareStatement("update stock_tbl set count=count-2 where commodity_code=2001");ps2.execute();rm2.end(xid2, XAResource.TMSUCCESS);// ===================两阶段提交================================// phase1:询问所有的RM 准备提交事务分支int rm1_prepare = rm1.prepare(xid1);int rm2_prepare = rm2.prepare(xid2);// phase2:提交所有事务分支boolean onePhase = false;//TM判断有2个事务分支,所以不能优化为一阶段提交if (rm1_prepare == XAResource.XA_OK&& rm2_prepare == XAResource.XA_OK) {//所有事务分支都prepare成功,提交所有事务分支rm1.commit(xid1, onePhase);rm2.commit(xid2, onePhase);} else {//如果有事务分支没有成功,则回滚rm1.rollback(xid1);rm2.rollback(xid2);}} catch (XAException e) {// 如果出现异常,也要进行回滚e.printStackTrace();}}

4,两阶段提交的缺陷

虽说两阶段提交确实可以实现分布式事务,但是两阶段提交也存在着一定的缺陷。

事务管理器高可用:首先是事务管理器收集信息的问题,在收集时如何保证高可用问题,比如可以通过redis或者mysql将数据收集,然后再发出相关的指令,但是如果此时宕机要如何保证,因此可以做一些集群等,从而解决事务管理器的单点故障问题,不会让整个系统卡死

同步阻塞问题:由于第一阶段和第二阶段时一个完整的事务,因此只有第二阶段执行完第一段才能释放接连,如果出现延迟情况,那么就可能造成连接延迟阻塞等问题,如果大量的连接进来,那么就可能在成整个系统阻塞

提交/回滚不一致问题:由于在整个系统都是使用RPC的模式进行网络通信,如上面的订单和库存系统,假设订单的本地事务在预提交阶段给了一个否定消息,那么订单事务和扣减库存事务都得回滚,如果订单事务回滚成功,但是库存事务由于网络原因回滚失败,那么就造成少卖问题,甚至可能会涉及到账户余额等问题。

相关文章:

【分布式事务-01】分布式事务之2pc两阶段提交

redis系列整体栏目 内容链接地址【一】分布式事务之2pc两阶段提交https://zhenghuisheng.blog.csdn.net/article/details/142406325 分布式事务之2pc两阶段提交 一,分布式事务之2pc两阶段提交1,两阶段提交(2pc)2,2pc两阶段提交实现思路3&…...

docker 安装 rabbitMQ

第一步:准备工作 # 打开docker目录 [rootMuYu ~]# cd /usr/local/docker/ # 创建rabbitmq文件夹 [rootMuYu docker]# mkdir rabbitmq # 打开rabbitmq文件夹 [rootMuYu docker]# cd rabbitmq/ # 创建挂载目录 [rootMuYu rabbitmq]# mkdir data 第二步&#xff…...

知识改变命运 数据结构【java对象的比较】

0:前言 在基本数据类型中,我们可以直接使用号比较是否相等,还记的学堆哪里时候,插入一个数据,就会与其他数据进行比较,当时我们传入的是Integer类型,在Integer类里面已经实现了compare。 如果…...

01_23 种设计模式之《简单工厂模式》

文章目录 一、什么是设计模式二、设计模式类型简单工厂模式及应用场景定义抽象产品类和具体产品类实现工厂类客户端代码注意事项 一、什么是设计模式 设计模式:在软件研发过程中,经过实战验证,用于解决在特定环境下、重复出现的,…...

Android 12.0 关于定制自适应AdaptiveIconDrawable类型的动态日历图标的功能实现系列一

1.前言 在12.0的系统rom定制化开发中,在关于定制动态日历图标中,原系统是不支持动态日历图标的功能,所以就需要从新 定制动态时钟图标关于自适应AdaptiveIconDrawable类型的样式,就是可以支持当改变系统图标样式变化时,动态日历 图标的背景图形也跟着改变,所以接下来就来…...

【源码+文档+调试讲解】基于安卓的小餐桌管理系统springboot框架

摘 要 相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低运营人员成本,实现了小餐桌的标准化、制度化、程序化的管理,有效地防止了小餐桌的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询和修…...

C语言中的文件操作(二)

C语言中的文件操作&#xff08;一&#xff09;-CSDN博客https://blog.csdn.net/Xiaodao12345djs/article/details/142746010?spm1001.2014.3001.5501 四、文件的顺序读写 1、fputc (字符输出函数/写) 将一个字符写入文件中 #include <stdio.h>int main() {FILE* pf fo…...

【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则

文章目录 C 继承详解&#xff1a;初阶理解与实战应用前言第一章&#xff1a;继承的基本概念与定义1.1 继承的概念1.2 继承的定义 第二章&#xff1a;继承中的访问权限2.1 基类成员在派生类中的访问权限2.2 基类与派生类对象的赋值转换2.2.1 派生类对象赋值给基类对象2.2.2 基类…...

Ubuntu 22.04 安装 KVM

首先检查是否支持 CPU 虚拟化&#xff0c;现在的 CPU 都应该支持&#xff0c;运行下面的命令&#xff0c;大于0 就是支持。 egrep -c (vmx|svm) /proc/cpuinfo安装 Libvirt apt install -y qemu-kvm virt-manager libvirt-daemon-system virtinst libvirt-clients bridge-uti…...

101 公司战略的基本概念

公司战略的概念 传统概念&#xff08;战略是终点途径&#xff09;&#xff1a;计划性、全局性、长期性现代概念&#xff08;战略是途径&#xff09;&#xff1a;应变性、竞争性、风险性综合概念&#xff08;前二者的折中&#xff09;&#xff1a;预先性、反应性公司的使命与目标…...

【devops】devops-ansible之剧本初出茅庐--搭建rsync和nfs

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8》从问题中去学习k8s 《docker学习》暂未更…...

@RestController 和 @Controller 注解的联系及要点

1. RestController • RestController 是 Spring 4.0 引入的一个注解&#xff0c;它相当于 Controller ResponseBody组合注解。 主要作用&#xff1a;主要用于构建 RESTful Web 服务。标注 RestController 的类里的所有方法&#xff0c;返回的都是 JSON 或 XML 等格式的数据…...

机器学习篇-day03-线性回归-正规方程与梯度下降-模型评估-正则化解决模型拟合问题

一. 线性回归简介 定义 线性回归(Linear regression)是利用 回归方程(函数) 对 一个或多个自变量(特征值)和因变量(目标值)之间 关系进行建模的一种分析方式。 回归方程(函数) 一元线性回归: y kx b > wx b k: 斜率, 在机器学习中叫 权重(weight), 简称: w b: 截距, 在机…...

图像人脸与视频人脸匹配度检测

import cv2 import dlib import numpy as np import os from pathlib import Path# 加载预训练模型 face_recognition_model "dlib_face_recognition_resnet_model_v1.dat" face_recognition_net dlib.face_recognition_model_v1(face_recognition_model)detector …...

【AI绘画】Midjourney进阶:对称构图详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;什么是构图为什么Midjourney要使用构图 &#x1f4af;对称构图特点使用场景提示词书写技巧测试 &#x1f4af;小结 &#x1f4af;前言 通常来学习AI绘画的人可以分为…...

道路积水检测数据集 1450张 路面积水 带分割 voc yolo

道路积水检测数据集 1450张 路面积水 带分割 voc yolo 分类名: (图片张数&#xff0c; 标注个数) puddle:(1468,1994) 总数:(1468&#xff0c;1994) 总类(nc): 1类 道路积水检测数据集介绍 项目名称 道路积水检测数据集 项目概述 本数据集包含1450张带有标注的图像&#x…...

上门安装维修系统小程序开发详解及源码示例

随着智能家居和设备的普及&#xff0c;消费者对上门安装和维修服务的需求日益增加。为了满足这一市场需求&#xff0c;开发一款上门安装维修系统小程序成为了一种有效的解决方案。本文将详细介绍上门安装维修系统小程序的开发过程&#xff0c;并提供一个简单的源码示例&#xf…...

03_23 种设计模式之《原型模式》

文章目录 一、原型模式基础知识原型模式的结构应用场景 实例拷贝构造函数被调用场景如下&#xff1a;典型的应用场景&#xff1a; 一、原型模式基础知识 原型模式是一种创建型设计模式&#xff0c;其功能为复制一个运行时的对象&#xff0c;包括对象各个成员当前的值。而代码又…...

【秋招笔试】10.08华为荣耀秋招(已改编)-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 本次的三题全部上线…...

基于ResNet50模型的船型识别与分类系统研究

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...