RabbitMQ

本文探讨了分布式环境下的事务处理,包括Spring的@Transactional注解的不同传播行为,以及RabbitMQ消息队列在确保消息不被重复消费、保证消息一致性和可靠传输的方法。提到了幂等性设计在处理消息重复时的重要性,并介绍了订单与库存系统中的事务挑战,如远程服务假失败和分布式事务的CAP原理。同时,提出了利用日志表记录消息状态和定期重试策略来防止消息丢失和重复。

@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
YAML文件嵌套Map的key为List
SeviceA中的A方法自动创建一个事务,B方法被调用用后发现已经在事务中就不会新创建事务,B方法回滚,A方法也会回滚。
在B方法commit后如果A方法回滚了B方法同样还是会回滚

//登录后的键
String cartKey = CART_PREFIX + userInfoTo.getUserId();
//临时购物车的键
String temptCartKey = CART_PREFIX + userInfoTo.getUserKey();
根据临时购物车的键来获取临时购物车的数据 遍历添加到登录后的购物车 最后清除临时购物车的数据就可以了

判断是否登录
在浏览器中有一个cookie,在cookie中创建了一个临时用户标识(过期时间),浏览器进行保存,
如果是第一次使用购物车,添加购物车我们就创建一个临时购物车 用户每次访问都会带着cookie ,
如果用户登录(有session)就进行数据同步,清空临时购物车

1、如何保证RabbitMQ不被重复消费?
比如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过;

2、RabbitMQ有什么优缺点?
答:优点:解耦、异步、削峰;
缺点:降低了系统的稳定性:本来系统运行好好的,现在你非要加入个消息队列进去 系统可用性会降低;
增加了系统的复杂性:加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。
因此,需要考虑的东西更多,复杂性增大。

造成消息重复的根本原因是:网络不可达。
所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。
保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,
如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。

如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过;

项目中的
订单表:订单id /用户id/订单号/时间/金额/订单状态/收货人信息
订单详情表:spuid/skuid/商品名称/数量/价格/颜色
spu:指的是一款商品 每一款商品都有一个spu 手机->苹果手机->苹果12,苹果12就是SPU
sku:是最小单元,可以根据sku来确定货物存量 例如商品的颜色

本地事务Transaction(只能操作在同一个数据库 同时成功 同时失败) 在分布式系统 只能控制自己的回滚 控制不了其他服务的回滚
远程服务假失败(库存假失败,扣库存成功了,但是网络超时,订单回滚,库存不滚)
(远程服务成功了 但是网络原因 没收到返回结果 以为失败了就会回滚订单 没有订单 但是库存却减少了)
远程服务执行完成 其他方法出现问题 导致:已经执行的远程请求,肯定不能回滚
(因为他们不在一个链接里面)
比如说在分布式里面 A调B 还会有A调C C呢又调D 只要有任何一个服务出现异常(已经成功的远程服务没办法就是通过Transaction 来进行一个整体服务的回滚)

要想回滚 除非他们几个服务不是远程服务 而且操作的需要是同一个数据库

分布式事务 :产生的最大原因就是网络原因
一号机器调二号机器,调二号之前,二号服务宕机了,这还合理
(调用二号机器成功了,返回结果的那一刻,二号机器宕机了,此时一号机器根本不知道二号机器是否成功失败了,那么就要进行回滚)

CAP(一致性/可用性/分区容错性) 只能满足两个 其中P必须满足 P(分区容错保护 也就是服务之间的网络通信)

RabbitMq 消息丢失(网络原因 消息没发出去 造成消息丢失)
给每一个消息做好日志记录(给数据库保存每一个消息的详细信息 消息的状态012 已发送/错误抵达/已经抵达 )
定期扫描数据库 将失败的消息在发送一次
日志表组成(消息内容/发送给哪个交换机/路由键/消息状态/时间等)
RabbitMq 消息重复 (网络原因)
将我们的业务设计成幂等性(只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样)
利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。
RabbitMq 定时关单
消息死了 丢给交换机 接着到队列
订单服务 一下订单就给我们的MQ发消息 根据我们的绑定关系找到对应的消息队列(不进行消费)这个队列设置过期时间
假设设置过期时间为30分钟 消息过期我们就交给交换机(不丢掉) 交换机呢在路由绑定到相应的队列 进行消费 关单

解锁库存
(1) 下单成功 30分钟未支付/用户手动取消订单 解锁库存
(2) 下单成功,库存锁定成功,但是接下来的业务调用失败 之前锁定的库存就要自动解锁 195个视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值