.Net Core with 微服务 - 分布式事务 - 2PC、3PC
最近比较忙,好久没更新了。这次我们来聊一聊分布式事务。
在微服务体系下,我们的应用被分割成多个服务,每个服务都配置一个数据库。如果我们的服务划分的不够完美,那么为了完成业务会出现非常多的跨库事务。即使按照 DDD 的原则来切分服务还是免不了有的业务场景需要多个业务同时提交成功或者同时回滚的场景。比如会员使用积分下订单这个场景,那么会员服务的积分扣减需要跟订单下单成功同时完成。如果下单成功,但是扣减积分接口失败,那么就会造成数据的不一致性。这个时候我们就需要使用分布式事务来保证数据的一致性。
由于分布式事务要介绍的东西比较多,这一篇只介绍 2PC、3PC 的基本概念,所以 .net 相关的内容大概也只会出现在标题上一次,笑哭。
什么是 2PC
2PC 既 Two-phase Commit ,中文翻译为二阶段提交。2PC 要求每个事务的参与方都把一个事务抽象成2个阶段。下面大概分析下 2PC 事务的流程。
首先提出2个概念:
- 参与方
分布式事务中所有需要同时进入事务的业务方。 - 协调器
分布式环境下为了对多个事务参与方进行统一的调度管理,我们需要一个调度器。
阶段一
事务开始后,协调器下达事务开始的命令,每个参与方收到命令后开始执行准备阶段(Prepare phase),所谓准备阶段就是执行本地事物,这个时候资源被锁定,但是不进行提交。如果这个阶段没有发生异常,那么参与方会通知协调器“执行成功”。如果某个参与方在这个阶段失败了,那么同样通知协调器“执行失败”,协调器会给所有参与方发布回滚的命令。参与方在收到“回滚”命令后执行回滚操作。
阶段二
如果所有的参与方在阶段一全部响应成功,那么协调器就会给每个参与方发布执行提交操作的命令。参与方收到提交命令后开始尝试进行事务提交。如果事务提交成功,参与方会通知协调器“提交成功”。待到所有的参与方全部回复“提交成功”,那么本次事务成功执行。

到这里我们可以看到 2PC 模型跟数据库的事务模型是高度契合的,所以 2PC 经常用来把多个数据库事物包装成一个分布式事务的场景。事实上大多数数据库如:oracle,mysql等自己已经实现了基于XA协议的2PC 事务。
2PC 的问题
- 在一阶段,假设参与方A执行事务成功并通知了协调器,参与方B执行失败,由于网络的问题一直无法上报给协调器,这个时候会造成参与方A事务一直是等待提交状态,阻塞整个业务。这个时候就需要引入超时机制,在一定时间内没收到协调器的指令后直接回滚事务。
- 在一阶段,假设参与方A执行事务成功并通知了协调器,参与方B执行成功,由于网络的问题一直无法上报给协调器,这个时候会造成参与方A、参与方B事务一直是等待提交状态,阻塞整个业务。这个时候不光在参与方A一侧需要引入超时机制,在参与方B同样需要进入超时机制来自动回滚事务。
- 在二阶段,如果参与方A提交成功,参与方B因为某些原因提交失败,或者是服务器宕机或者是网络原因B一致没有收到提交的指令,这个时候就会造成数据不一致,这种情况 2PC 几乎没有补偿能力,只能依靠后期手动修复数据。
- 如果协调器在一阶段中间挂了,那么跟以上1、2情况类似,需要通过超时机制来补偿。
- 如果协调器在二阶段中间挂了,比如只给参与方A发送了提交请求,那么就会造成以上问题3类似的问题,造成数据不一致。
- 2PC 因为依赖数据库本地事务,我们知道事务一旦开启就会阻塞后面的业务执行。所以该方法在并发高的情况下会有比较大的性能问题。而且他所阻塞的时间远远高于单机事务,因为它所耗的时间取决于执行时间最长的那个参与方所执行的事务。
3PC
由于 2PC 的众多问题,又有人发明了 3PC 事务。
3PC 事务是对 2PC 的一次改进:
- 首先引入了超时机制避免事务长时间阻塞。
- 3PC 在 2PC 的 Prepare phase 阶段之前又加入了一个阶段叫做 CanCommit 阶段。现在3个阶段分别是:CanCommit、PreCommit、DoCommit 。后两个阶段大致可以映射到 2PC 的一阶段跟二阶段。那么CanCommit 阶段是干嘛的呢?CanCommit 只是一次预检,协调器先问一下各个参与者是否可以进行事务,同时也校验一下当前的网络是否正常,参与者服务器有没有宕机。经过这一次校验后,至少可以比 2PC 安全一点,减少因为当前网络故障服务宕机带来的故障的概率。但是 3PC 任然无法完全解决问题,在 DoCommit 命令发布后,依然有可能部分参与者提交成功,部分失败,2PC 数据不一致的问题 3PC 依然无法避免。
总结
以上简单介绍了 2PC、3PC 分布式事务的原理。我们可以看到 2PC 在理想情况下是可以保证数据一致性的。但是在复杂的生产环境下服务器宕机、网络故障的情况时有发生,最终导致数据的不一致,并且 2PC 的性能也差强人意。3PC 虽然改进了 2PC 的一些缺点,但是仍然没有解决掉最致命的数据不一致的问题、以及性能的问题。所以 2PC、3PC 并不是分布式事务的首选方案。那么下期我们将继续这个话题,继续介绍 TCC 分布式事务。
相关文章
NET Core with 微服务 - 什么是微服务
.Net Core with 微服务 - 架构图
.Net Core with 微服务 - Ocelot 网关
.Net Core with 微服务 - Consul 注册中心
.Net Core with 微服务 - Seq 日志聚合
.Net Core with 微服务 - Elastic APM
.Net Core with 微服务 - Consul 配置中心
.Net Core with 微服务 - Polly 熔断降级
关注我的公众号一起玩转技术

.Net Core with 微服务 - 分布式事务 - 2PC、3PC的更多相关文章
- .Net Core with 微服务 - 分布式事务 - TCC
上一次我们讲解了分布式事务的 2PC.3PC .那么这次我们来理一下 TCC 事务.本次还是讲解 TCC 的原理跟 .NET 其实没有关系. TCC Try 准备阶段,尝试执行业务 Confirm 完 ...
- .Net Core with 微服务 - 分布式事务 - 可靠消息最终一致性
前面我们讲了分布式事务的2PC.3PC , TCC 的原理.这些事务其实都在尽力的模拟数据库的事务,我们可以简单的认为他们是一个同步行的事务.特别是 2PC,3PC 他们完全利用数据库的事务能力,在一 ...
- Spring Cloud Alibaba | 微服务分布式事务之Seata
Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...
- 微服务分布式事务之LCN、TCC
在亿级流量架构之分布式事务解决方案对比中, 已经简单阐明了从本机事务到分布式事务的演变过程, 文章的最后简单说明了TCC事务, 这儿将会深入了解TCC事务是原理, 以及理论支持, 最后会用Demo举例 ...
- .Net Core with 微服务 - 使用 AgileDT 快速实现基于可靠消息的分布式事务
前面对于分布式事务也讲了好几篇了(可靠消息最终一致性 分布式事务 - TCC 分布式事务 - 2PC.3PC),但是还没有实战过.那么本篇我们就来演示下如何在 .NET 环境下实现一个基于可靠消息的分 ...
- spring cloud+dotnet core搭建微服务架构:服务发现(二)
前言 上篇文章实际上只讲了服务治理中的服务注册,服务与服务之间如何调用呢?传统的方式,服务A调用服务B,那么服务A访问的是服务B的负载均衡地址,通过负载均衡来指向到服务B的真实地址,上篇文章已经说了这 ...
- spring cloud+dotnet core搭建微服务架构:配置中心续(五)
前言 上一章最后讲了,更新配置以后需要重启客户端才能生效,这在实际的场景中是不可取的.由于目前Steeltoe配置的重载只能由客户端发起,没有实现处理程序侦听服务器更改事件,所以还没办法实现彻底实现这 ...
- spring cloud+dotnet core搭建微服务架构:Api授权认证(六)
前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...
- spring cloud+.net core搭建微服务架构:Api授权认证(六)
前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...
随机推荐
- 单片机引脚扩展芯片74HC595手工分解实验
我们先来看下效果 74HC595是常用的串转并芯片,支持芯片级联实现少量IO口控制多个IO口输出功能 14脚:DS,串行数据输入引脚 13脚:OE, 输出使能控制脚,它是低电才使能输出,所以接GND ...
- 8、ITSM基本概念(2)
6.流程和职能: 7.故障管理: (1)故障管理的输入和输出: (2)故障管理的目标: 优先解决影响度大的事件: (3)故障管理的指标: (4)故障管理的流程: 8.问题管理: (1)问题管理的输入和 ...
- Sherlock and His Girlfriend题解
题目描述 Sherlock 有了一个新女友(这太不像他了!).情人节到了,他想送给女友一些珠宝当做礼物. 他买了 n件珠宝.第i 件的价值是i+1.那就是说,珠宝的价值分别为2,3,4,-,n+1 . ...
- 无需手动输入命令,简单3步即可在K8S集群中启用GPU!
随着全球各大企业开始广泛采用Kubernetes,我们看到Kubernetes正在向新的阶段发展.一方面,Kubernetes被边缘的工作负载所采用并提供超越数据中心的价值.另一方面,Kubernet ...
- HTTP:Java实现HTTP请求的三种方式
目前JAVA实现HTTP请求的方法用的最多的有两种: 一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,H ...
- Java实验项目二——打印某年某月日历
Program:打印万年历(输入年份,月份,输出该月的日历,已知1900年1月1日是星期一), 要 求: (1)编写一个方法判断闰年: (2)编写一个方法判断某年某月有多少天: (3)编写一个方法计算 ...
- webpack(11)配置文件分离为开发配置、生成配置和基础配置
前言 上篇我们已经配置好了本地开发服务器,但是配置的相对比较凌乱,一个文件中有些是开发时用到的配置,有些是生成时用到的配置,有些是开发和生成都要用到的配置,所以我们这里把环境分为3个环境 webpac ...
- python04篇 文件操作(二)、集合
一.文件操作(二) 1.1 利用with来打开文件 # with open ,python 会自动关闭文件 with open('a.txt', encoding='utf-8') as f: # f ...
- 添加Lombok插件后调用Setter或Getter方法IDEA编译错误
虽然添加Lombok插件,但是调用Setter或Getter方法IDEA编译错误,主要原因如下 解决办法:
- 前端开发入门到进阶第三集【Jsonp】
/* $.ajax({ type : "get", url : "${loginInfo.SSO_BASE_URL }/user/token/" + token ...