Rabbitmq解决分布式事务demo

分布式事务Demo

项目gitee地址 : https://gitee.com/ryt9806/rabbitmq.git

基于MQ的分布式事务整体设计思路

img

使用Rabbitmq消息队列进行两个服务之间的通信!

1.1、基于MQ的分布式事务消息的可靠生产问题

img

如果这个时候MQ服务器出现了异常和故障,那么消息是无法获取到回执信息。怎么解决呢?

1.2、基于MQ的分布式事务消息的可靠生产问题-定时重发

img

总结:在生产者这边,会产生一个订单,产生订单之后,将订单存入数据库中,在生者这这边增加一个消息冗余表,用来确认消息是否正确投递到交换机中。这就依赖于消息的确认机制,当消息正确投递时,会将这个信息,写入到数据库冗余表中,当发生错误时,会将这个信息写入到数据库中标注status=0,说明为消息未成功投递,服务器可能出现宕机,此时设置一个定时器,定时对消息进行重发。当正确投递时,会将冗余表中的status=1,以此来保证消息的正确投递。status=1,说明消息应答成功,消息已经被准备的移入到消息队列中。**

2.1、基于MQ的分布式事务消息的可靠消费

img

2.2、基于MQ的分布式事务消息的消息重发

img

2.3、基于MQ的分布式事务消息的死信队列消息转移 + 人工处理

img

如果死信队列报错就进行人工处理

img

总结:在消费者这边,会监听消息队列,当消息队列中有消息时,会进行消费,就可以拿到这个值。当消费过程中如果出现了异常,就会开启手动ack应答模式,会将消息打入到死信队列中,在死信队列中作出处理,倘如死信队列中也出现问题的话,就会进行人工干预,发信息或者邮件告诉用户或者同时把消息转移别的存储DB,服务可能出现了未知的错误,提醒用户,同时会把消息从死信队列中移除,说明这条消息存在未知 的错误!以此来达到消息的可靠消费的过程!当正常消费时,数据库表中status=0,说明正常的派单了。当没有正常消费时,数据库表中的status=1,说明未成功派单,消息可能存在问题。

总结:

基于MQ的分布式事务解决方案优点:

1、通用性强
2、拓展方便
3、耦合度低,方案也比较成熟

基于MQ的分布式事务解决方案缺点:

1、基于消息中间件,只适合异步场景
2、消息会延迟处理,需要业务上能够容忍!

建议

1、尽量去避免分布式事务
2、尽量将非核心业务做成异步

注意点:

该项目中,必须要注意幂等性问题,否则就会产生多条数据,解决幂等性问题的方法就是

1、防重表
数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据(比如订单表对订单号进行唯一索引,所有重复提交可能产生同一个订单号的都会被拆除。当然,订单号要按你自己的设定走,一般订单号设计会是时间戳加迭代。那么如果是这样,创建仍然不能保证幂等,具体根据业务需求来判定建立的唯一索引位置)
2、token令牌机制
分为两个阶段,获取token和使用token。每次接口请求前先获取一个token,然后再下次请求的时候在请求的header体中加上这个token,后台进行验证,如果验证通过删除token,下次请求再次判断token。如果使用上redis缓存,流程图会是这样。

img

3、先查询后判断,
首先通过查询数据库是否存在数据,如果存在证明已经请求过了,直接拒绝该请求,如果没有存在,就证明是第一次进来,直接放行。
4、支付缓冲区
把订单的支付请求都快速地接下来,一个快速接单的缓冲管道。后续使用异步任务处理管道中的数据,过滤掉重复的待支付订单。优点是同步转异步,高吞吐。不足是不能及时地返回支付结果,需要后续监听支付结果的异步返回。(一般支付都是采用这种方式)
5、悲观锁或者乐观锁
悲观锁可以保证每次for update的时候其他sql无法update数据(在数据库引擎是innodb的时候,select的条件必须是唯一索引,防止锁全表)
乐观锁,一般通过version来做乐观锁,这样既能保证执行效率,又能保证幂等。例如: UPDATE tab1 SET col1=1,version=version+1 WHERE version=#version# 不过,乐观锁存在失效的情况,就是常说的ABA问题,不过如果version版本一直是自增的就不会出现ABA的情况。(ABA可以查看这篇文章链接,关于CAS机制可以看这篇链接)
6、分布式锁
防重表可以使用分布式锁代替,比如Redis。订单发起支付请求,支付系统会去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为订单号。查询订单支付已经支付,如果没有则进行支付,支付完成后删除该订单号的Key。通过Redis做到了分布式锁(setnx()),只有这次订单订单支付请求完成,下次请求才能进来。相比去重表,将放并发做到了缓存中,较为高效。思路相同,同一时间只能完成一次支付请求。

说明:这个项目来自于学相伴的Rabbitmq教学视频 : https://www.kuangstudy.com/

猜你喜欢

转载自blog.csdn.net/qq_46611668/article/details/117707044