1. CAP定理


  1. 参考文档
    1. https://class.imooc.com/lesson/1230#mid=30731
    2. https://class.imooc.com/lesson/1237#mid=29631

1.1 概念说明

  1. consistent:一致性,指数据的一致性。
  2. availability:可用性
  3. partition tolerance:分区容错性,发生故障的时候依然能够对外提供服务
  4. 分布式系统中,三个要素最多选择两个,且partition tolerance一定会被选中

    1.2 一致性类型

  5. 强一致性:修改数据,后续的每个请求都能且必须拿到修改后的数据

  6. 弱一致性:修改数据,后面的请求一部分能拿到,一部分拿不到,最后进化为—>最终一致性
  7. 最终一致性:在可接受的时间里面,最终所有的请求都能拿到修改后的数据

    1.3 CA、CP、AP分析

  8. CA:满足一致性,可用性,一般来说都是以单体存在的集群架构,扩展性不高,且都是关系型数据库

  9. CP:满足一致性,分区容错性的系统一般来说,性能不会很高;例如dubbo
  10. AP:例如SpringCloud

    2. ACID原理

    2.1 事务的四大特性

  11. atomicity:原子性,事务中的操作要么做,要么都不做

  12. consistency:一致性,系统必须处在强一致的状态下
  13. isolation:隔离性,一个事务的执行不能被其它事务所干扰
  14. durability:持久性,一个已提交的事务对数据库中数据的改变是永久性的

    2.2 结论

  15. 它强调的是一致性,要么全成功,要么全不成功,所有用户看到的数据都是一致的

  16. 传统的数据库都有ACID的特性,它在CAP理论中保证的是CA

    3. BASE原理

    3.1 特性介绍

  17. basically available

    1. 基本可用,指在分布式系统出现故障的时候,允许损失部分可用性,保证核心链路可用
    2. 服务降级就是一种基本可用的体现
  18. soft state
    1. 软状态,指允许系统出现中间状态,而中间状态不会影响整个系统可用性
    2. 分布式存储中一般一份数据存在多个副本,允许多个副本数据同步的延时就是软状态的体现
  19. eventual consistency

    1. 最终一致性,指系统中所有的数据副本经过一定的时间,最终能够达到一致的状态

      4. 分布式事务

  20. 在分布式事务的解决方案中,它都是依赖于ACIDBASE模型实现的

  21. 基于ACID模型
    1. 基于XA的两阶段提交
    2. 事务补偿机制(TCC)
  22. 基于BASE模型
    1. 而基于本地消息表和基于MQ的最终一致性方案都是通过BASE原理实现的
  23. 实际工作更推荐消息队列解决

    5. 基于XA协议的两阶段提交

    5.1 原理解析

  24. 它是由X/Open组织提出的分布式事务的规范

  25. 由于一个事务管理器(TM)和多个资源管理器(RM)组成
  26. 事务管理器就是程序中的数据源,资源管理器是具体的数据库
  27. 提交分为两个阶段:准备阶段(prepare)提交阶段(commit)
  28. 所有的RM先准备,然后通知TM,然后由TM统一的发出commit指令
  29. image.png
  30. image.png

    5.2 使用及注意事项

  31. 它保证了数据的强一致性

  32. 提交阶段出现问题,事务出现不一致,需要人工干预,例如写异常处理…
  33. 效率低下,性能与本地事务至少相差十倍
  34. 支持
    1. MySQL 5.7以上均支持XA协议
    2. MySQL Connector 5.0以上均支持XA协议
  35. 它只能解决单个服务使用多个数据源的问题
    1. 例如:积分在用户库,订单在订单库,用户使用积分购买商品的流程发生异常
  36. 无法解决多个微服务之间的事务问题

    1. image.png

      5.3 XA分布式事务的实现

      5.3.1 基于Atomikos的实现

      Java系统中,数据源基本上采用的Atomikos数据源做分布式事务,它就是充当TM的角色,具体的实现查看视频即可:https://class.imooc.com/lesson/1237#mid=29618

      5.3.2 MtCat配置分布式事务

  37. 不过滤 = 支持

  38. server.xml配置:<property name="handleDistributedTransactions">0</property>
  39. 配置属性说明
    1. 0:不过滤分布式事务
    2. 1:过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤)
    3. 2:不过滤分布式事务,但是记录分布式事务日志 ```sql — 首先关闭事务的自动提交 set @@autocommit = 0;

— 开启XA的事务 set xa = on;

— username字段只有两位,插入一个长的字符串,模拟异常 insert into user (id,username) values(1,”奇数”),(2,”偶数ssss”);

— 提交事务 commit;

— 项目连接MyCat之后,只要开启分布式事务,然后出现异常它会自动支持的 ```

5.3.3 Sharding-Jdbc配置分布式事务

6. 事务补偿机制

  1. 简称TCC
  2. 针对每一个操作,都要注册一个与其对应的补偿(撤销)操作
  3. 在执行失败的时候,再调用补偿操作,撤销之前的操作
  4. 说白了就是出错了,调用补偿接口
  5. 补偿接口也会出现失败?
    1. 可以提供重试的次数,只要保持这个接口的幂等性即可
    2. 重试依然失败,则保存到数据库,人工补偿
    3. 也可以借助第三方工具,比如:SEATA。它把所有回滚的sql都记录在数据库中,并且标识是否执行成功。这样即使失败了,也可以再执行
  6. 优点:逻辑清晰,流程简单
  7. 缺点:数据一致性比XA还差,可能出错的点比较多
  8. TCC属于应用层的一种补偿方式,程序员需要写大量的代码

    1. 半仙老师的直播课,有时间回顾即可
    2. image.png

      7. 基于本地消息表+定时任务的最终一致方案

      7.1 原理解析

  9. 采用BASE原理,保证事务最终一致性

  10. 在一致性方面,允许一段时间内不一致,但是最终会一致
  11. 将本事务外的操作,记录在消息表中
  12. 个人理解的整体流程

    1. 就是下游记录操作,上游提供回调通知接口
    2. 定时任务扫描,记录状态调用上游接口修改状态
    3. 规定重试次数,支持人工操作,注意重试接口的幂等性问题
    4. 整体很像Rabbit MQ基础组件

      7.2 实现流程

      7.2.1 业务背景及流程

  13. 模拟下单扣减金额的业务流程

  14. 下单之后产生一笔订单,当前订单的状态是未支付
  15. 调用支付服务的支付接口,客户支付50元,在支付服务上生成一条支付记录和消息记录
  16. 并且消息记录的状态是1、重试次数是0,代表还没有回调订单服务提供的修改订单状态的接口
  17. 定时任务不断轮询消息表,调用上游订单服务的接口,修改订单状态
    1. 调用成功,返回给支付服务一个成功标识,消息记录表把状态修改为2,代表回调成功
    2. 调用失败,重试这个消息,
      1. 成功:走a的流程,但是重试次数+1
      2. 失败:一直到最大重试次数,依然没有成功,状态修改为3,后续成功介入

        7.2.2 代码实现

        课程是连接两个数据库,自己测试最好是搭建两个微服务即可

        8. 基于MQ的最终一致方案

        9. 幂等性

        image.png
        并发情况个人理解,除非黑客攻击,不然一个人的点击没法引起并发,对应系统的并发并不会影响,因为大家操作的不是同一条消息

image.png
image.png

可以使用原生的redis分布式锁,因为它是非阻塞的,直接返回错误