分布式事务 -- MQ实现

场景:

订单系统和运单系统

点外卖,用户下单 ,下单后触发运单系统生成运单

分布式系统:一个请求,由多个系统协同处理完成

微服务只是架构分布式系统的一种方法

订单系统,调用运单系统,

程序分析:

使用RPC远程过程调用,实现服务直接交互

分布式事务涉及:CAP |BASE

理论是实践之后的总结

尽管加了事务@Transaction,可是依然会发生如下异常:

订单失败,而运单依然有数据产生

原因是:运单系统内部处理的时候模拟耗时3秒,超过了请求时设置的超时时间2秒,所有调用方认为没有结果返回就认为异常了,

其实运单服务还正常运行中。所以运单系统有了数据,而订单系统因为回滚,所以没有数据


需要找一个中间载体来规避上述这些问题:

这个载体需要具备的特性:

 

载体选择:自研、MQ、Redis、zookeeper、数据库

  1. 自研:seata |lcn|TCC各种框架研发
  2. Redis、zookeeper[可靠,redis、zookeeper主动内存型,数据不保证丢失]
  3. 数据库--数据库集群高可用
  4. MQ--本质:和redis 、zookeeper本质一样, 数据存取

特点:没有要求结构化的数据

还没有开箱即用的开源方案。针对自身的业务场景,进行定制化的解决

演示一种MQ的解决方案:

消息可发发送

可能的异常

  • MQ发送失败
  1. mq调用成功,但是订单事务提交失败   --解决办法:mq操作和订单事务分离,把事务注解加到saveOrder方法上去,这样就保证了,order一定插入到数据库,才会去执行发送消息队列,如果order数据插入异常,则直接回滚,不去执行发送消息队列,保证了插入order数据和消息队列同时发生,或者同时失败
  2. mq调用网络不通【重发----】

    实现方式:新建一张本地消息tb_distribute_message表。【里面需要有一个业务消息的唯一id,保证幂等】在插入订单的同时,插入一条本地消息,并标记为未消费,标记为已消费的节点是,mq的ack机制,发送回执的时候

  3. Mq有ack机制[需要自己去开启]发送以后有回执,就消息会发送到一个名字叫做orderQueue的队列中去,会触发一个方式confirimCallback可以修改状态,

  4. 定时任务schedule可以去检查这张表,消息是否发送,这样就可以重发了
  5. 修改消息表的状态为已发送
  6. mq收到请求,突然断开网络,实际MQ已经存储消息【如何知晓MQ是否收到消息】
  • MQ本身可靠性如何保障【自带高可靠方案,副本】

消息可靠消费

1.运单系统配置rabbitMQ

从之前创建的队列orderQueue中取值

1.先创建队列

这里涉及幂等(重复),

产生的场景:mq ack之后,返回消息给订单系统,,此时订单系统挂掉了,没有收到消息,本地消息表中消息状态仍然是未发送,这样定时任务去扫消息表的时候,发现未发送,于是又触发一次发送操作

运单表主键直接就是order_id

要有一个业务标记,能够识别是否为同一条数据。记录已经处理的数据(比如用redissetNx)

 

 

还有问题,就是运单系统消费消息,处理中途,运单系统挂掉了。也就是没有可靠消费==消费中途出了问题

可是ack是自动发送的,并不考虑消费的结果(是否可靠消费)。此时消息也被消费了。也不能再次触发了

所以此时应该修改自动ack为手动(代码控制),并做后续的业务处理

看上面的代码messageConsumer中处理

requeue = true标识重发

requeue = false标识不重发

 

两个系统之间交互,用MQ消息队列

用RabbitMQ,因为和spring同一个母公司,集成非常好

有Message Queue| 有topic/queue的概念 多个queue


 

mq一般都是自动ack,容易出问题,

需要改为手动ack.当消息正常处理后,告诉mq删除

channel.basicAck(false);

//如果消费者突然断电或者进程kill,MQ检测到连接断开,会向其他消费者重复

//出现可控的异常,告诉MQ,你帮我重发--根据具体的业务系统设计

//出现未知异常,运维日志监控,预警机制

channel.asicNack(tag,false,"requeue":false);//丢到了垃圾堆,回收站可以找到

 

CAP=就是三选二

多系统之间肯定是通过网络来交互,网络是不可靠的

分区容错:多个系统之间不能交互,仍然要对外提供服务

一致性:订单系统和运单系统数据一致

可用性:

是对其中某一个部分做出一些牺牲,不是完全不能兼顾,要做一些取舍

 


对于大数据量并发

生产者可以分布式部署

消费者分组group概念

所有不用担心数据量大的问题

 

 

基于分区

Base理论:就是对CAP理论的扩展【基本可用】通过修改状态来实现回滚

 

SAGA理论,每一个模块都很好的工作,保证

Seata开源分布式解决方案对之前这些操作封装

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章