消息可靠性
rabbitmq向消费者投递消息后,有可能会丢失,有可能会重复投递。
比如:
- 投递过程网络故障
- 消费者收到消息后宕机
- 消费者接收到消息后处理不当导致异常
- ...
rabbitmq需要做的事:
机制
- 消费者确认机制
消费者处理成功后需要通知发
幂等性
幂等性指同一个业务,执行一次或多次对业务状态的影响是一致的
例如
- 唯一消息id
- 业务状态判断
但是数据的更新往往不是幂等的,所以需要确保幂等性
确保幂等性方法
有两种方案
唯一消息id
- 每一条消息都生成一个唯一id,与消息一起投递给消费者
- 消费者接收到消息后处理自己的业务,业务处理前将消息ID保存到数据库或redis中
数据库和redis的存取数据都是同步操作,可以避免异步程序重复消息处理。先读取,再判断,判断完之后再
处理业务
业务判断
基于业务本身的逻辑或状态来判断是否是重复的请求比如支付通知案例中,处理消息的业务逻辑是把订单状态从未支付变成己支付,因此可以在执行更新时判断
订单状态是否是未支付,如果不是则证明订单己经被处理过,无需重复处理@Override public void markOrderPaySuccess(Long orderId) { // 1.查询订单 Order old = getById(orderId); // 2.判断订单状态 if (old == null || old.getStatus() != 1) { // 订单不存在或者订单状态不是1,放弃处理 return; } // 3.尝试更新订单 Order order = new Order(); order.setId(orderId); order.setStatus(2); order.setPayTime(LocalDateTime.now()); updateById(order); }
上面两种方式的共同点都是利用了数据库的幂等性,数据库的幂等性是由于数据库本身保证,所以可以避免异步程序重复消息处理。数据库设计是同步的,所以可以避免异步程序重复消息处理。
业务补偿
万一mq通知失败该怎么办。业务补偿解决的是少发或部分发的问题。mq通知不一定发送到交易系统,那么交易系统
就必须自己主动去查询支付状态。
流程如下:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。