13.RabbitMQ常见问题(可靠性投递,幂等性等)

生产端可靠性投递

两种解决方案

  • 消息落库,对消息状态进行打标
  • 消息的延迟投递,做二次检查,回调检查

消息落库

流程图

在这里插入图片描述

实现流程
  1. 把自己的业务数据入库(BIZ DB)
  2. 发送消息前把消息入库(MSG DB)
  3. 发送消息到Broker
  4. 通过异步确认方式监听
    1. 如果成功到达交换机那么把在MSG DB中的消息状态改成成功发送(流程结束)
    2. 如果失败,可以选择重发
  5. 因为网络原因可能一直接收不到来自Broker的应答,那么MSG DB中消息的状态可能一直是未发送
  6. 使用分布式定时任务,抓取超时消息另做处理(比如重发,重发间隔与次数等问题要处理好)
  7. 如果重试发送消息多次依然无法投递成功,可以选择把消息状态变为投递失败,然后由补偿系统去抓取投递失败的消息进行其他操作
缺点
  • 在高并发场景下DB操作过多

延迟投递

流程图

在这里插入图片描述

实现流程
  1. 业务信息落库(BIZ DB)
  2. 上游服务发送业务消息
  3. 上游服务向Callback服务发送延时消息
  4. 下游服务接受到业务消息
  5. 下游服务向Callback服务发送消息
  6. Callback服务接收到下游服务传过来的消息,并进行落库(MSG DB)
  7. Callback服务接收到上游服务传过来的延时信息,根据信息检查MSG DB是否存在该消息
    1. 如果存在该消息则流程救赎
    2. 如果不存在则Callback服务通知上游服务消息没过来,进行重发

消息堆积

消息堆积是一种现象指的是大量消息积压在MQ中

为什么会发生消息堆积

  1. 生产端重发没有控制好重发次数造成消息堆积
  2. 生产者生产消息过快,消费者消费速度过慢

如何避免消息堆积

RabbitMQ默认有这个设置vm_memory_high_watermark.relative=0.4,当内存占用达到百分之40的时候它将发出内存警报并阻止所有正在发布消息的连接,一旦清除了内存警报便会恢复正常服务。磁盘也是同理,在rabbitmq.conf中或通过rabbitmqctl均可设置

如果消息已经堆积该如何处理

消费端幂等

幂等性

多次操作结果一致

为什么要做消费端幂等

因为生产端可能因为某种原因将一个消息重发好几次,如果消费端不做幂等性处理那么会让自己的业务处理N次重复数据,可能会出现数据库多条重复数据等情况。
总结下来就是消息可能会被重复消费所以需要做幂等性处理。

主流的幂等性解决方案

  • 唯一ID+指纹码(利用数据库主键去重)
  • 利用Redis的原子性

唯一ID+指纹码实现幂等性

  1. 消费端接收到消息后首先到数据库中进行查询(唯一ID+指纹码的主键)
    1. 如果存在则不作任何处理
    2. 如果不存在则插入到数据库中,然后进行消费
优点

实现简单

缺点

高并发情况下数据库写入的性能瓶颈

解决方案

根据ID进行分库分表进行算法路由

利用Redis实现幂等性

  1. 消费端接收到消息后使用setnx命令进行存储
    1. 如果存储成功了证明这条没有被处理过,消费者可以消费
    2. 如果失败了则不做任何处理
需要考虑的问题
业务数据是否要落库,如果落库关键解决的问题是数据库和缓存如何做到原子性
如果暂时不落库,通过定时任务同步到数据库中,如何设置定时同步的策略
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值