事务
原子性(atomicity)
一致性(consistency)
隔离性(isolation)
持久性(durability)
CAP理论
C(Consistency):一致性。服务A、B、C三个节点都存储了用户数据,三个节点的数据都需要保持同一时刻数据一致性
A(Availability):可用性。服务A、B、C三个节点,其中一个节点如果宕机了,不能影响整个集群对外提供服务。
P(Partition Tolerance):分区容错性就是允许系统通过网络协同工作,分区容错性要解决由于网络分区导致数据的不完整及无法访问等问题。
Base理论
BA(Basically Available):基本可用
S(Soft State):软状态
E(Eventually Consistent):最终一致性
全局事务
全局事务是基于DTP模型实现的,它规定了要实现分布式事务需要三种角色
AP(Application):应用系统(微服务)
TM(Transaction Manager):事务管理器(全局事务管理)
RM(Resource Manager):资源管理器(数据库)
什么时候会出现分布式事务
单体应用操作多个数据库
分布式架构
分布式事务实现的几种方式
两阶段提交
表决阶段
执行阶段
缺点
单点故障:如果事务管理器出现了故障,整个系统将不可用
同步阻塞:延迟了提交事件,加长了资源阻塞事件,不适合高并发的场景
数据不一致:如果执行到第二阶段,依然存在commit结果未知的情况,只有部分参与者接收到 commit 消息,部分没有收到,那也只有部分参与者提交了事务,依然会导致数据不一致问题
三阶段提交
三阶段提交相对于两阶段提交来说,增加了 CanCommit 阶段和超时机制。在一段规定时间内,如果服务器参与者没有接受到来自事务管理器的提交执行,那他们就会自己自动提交,这样子就能解决两阶段中单体故障问题
CanCommit:准备阶段。这个阶段要做的事就和两阶段提交一样,先去询问参与者是否有条件接收这个事务,这样子不会太暴力,一开始就直接干活锁死资源。
PreCommit:这个阶段是事务管理器向各个参加者发送准备提交请求,各个参与者接到请求或,将处理结果记录到自己的资源管理器中,如果准备好了,就会向协调者反馈ACK表示我已经准备好提交了。
DoCommit:这个就是从 预提交状态 转为 提交状态。事务管理器向各个参与者发送 提交 请求,参与者接收到请求后,就会各自执行自己事务的提交操作。将处理结果记录到自己的资源管理器中,并向协调者反馈 ACK 表示自己已经完成事务,如果有一个参与者未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送abort请求,从而中断事务。
三阶段提交解决的只是两阶段提交中 单体故障 的问题,因为加入了超时机制,这里的超时的机制作用于 预提交阶段 和 提交阶段。如果等待 预提交请求 超时,那参与者相当于说啥都没干,直接回到准备阶段之前。如果等到提交请求超时,那参与者就会提交事务了
TCC(Try Confirm Cancel)
它是属于补偿型分布式事务。它的核心思想是 针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作
Try: 尝试待执行的业务
这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的所有资源Confirm: 确认执行业务
确认执行业务的操作,不做任何业务检查,只使用Try阶段预留的业务资源。通常情况下,采用TCC则会认为 Confirm 阶段是不会出错的。只要 Try 成功,则 Confirm 一定成功。如果 Confirm 出错了,则需要引入重试机制或人工处理Cancel: 取消待执行的业务
取消 Try 阶段预留的业务资源。通常情况下,采用 TCC 则认为 Cancel 阶段也是一定能成功的,若 Cancel 阶段真的出错了,也要引入重试机制或人工处理
TCC 是业务层面的分布式事务,最终一致性,不会一直持有资源的锁
优点
把数据库层的二阶段提交上提到了应用层来实现,规避了数据库的 2PC(two-phase commit protocol) 性能低下问题
缺点
TCC 的 Try、Confirm 和 Cancel 操作功能需业务提供,开发成本高。TCC 对业务的侵入较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作
可靠消息事务
消息事务的原理是 将两个事务通过消息中间件来进行异步解耦
可靠消息服务方案是实现了 最终一致性。对比本地消息表实现方案,不需要再建立消息表。不用依赖本地数据库事务,适用于高并发的场景。RocketMQ 就很好的支持了消息事务。
如果最终还是不能成功进行投递,则需要人工干预
超时询问机制:服务A除了实现正常的业务流程之外,还是需要提供一个可供消息中间件事务询问的接口。在消息中间件第一次收到消息后便会开始计时,如果超过规定的时间没有收到后续的指令,就会主动调用服务A提供的事务询问接口,询问当前服务的状态,通常来说该接口会返回三种结果,中间件需要根据这三种不同的结果做出不同的处理:
提交:直接将该消息投递给服务B
回滚:直接将该消息丢弃
处理中:继续等待,重新计时
最大努力通知
最大努力通知也成为定期校对,是对可靠消息服务的进一步优化。它引入了本地消息表来记录错误消息,然后加入失败消息的定期校对功能,来进一步保证消息会被下游服务消费。
我曾经工作的一家电商公司ST
就是使用这个方案
分布式事务缺点
长时间锁定数据库资源,导致系统的响应不快,并发上不去。
网络抖动出现脑裂情况,导致事物参与者,不能很好地执行协调者的指令,导致数据不一致
单点故障:例如事物协调者,在某一时刻宕机,虽然可以通过选举机制产生新的Leader,但是这过程中,必然出现问题,而TCC,只有强悍的技术团队,才能支持开发,成本太高。
Seata
曾经我在一家电商公司ST
使用过,当时在订单模块接入了seata。在业务中使用的是AT模式,两段式提交方案
他把一个分布式事务理解成一个包含了若干分支事务的全局事务。而全局事务的职责是协调它管理的分支事务达成一致性,要么一起成功提交,要么一起失败回滚。也就是一荣俱荣一损俱损~
TCC 三段式提交,提交逻辑必然伴随着回滚的逻辑,这样的代码会使得项目非常臃肿,维护成本高
Seata 中存在几种重要角色
TC(Transaction Coordinator)
事务协调者。管理全局的分支事务的状态,用于全局性事务的提交和回滚。TM(Transaction Manager)
事务管理者。用于开启、提交或回滚事务。RM(Resource Manager)
资源管理器。用于分支事务上的资源管理,向 TC 注册分支事务,上报分支事务的状态,接收 TC 的命令来提交或者回滚分支事务。