分布式事务方案学习笔记(一)——可靠消息最终一致性

什么是事务

事务是由一组操作构成可靠的独立的单元。
有ACID原则:
Atomicity(原子性) -> 整个事务视为一个单元,要么一起完成,要不一起失败
Consistency(一致性) -> 事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少;比如系统总共有500元,经过多次事务之后,不同账户金额大小不一,但是这个系统总共还是只有500
Isolation(隔离性) -> 隔离执行事务。事务之间互不干扰
Durability(持久性) -> 在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚

事务可以划分为本地事务以及全局事务

本地事务

本地事务是由资源管理器(如:DBMS)本地管理的,其高效可靠,应用编程模型简单,支持严格的ACID,但是不支持分布式事务管理

全局事务

全局事务由全局事务器全局管理,因为有专门的一个服务来管理全局事务,所以是支持分布式管理的
全局事务

  • TX协议
    应用或者应用服务器与事务管理器的接口。

  • XA协议
    全局事务管理器与资源管理器的接口

两阶段提交

两阶段提交协议(Two-phase commit protocol)是XA用于在全局事务中协调多个资源的机制。
两阶段提交需要一个协调者(TM)来掌控所有参与者节点(RM)的操作结果并且指引这些节点是否需要最终提交。

CAP定理和BASE理论

  • CAP
    C:Consistency -> 一致性
    A:Availability -> 可用性
    P:Tolerance to Network Partition -> 分区容错性(允许传输同步中断)
    简单来说,就是对于分布式事务共享数据系统,最多只能同时拥有CAP的两个,无法三者兼顾,就比如数据库的主从分离
    主从分离
    主机可写可读,这个系统满足可用性,就是读取由从机读取。假如要满足一致性,就需要主机和从机一定要同步,但是这样不满足分区容错性,因为为了保证数据一致,从机必须要和主机同步;同理,如果硬要容忍分区数据不同,那这样就不保证数据一致;如果要保证分区容错和一致,那么就相当于读取也是从主机读取,相当于读写都在一个数据库,但是这样就不满足可用性

  • BASE
    BA: Basic Availability 基本业务可用性(支持分区失败)
    S: Soft state 柔性状态(状态允许有短时间不同步,异步)
    E: Eventual consistency 最终一致性(最终数据是一致的,但不是实时一致)
    原子性(A)与持久性(D)必须根本保障
    为了可用性、性能与降级服务的需要,只有降低一致性©与隔离性(I)的要求,也就是需要最终一致

基于可靠消息的最终一致性方案

  • 案例
    用户下达订单后,保存订单数据,同时保存订单凭证,这两个数据不放在同一个服务中处理,以分布式部署这两个服务,需要确定的是凭证数据和用户下的订单一致,所以这是一个分布式事务管理业务
  • 分析
    我们先按照最普通的方式来部署,看看其中的问题,如图部署服务

简单消息方案

因为①和⑤分别为一个本地服务,所以对于各自独立的它们,都可由本地事务管理,满足ACID,但是对于整个系统来说,由于网络或者服务器宕机等其他原因导致数据不一致

  1. ①出错
    业务回滚,不影响
  2. 网络或断电等原因导致②出错,此时业务已经执行,但是消息未能到达,此时凭证服务不能保存数据,数据不一致
  3. 若消息还未发给凭证服务时,MQ断电,此时再重启MQ(虽有持久化机制,但是若持久化也出错了,此时也是没有消息发送给凭证服务)
  4. ④出错,导致消息不能正常到达凭证服务,两边数据不一致
  5. 凭证服务执行失败

其实,上面导致消息不一致的根本原因就是凭证服务不能正常执行,所以我们可以加上一个定时服务,于是项目变成这样
可靠消息事务最终一致性方案1

  • 分析
    业务完成时,往业务表中插入数据,同时在同一个数据库中插入一条标记为未确认的消息数据,因为业务数据和消息数据在同一个数据库中,所以满足ACID,要么一起成功,要么一起失败;
    定时任务定时地从订单数据库中查找未确认的数据,如果找到就给MQ发送消息,凭证服务正常执行后,就将订单服务数据库中的消息数据标记为已确认或者删除这条数据,这个过程中,无论哪个环节出了问题,只要重启机器,都能够执行,使整个数据最终一致

利用这个系统,我们可以满足最终一致,但是因为是不断地查询发消息,所以很大可能凭证服务会重复执行相同的业务,所以凭证服务一定要满足幂等性
并且为了保证服务可用,可用设置累计5次都没有同步的数据则记录在日志中,不再定时重复;

但是这个模型也有缺陷,不仅与具体的业务场景绑定在一起,耦合度高,并且消息数据与业务数据同库,占用业务系统资源

将事务管理抽离解耦

可靠消息事务最终一致性方案2

  • 正常的执行的流程:
    首先预发送消息,将需要保存的数据先存进消息数据库(准备阶段),状态为未确认,执行业务,将业务数据保存进业务数据库中,而后发送结果告知消息服务系统,消息系统将数据状态修改为已确认,并将消息数据通过MQ发送到消费者服务端,服务端正常执行业务之后,便调用消息系统的接口将消息数据库的数据删除或标记为已消费

  • 消息状态确认子系统
    该服务就是检查消息数据库中的未确认的数据,如果有未确认的数据,则定时从业务数据库中查询是否有该条数据,如果有,则将消息数据库的数据标记为已确认(提交阶段),否则删除该条数据;这是生产者和消息系统之间的一致便保证了,只要业务数据库操作了这条数据,那么消息数据库业务一定会操作这条数据

  • 消息恢复子系统
    该服务检查消息数据库中是否有标记为已确认的数据,有的话则发送MQ给消费者消费,消费者要满足幂等性;
    如果消费者始终消费不了数据,则并记录到日志中,删除该条数据,消息恢复子系统是为了保证消息系统和消费者的一致性

  • 为什么要有预发送消息
    首先,预发送消息可以先判断资源是否可以操作,如果预发送消息成功,那么证明该资源是可以正常操作,这样相当于打头阵试探,避免了后面资源的浪费。并且,预发送消息是为了保证消息数据库和业务数据库保持一致,如果没有预发送消息,就没有办法保证业务数据库操作了,但是发送消息过程中出错的情况。
    如果取消预发送消息,就要像上一种模型一样将业务数据可消息数据放在同一个数据库中,利用数据库的事务来操持一致

  • 局限
    该模型也有局限,比如一次消息发送需要两次请求、我们的应用系统需要实现业务操作状态查询接口等,但是因为分布式事务的价值,这种局限也可以忽略

发布了25 篇原创文章 · 获赞 9 · 访问量 6645

猜你喜欢

转载自blog.csdn.net/qq_40233503/article/details/87827822