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

    科技2022-07-12  141

    生产端可靠性投递

    两种解决方案

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

    消息落库

    流程图

    实现流程

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

    缺点

    在高并发场景下DB操作过多

    延迟投递

    流程图

    实现流程

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

    消息堆积

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

    为什么会发生消息堆积

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

    如何避免消息堆积

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

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

    消费端幂等

    幂等性

    多次操作结果一致

    为什么要做消费端幂等

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

    主流的幂等性解决方案

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

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

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

    优点

    实现简单

    缺点

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

    解决方案

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

    利用Redis实现幂等性

    消费端接收到消息后使用setnx命令进行存储 如果存储成功了证明这条没有被处理过,消费者可以消费如果失败了则不做任何处理

    需要考虑的问题

    业务数据是否要落库,如果落库关键解决的问题是数据库和缓存如何做到原子性

    如果暂时不落库,通过定时任务同步到数据库中,如何设置定时同步的策略

    Processed: 0.009, SQL: 8