分布式事务解决方案

事务

ACID特性:
原子性(Atomicity),一致性(Consistency),隔离性(lsolation),持久性(Durability)
1. 原子性
原子性是指一个事务是一个不可再分割的工作单位,事务中的操作要么都执行,要么都不执行
例如:
A给B转账,如果B的账户操作失败,则本次交易失败,A和B的账户都不会进行修改。

2. 一致性
一致性是指在执行一个事务前和后,数据库的完整性约束没有没有被破坏。也就是说事务不能破坏数据库的完整性以及业务逻辑的一致性
例如:
业务逻辑一致性:A给B转账,无论是否操作成功,两者的账户余额之和应该是不变的。
数据库完整性:数据库的约束关系应该是正确的,例如唯一索引,主键等。

3. 隔离性
隔离性是指多个事务并发时,每个事务应该是隔离的,一个事务不应影响其他事务的运行效果

在并发环境当中,不同的事务访问相同的数据时,每个事务都有各自的完整的数据空间,由于并发事务所做的修改必须与并发的其他事务的修改隔离,所以事务查看数据更新时,数据所处的状态要么是另一个事务开始前的状态,要么就是另一个事务结束后的状态,不会查看到中间状态数据

事务最复杂的问题都是由隔离性引起的,但是完全的隔离是不现实的,完全的隔离要求数据库同一时间只能执行一个事务,这样会严重影响性能


经典的X/OpenDTP事务模型

这个标准提出了使用二阶段提交(2PC – Two-Phase-Commit)来保证分布式事务的完整性。J2EE也遵循了X/OpenDTP规范,设计并实现了java里的分布式事务编程接口规范-JTA

X/OpenDTP角色
在X/OpenDTP事务模型中,定义了三个角色
AP: application: 应用程序,也就是业务层。哪些操作属于一个事务,就是AP定义的
RM: Resource Manager:资源管理器。一般是数据库,也可以是其他资源管理器,比如消息队列,文件系统
TM: Transaction Manager :事务管理器、事务协调者,负责接收来自用户程序(AP)发起的XA事务指令,并调度和协调参与事务的所有RM(数据库),确保事务正确完成

角色架构如下图所示:

2PC(二阶段提交)2PC主要为了保证分布式事务的原子性
很显然 leader/follower模式的集群数据更新也符合2PC的特性
二阶段提交的意思很简单,其实就是一部操作分为两步来走

  • 第一步是事务管理器通知资源管理器开始预备操作,执行器返回预备结果
  • 第二步是事务管理器根据预备情况通知源管理器是执行提交操作,还是回滚操作 

将提交分成两阶段进行的目的很明确,一是尽可能晚地提交事务,让事务在提交前尽可能地完成
所有能完成的工作,二是当第一步失败的时候还可以执行回滚操作,在没有确认之前
第一阶段

RM在第一阶段会做两件事:
  1.记录事务日志:reduo,undo
  2.返回给TM信息,ok、error

第二阶段


但是2PC存在问题: 
如果第一阶段完成后TM宕机或网络出现故障了,此时RM会一直阻塞,发生了死锁,因为没有timeout机制,3pc就针对此问题进行了改造,加入了timeout机制

我们发现好像一致性和可用性存在了冲突,这就是著名的CAP理论


CAP理论
CAP的含义:

  • C:Consistency 一致性:同一数据的多个副本是否实时相同
  • A:Availability 可用性:在一定时间内系统返回一个明确的结果,则称为该系统可用
  • P:Partition tolerance 分区容错性:将同一服务分布在多个系统中,从而保证某一个系统宕机,仍然有其他系统提供相同的服务

CAP理论告诉我们,在分布式系统中,C、A、P三个条件中我们最多只能选择两个。那么问题来了,究竟选择哪两个条件较为合适呢?
对于一个业务系统来说,分区容错性是必须要满足的条件

业务系统之所以使用分布式系统,主要原因有两个:
(1)提升整体性能 当业务量猛增,单个服务器已经无法满足我们的业务需求的时候,就需要使用分布式系统,使用多个节点提供相同的功能
(2)实现分区容错性 单一节点 或 多个节点处于相同的网络环境下,那么会存在一定的风险,万一该机房断电、该地区发生自然灾害,那么业务系统就全面瘫痪了。为了防止这一问题,采用分布式系统,将多个子系统分布在不同的地域、不同的机房中,从而保证系统高可用性。

这说明分区容错性是分布式系统的根本,如果分区容错性不能满足,那使用分布式系统将失去意义,也就是说我们只能选择AP和CP

对一些业务系统来讲可用性也尤为重要。在大谈用户体验的今天,如果业务系统时常出现“系统异常”、响应时间过长等情况,这使得用户对系统的好感度大打折扣,在互联网行业竞争激烈的今天,系统的间歇性不可用会立马导致用户流向竞争对手。因此,我们只能通过牺牲一致性来换取系统的可用性和分区容错

在设计钱的部分需要使用强一致性

强一致性和最终一致性
2PC是强一致性协议
zookeeper中因为2PC存在的问题,使用过半提交(弱一致性)来解决这个问题
所谓的“牺牲一致性”并不是完全放弃数据一致性,而是牺牲强一致性换取弱一致性,这就是Base理论

Base理论

  • BA:Basic Available 基本可用

            整个系统在某些不可抗力的情况下,仍然能够保证“可用性”,即一定时间内仍然能够返回一个明确的结果。只不过“基本可用”和“高可用”的区别是:“一定时间”可以适当延长 当举行大促时,响应时间可以适当延长。给部分用户返回一个降级页面 给部分用户直接返回一个降级页面,从而缓解服务器压力。但要注意,返回降级页面仍然是返回明确结果。

  • S:Soft State:柔性状态(数据存在中间状态) 同一数据的不同副本的状态,可以不需要实时一致

例如我们在支付订单的时候,存在等待支付--》开始支付--》支付中--》支付成功/支付失败,这就是状态的流转,支付中就是中间状态,可能这个时候已经支付成功了,但是我们不知道,所以我们可以定时去查询支付结果,将结果变为最终状态

  • E:Eventual Consisstency:最终一致性 同一数据的不同副本的状态,可以不需要实时一致,但一定要保证经过一定时间后仍然是一致的

分布式事务的解决方案

TCC与2PC、3PC一样,都是分布式事务的一种实现方案

(1)最大努力通知方案 :


(2)TCC两阶段补偿方案:


TCC是Try-Confifirm-Cancel, 比如在支付场景中,先冻结一笔资金,再去发起支付。如果支付成功,则
讲冻结资金进行实际扣除;如果支付失败,则取消资金冻结

  • Try阶段

完成所有业务检查(一致性),预留业务资源(准隔离性)

  • Confifirm阶段

确认执行业务操作,不做任何业务检查,只使用Try阶段预留的业务资源

  • Cancel阶段

取消Try阶段预留的业务资源。Try阶段出现异常时,取消所有业务资源预留请求


(3)基于可靠性分布式消息队列的最终一致性
RocketMQ消息的事务架构设计:
1. 生产者执行本地事务,修改订单支付状态,并且提交事务
2. 生产者发送事务消息到broker上,消息发送到broker上在没有确认之前,消息对于consumer是不可见状态
3. 生产者确认事务消息,使得发送到broker上的事务消息对于消费者可见
4. 消费者获取到消息进行消费,消费完之后执行ack进行确认
5. 这里可能会存在一个问题,生产者本地事务成功后,发送确认消息到broker上的时候失败了怎么办(第2步)?
这个时候意味着消费者无法正常消费到这个消息。所以RocketMQ提供了消息回查机制,如果事务消息一直处于中间状态,broker会发起回调去查询生产者这个事务的处理状态。一旦发现事务处理成功,则把当前这条消息设置为可见

第3步是回查,也就是说rocketMQ是可以调用生产者的方法的

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值