分布式事务的具体实现:两阶段提交(2PC)

2024-04-16 02:20

本文主要是介绍分布式事务的具体实现:两阶段提交(2PC),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

分布式事务的具体实现:两阶段提交(2PC)

🍔前言

”分布式事务“顾名思义,指的是涉及到多个分布式系统或者多个数据库的事务操作。在分布式系统中,如果一个事务涉及到多个独立的组件或者服务,每个组件或服务可能位于不同的物理节点上,那么这个事务就被称为分布式事务。

在分布式系统中实现分布式事务是一个复杂的问题,因为涉及到多个独立的组件或者服务,可能存在网络延迟、通信故障、节点故障等因素。为了保证分布式事务的一致性和可靠性,需要使用合适的事务管理协议和机制,如两阶段提交(2PC)、三阶段提交(3PC)、基于消息的事务、分布式事务管理器等。这些方法都旨在确保在分布式环境中执行的事务要么全部提交,要么全部回滚,从而保证数据的一致性。🤗

而两阶段提交又是较为简单和常用的实现协议,本文主要也是讲述两阶段提交的

简单贴下各协议的定义:(可以先只看两阶段提交,其他还不参与讨论)

  1. **两阶段提交(Two-Phase Commit,2PC)**是一种用于分布式系统中实现分布式事务的协议。它分为两个阶段:

    准备阶段:事务协调者询问所有参与者是否准备好提交或者回滚事务,并等待它们的响应。

    提交阶段:如果所有参与者都准备好提交,事务协调者通知它们提交事务;如果有任何一个参与者未能准备好或者出现错误,事务协调者通知它们回滚事务。

  2. 三阶段提交(3PC):三阶段提交是对两阶段提交的改进,通过在第一阶段引入额外的准备阶段来解决某些情况下的阻塞问题。在三阶段提交中,除了准备和提交阶段外,还有一个称为“预提交”或“预准备”阶段,用于减少参与者在第二阶段的等待时间。

  3. 基于消息的事务:在分布式系统中,可以使用消息队列等消息传递机制来实现事务的一致性。在这种方法中,事务的各个参与者将事务信息发送到消息队列中,协调者会根据消息的发送情况来决定事务是否提交或者回滚。

  4. 两阶段提交的改进:针对两阶段提交的一些不足之处,还有一些改进的方法,如柔性事务(Flexible Transactions)、Paxos协议、Raft算法等。这些方法都是针对分布式系统中事务一致性的改进和优化。

  5. 分布式事务管理器:一些分布式数据库系统或者中间件提供了分布式事务管理器(如Java Transaction API,JTA),它们提供了高级的事务管理功能,帮助开发者在分布式环境中管理事务。

🍟两阶段提交协议的实现和作用

MySQL的两阶段提交(Two-Phase Commit,2PC)是一种用于确保分布式事务的一致性的协议。。MySQL的两阶段提交协议包括以下两个阶段:(请仔细阅读两个阶段的具体实现

  1. 准备阶段(Prepare Phase)
    • 在这个阶段,事务的协调者(通常是MySQL服务器)会向所有涉及的数据库或者资源管理器发送准备请求。
    • 每个数据库或者资源管理器收到准备请求后,会执行相应的操作,并且记录准备状态(prepared)。如果准备成功,就向协调者发送准备就绪的信号。
    • 协调者等待所有参与者都发送准备就绪的信号,如果有任何一个参与者未能准备就绪或者出现了错误,协调者将会发送回滚请求给所有参与者。
  2. 提交阶段(Commit Phase)
    • 如果所有的参与者都准备就绪,协调者会向它们发送提交请求。
    • 参与者接收到提交请求后,会正式提交事务,并且释放相关资源。
    • 如果有任何一个参与者未能接收到提交请求或者出现了错误,协调者将会发送回滚请求给所有参与者。

这些话说的有点笼统且并没有和具体数据库操作连接起来:更加详细的操作如下(👶也能看懂233):

第一阶段 - 准备阶段:

  1. 协调者发送准备请求: 协调者向所有参与者发送准备请求,询问它们是否可以执行事务操作,并等待它们的响应。
  2. 参与者准备就绪: 参与者在收到准备请求后,进行本地事务的准备工作,如锁定资源、写入日志等,并向协调者发送准备就绪的消息
  3. 协调者等待响应: 协调者收到所有参与者的准备就绪消息后,等待一段时间以确保所有参与者都已准备就绪。

第二阶段 - 提交阶段:

  1. 协调者发送提交请求: 如果协调者收到了所有参与者的准备就绪消息,它会向所有参与者发送提交请求,要求它们提交事务。
  2. 参与者执行提交操作: 参与者在收到提交请求后,正式执行事务提交操作,并释放相关资源。如果提交成功,参与者会向协调者发送提交成功的消息;如果提交失败,参与者会向协调者发送提交失败的消息。
  3. 协调者等待结果: 协调者收到所有参与者的提交结果后,根据结果决定是否将事务标记为提交或者回滚。如果所有参与者都提交成功,协调者将向应用程序返回提交成功的消息;如果有任何一个参与者提交失败或者超时未响应,协调者将向应用程序返回提交失败的消息,并要求所有参与者回滚事务。

通过这两个阶段,MySQL的两阶段提交协议可以确保要么所有的数据库都成功提交事务,要么所有的数据库都回滚事务,从而保证了分布式系统中的数据一致性。

就像是军训一样,准备阶段:教官让所有同学都立正站好,所有同学都得对齐站好,谁没有站好,全部同学都得重新立正,直到所有同学都准备好,然后,训练阶段:同学们都站一排齐步走,只要有一个没走齐的就重新开始;(👴已经尽力去解释了,我相信即使没有学过计算机的应该也知道这玩意是什么了,嘿嘿);看着是不是毫无压力,

🌭两阶段提交的必要性

我们都知道了两阶段协议其实就是事务在分布式的具体实现;所以其也拥有了事务的特征:核心目的是确保分布式事务的原子性和一致性,即要么所有数据库都成功提交事务,要么都回滚事务,从而保证了数据的一致性。要是总结的话,两阶段提交协议的必要性包括以下几个方面:

  1. 数据一致性:在分布式系统中,由于涉及到多个独立的数据库或者资源管理器,可能出现某些数据库提交成功而其他数据库提交失败的情况,导致数据不一致。两阶段提交协议通过协调者的调度和协调,确保了要么所有数据库都成功提交事务,要么都回滚事务,从而保证了数据的一致性。
  2. 事务的原子性:原子性是事务的基本属性,表示事务要么全部提交成功,要么全部回滚失败。在分布式系统中,要保证所有参与者都能够按照一致的方式提交或者回滚事务,这就需要引入协调者来统一管理事务的提交和回滚过程,而两阶段提交协议提供了这样的机制。
  3. 避免数据丢失:两阶段提交协议确保了在所有数据库都准备就绪后才进行提交操作,避免了数据丢失或不完整的情况发生。即使在网络分区或者节点故障等异常情况下,协调者也能够根据参与者的响应情况来决定是否提交或者回滚事务,从而保证了数据的完整性和可靠性。

🍿实战案例

下边会以银行转账的项目案例来进一步说明其必要性(分布式多数据库系统)

假设有一个在线银行系统,允许用户进行转账操作。在这个系统中,每当用户发起一笔转账请求时,需要在转出账户和转入账户对应的数据库中进行更新操作。下面是针对这个场景的两阶段提交的必要性分析:

第一阶段 - 准备阶段:

  1. 用户A向用户B转账100元。系统需要在用户A的账户数据库和用户B的账户数据库中分别执行相应的更新操作。
  2. 在准备阶段,系统向用户A的账户数据库发送准备请求,要求进行扣款操作,并等待其响应。
  1. 收到准备请求: 转出账户数据库收到系统的准备请求后,首先检查账户余额是否足够扣款,并锁定转出账户以防止并发操作
  2. 准备就绪响应: 如果账户余额足够扣款,并且成功锁定转出账户,转出账户数据库向系统发送准备就绪的响应,表示可以执行扣款操作。

​ 3.同时,系统向用户B的账户数据库发送准备请求,要求进行存款操作,并等待其响应。

  1. 收到准备请求: 转入账户数据库收到系统的准备请求后,会锁定转入账户以防止并发操作,并准备执行存款操作。
  2. 准备就绪响应: 转入账户数据库向系统发送准备就绪的响应,表示可以执行存款操作。

第二阶段 - 提交阶段:

  1. 当所有数据库都准备就绪后,系统向所有数据库发送提交请求。
  2. 用户A的账户数据库接收到提交请求后,正式执行扣款操作,并将结果持久化到数据库中。
  1. 收到提交请求: 如果在准备阶段收到了系统的提交请求,转出账户数据库会执行实际的扣款操作,并将转出账户的余额更新到数据库中。
  2. 提交成功响应: 扣款操作成功完成后,转出账户数据库向系统发送提交成功的响应,表示转出账户的扣款操作已经完成并成功提交。
  3. 回滚操作: 如果在准备阶段或提交阶段出现任何错误或失败情况,转出账户数据库会执行回滚操作,取消已经扣款的操作,并释放转出账户的锁定状态。

​ 3.用户B的账户数据库接收到提交请求后,正式执行存款操作,并将结果持久化到数据库中。

  1. 收到提交请求: 在收到系统的提交请求后,转入账户数据库会执行实际的存款操作,并将转入账户的余额更新到数据库中。
  2. 提交成功响应: 存款操作成功完成后,转入账户数据库向系统发送提交成功的响应,表示转入账户的存款操作已经完成并成功提交。
  3. 回滚操作: 如果在准备阶段或提交阶段出现任何错误或失败情况,转入账户数据库会执行回滚操作,取消已经执行的存款操作,并释放转入账户的锁定状态。

必要性分析:

  1. 数据一致性:如果不使用两阶段提交,可能会出现一种情况,即用户A的账户数据库已经扣款成功,但是用户B的账户数据库却未能成功存款。这样会导致转账操作的数据不一致,用户的资金可能会出现异常。
  2. 保证事务的完整性:使用两阶段提交可以确保要么转账操作的所有数据库都成功提交,要么都回滚,从而保证了整个事务的完整性。
  3. 避免数据丢失:两阶段提交可以确保在所有数据库都准备就绪后才进行提交操作,避免了数据丢失或不完整的情况发生,提高了系统的稳定性和可靠性。

🧇总结

通过以上的分析,我总结出来一句话==“两阶段提交”这个新名词落实到具体作用上其实就是分布式事务的一种具体实现方法,他是定义的一种新协议,用于在分布式数据库中实现类似于事务的作用,以保证数据的一致性。==

虽然这篇博客有点点长或者说基础~~(有点冗长)~~🤐,甚至总结起来只有最后的这一句话,但是通篇看下来有助于复习事务的相关知识点,也可以对分布式事务有个大致的了解,对于之后的学习还是很有帮助的;🤤

通过这些概念的学习,在之后的go语言开发中我们会用到go-zero框架,他是基于分布式理念的微服务框架,到那时会我们对分布式事务的实现有一个更深层次的理解和应用;🥰

这篇关于分布式事务的具体实现:两阶段提交(2PC)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907560

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2