• RabbitMQ死信队列、延时队列、可靠传输、消息幂等性


    死信队列

    DLX(Dead-Letter-Exchange),死信交换器,死信邮箱。
    当消息在一个队列中变成死信(Dead Message)后,它能被重新发送到另一个交换器中,这个交换器叫DLX,绑定DLX的队列就叫做死信队列。
    造成消息死信的原因:
    1.消息被拒绝
    2.消息超时
    3.超过队列的最大长度

    延时队列

    延迟队列指的是存储对应的延迟消息,消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

    RabbitMQ本身是没有延迟队列的,要实现延迟消息,一般有两种方式:

    1.通过RabbitMQ本身队列的特性来实现,需要使用RabbitMQ的死信交换机(Exchange)和消息的存活时间TTL(Time To Live)。
    2.在RabbitMQ 3.5.7及以上的版本提供了一个插件(rabbitmq-delayed-message-exchange)来实现延迟队列功能。同时,插件依赖Erlang/OPT 18.0及以上。

    AMQP 协议以及RabbitMQ本身没有直接支持延迟队列的功能,但是可以通过TTL和DLX模拟出延迟队列的功能。

    可靠传输

    怎么保证消息的可靠性?
    消息的传输时从生产者->MQ,保存在MQ,MQ->消费者。
    这三个阶段都可能会造成消息的丢失。
    在生产者->MQ:
    我们要保证消息的可靠性可以采用事务机制和Confirm机制(这两种机制使用一种即可,不能共存)。

    1. 开启事务,Producer发送消息时开启事务,如果发生异常事务回滚,但开启事务就意味着降低性能,尤其在高并发环境下,一般不建议使用。
    2. 开启生产者confirm机制,在SpringBoot中,在application.yml配置文件中设置spring.rabbitmq.publisher-confirm-type=correlated,生产类实现RabbitTemplate.ConfirmCallback接口,重写confirm方法,不管消息是否成功发送到交换机,都会回调confirm方法,可以在这个方法里做判断处理。

    MQ本身保存消息:

    持久化、集群、普通模式、镜像模式。

    设置持久化,以保证即使Broker挂掉,服务重启后消息依然会恢复。
    但有个问题,设置了持久化的消息存入Broker之后,还需要一段时间才能存入磁盘,因为Broker并不会为每条消息都实时同步存盘,如果这个很短的时间内发生宕机、异常、重启等情况,消息也会丢失,解决办法是引入"RabbitMQ的镜像队列"(RabbitMQ集群,Master挂了Slave会换上去充当Master)

    MQ->消费者:

    baseAck机制、死信队列、消息补偿机制。

    流量削峰:
    比如在双十一的时候,在某一时刻会有大量用户并发,数据库并不能承受那么多并发量,就会有一种专门为高并发设计的MQ来承受流量,将请求发送给MQ后,数据库再根据自己的处理能力去MQ拉取消息进行处理。

    RabbitMQ的幂等性

    幂等性指:
    1.一次或多次请求,对资源均不会造成影响,比如select操作
    2.第一次请求对资源产生了影响,后面再发出多个相同的请求,与发出单个请求具有相同的效果,不能重复对资源产生影响.比如说同一个表单不能重复提交,只能提交一次。

    在RabbitMQ中有一些情况会造成非幂等性:
    1.consumer接收到消息处理完成后,在给Broker返回ack途中网络中断,Broker未收到确认信息,根据RabbitMQ的重试补偿机制,则会把这条消息再重发给其他的消费者或等网络重连后再发送给该消费者,造成了消息的重复消费
    2.在开启生产者confirm模式下,生产者已经把消息发送到Broker,但在Broker回传ack确认时网络中断,生产者也会重新发送刚才的消息,造成Broker收到了重复的消息,最终将两条重复的消息发送到消费端,造成了消息的重复消费

    保证幂等性的方法:
    1.使用全局MessageID判断消费者是否消费过
    生产者在发送消息时,为每条消息设置一个全局唯一的MessageId,消费者在拿到消息后,使用setnx命令,将messageId作为key放到Redis中,setnx(MessageId,1),返回1则说明之前没有消费过并进行消费,返回0,则说明这条消息之前被消费过,抛弃
    ( setnx命令,若给定的key不存在,执行set操作,返回1,若给定的Key已存在,不做任何操作,返回0)
    2.使用业务逻辑保证唯一

  • 相关阅读:
    阿里云个人镜像仓库日常基本使用
    WPF---Grid布局讲解
    设置 wsl 桥接模式
    vue.js毕业设计,基于vue.js前后端分离图书购物商城小程序系统 开题报告
    MySQL:读写分离-amoeba(7)
    CSS 线条流转 login
    【WLAN】如何从显示角度调试WFD问题
    基于bat脚本的前端发布流程的优化
    Java之日期相关
    systemd 强大的初始化系统和服务管理器
  • 原文地址:https://blog.csdn.net/qq_45968950/article/details/127448041