一、事务的保证

1、会遇到的问题

已商城下单为例
1、订单服务异常,库存锁定不运行,全部回滚,撤销操作
2、库存服务事务自治,锁定失败全部回滚,订单感受到,继续回滚
3、库存服务锁定成功了,但是网络原因返回数据途中问题?
4、库存服务锁定成功了,库存服务下面的逻辑发生故障,订单回滚了,怎么处理?

遇到的问题:

  • 远程服务假失败:
    • 远程服务其实成功了,由于网络故障等没有返回导致:订单回滚,库存却减少
  • 远程服务执行完成,下面的其他方法出现问题
    • 导致:已执行的远程请求,肯定不能回滚

      利用消息队列实现最终一致 库存服务锁定成功后发送消息队列消息(当前库存工作单),过段时间自动解锁,解锁时先检查订单的支付状态。解锁成功修改库存工作单详情项状态为已解锁。

2、CAP定理

  • 强一致性(Consistency)

    1. 在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)。例如abc三台机器,在同一个时刻的值是一样的
  • 可用性(Available)

    1. 在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
  • 分区容错性(Partition tolerance)

大多数分布式系统都分布在多个子网络。每个子网络叫做一个区(partition)。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另外一台服务器放在美国,这就是两个区,它们之间可能无法通信。

CAP原则就是说这三个要素只能同时实现两点,不可能三者兼顾,在一般的系统中,都必须保证分区容错性,所以只能在可用性和一致性中二选一,所以我们的机器大都是CP机器,要么是AP机器。

AC是不可能并存的,因为C要求三台机器一样的值,A可以容忍三台中的两台挂掉,来保证可用性
分布式系统中实现一致性的raft算法(保证CP)、paxos算法。

面临的问题
对于多数大型互联网应用场景,主机众多、部署分散,而且现在的集群规模越来越大,所以节点故障、网络故障是常态,而且要保证服务可用性达到99.99999(N个9),既保证P和A,舍弃C。

3、BASE理论

既是无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

  • 基本可用(Basically Available)什么是基本可用呢?假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言
    • 响应时间上的损失:正常情况下的搜索引擎0.5秒即返回给用户结果,而基本可用的搜索引擎可以在2秒作用返回结果。
    • 功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单。但是到了大促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。
  • 软状态(Soft State)什么是软状态呢?相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种“硬状态”。软状态指的是:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
  • 最终一致性(Eventually Consistent)上面说软状态,然后不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保持数据一致性,从而达到数据的最终一致性。这个时间期限取决于网络延时、系统负载、数据复制方案设计等等因素。实际上,不只是分布式系统使用最终一致性,关系型数据库在某个功能上,也是使用最终一致性的。比如备份,数据库的复制过程是需要时间的,这个复制过程中,业务读取到的值就是旧的。当然,最终还是达成了数据一致性。这也算是一个最终一致性的经典案例。

总结:总体来说BASE理论面向的是大型高可用、可扩展的分布式系统。与传统ACID特性相反,不同于ACID的强一致性模型,BASE提出通过牺牲强一致性来获得可用性,并允许数据段时间内的不一致,但是最终达到一致状态。同时,在实际分布式场景中,不同业务对数据的一致性要求不一样。因此在设计中,ACID和BASE理论往往又会结合使用。

4、强一致性、弱一致性、最终一致性

从客户端角度看,多进程并发访问时,更新过的数据在不同的进程如何获取的不同策略,决定了不同的一致性。对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性,如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。

二、分布式事务中的几种解决方案

1、2PC模式

2PC即两阶段提交协议(2 phase commit),是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit phase).
2是指两个阶段,P是指准备阶段,C是指提交阶段。

数据库支持的2PC,又叫XA transaciton。XA是传统分布式事务解决方案,基于数据库必须要支持2PC协议,利用数据的2PC协议来实现分布式事务。

第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)操作,并反映是否可以提交。
第二阶段:事务协调器要求每个数据库提交数据。其中,如果有任何一个数据库否决此次提交,那么所有数据库都会被要求回滚它们在此事务中的那部分信息。

  • XA协议比较简单,而且一旦商业数据库实现了xA协议,使用分布式事务的成本也比较
    低。
  • XA性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景
  • XA目前在商业数据库支持的比较理想,在 mysql数据库中支持的不太理想,mys的XA实现,没有记录 prepare阶段日志,主备切换会导致主库与备库数据不一致。
  • 许多 nosql也没有支持XA,这让XA的应用场景变得非常狭隘。
  • 也有3PC,引入了超时机制(无论协调者还是参与者,在向对方发送请求后,若长时间
    未收到回应则做出相应处理)

    2、柔性事务-TCC事务补偿型方案

    刚性事务:遵循ACID原则,强一致性 柔性事务:遵循BASE理论,最终一致性 与刚性事务不同的是,柔性事务允许在一定时间内,不同节点的数据不一致,但要求最终一致性

TCC(Try-Confirm-Cancel)的概念,最早是由 Pat Helland 于 2007 年发表的一篇名为《Life beyond Distributed Transactions:an Apostate’s Opinion》的论文提出。

TCC 是服务化的二阶段编程模型,其 Try、Confirm、Cancel 3 个方法均由业务编码实现:

  • Try 操作作为一阶段,负责资源的检查和预留。
  • Confirm 操作作为二阶段提交操作,执行真正的业务。
  • Cancel 是预留资源的取消。

TCC 事务的 Try、Confirm、Cancel 可以理解为 SQL 事务中的 Lock、Commit、Rollback。

3、柔性事务-最大努力通知型方案

按一定规律进行通知,不保证数据一定能通知成功,但会提供可查询操作接口进行核对。这种方案也会使用MQ进行实现,通知是否成功。案例,支付宝的支付成功会调。

4、柔性事务-可靠消息+最终一致性方案(异步确保型)

保证高并发的情况下,其他业务自己回滚,发消息通知。

5、SEATA

详情参考官网文档:http://seata.io/zh-cn/docs/user/quickstart.html
备注:
1、每个微服务必须创建undo_log表
2、安装事务协调器:seata-server:https://github.com/seata/seata/releases
3、整合
1、导入依赖:spring-cloud-starter-alibaba-seata seata-all-0.7.1
2、解压并启动seata服务器,注意下载的版本和maven中jar包的版本
3、修改registry.conf配置文件中的注册中心和地址,以及文件的配置
4、所有想要用到分布式事务的微服务都需要使用seata datasourceProxy代理自己的数据源
5、每个微服务都必须导入 registry.conf和file.conf
6、给分布式大事务的入口标注@GlobalTransactionl,每个远程的小事务用@Transactional

整体机制

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。