RabbitMQ的使用场景
消息中间件
使用场景?解耦 异步化 削峰 分布式柔性事务
如何保证消息可达不丢失?
网络不可靠
解决方案:确认机制+补偿重发
A系统---->MQ 服务器----->B系统
1、消息发送到MQ服务器
解决方式:事务的方式(性能不佳)
异步confrim模式 客户端设置confrim监听器,获取MQ服务器的异步相应,如果消息成功发送到MQ服务器,则服务器会返回ack=true,否则为false;
springboot中配置:spring.rabbitmq.publisher-confirm=true
在代码中回调监听器 验证响应结果中的ack。
confrim机制只确保了消息到达MQ服务器。
2、MQ服务器到B系统
解决方案:return机制,能确保消息到达MQ服务器后,消息到达交换器和队列。正常不会发生,一般忽略。
消息队列做持久化,如果一旦发送宕机,未处理的消息也不会丢失。
消费端的消费确认模式开启,须手工确认消费后,才表示消息被消费处理。
存在问题:MQ服务器没有收到消费者发送的确认消息,会重复处理,所以需保证接口的幂等性。
为了避免处理不成功,造成堵塞,,引入有固定次数的重试机制。
为了避免重试仍失败,一般重复处理次数为3次,如果三次以后还是有问题,则将错误信息存入日志表中,然后人工介入处理,避免堵塞其他消息处理。
如何保证消息的幂等性,不被重复消费?
生产者端可能会重发消息 原因?
其实就是要方式消费者重复消费消息的问题。
所有MQ产品并没有提供主动解决幂等性的机制,需要由消费者自行控制。
RocketMQ: 给每个消息分配了个MessageID。这个MessageID就可以作为消费者判断幂等的依据。这种方式不太建议。
最好的方式就是自己带一个有业务标识的ID,来进行幂等判断。OrderID
统一ID分配。
延时队列
需要延迟处理的消息,交给延迟队列来完成。
如超时未支付,30分钟后取消订单,解锁库存。
方案:1、定时任务扫描 订单表 比较下单时间的差异和支付状态等,消耗cpu资源。调度。
2、消息队列的延迟队列 到时自动触发。