RabbitMQ

基础概念

  • mq是消息队列,类似于数据结构中的query,先进先出。一般用来解决应用解耦,异步消息,流量削峰
  • 流量肖峰:比如订单系统只能承受同时1w人访问,那么超过一万服务器就有可能宕机,为了防止服务宕机,让用户访问服务器之前先访问MQ,超过承受值使后面的用户进入等待状态。虽然等待时间会比较久,但总比服务宕机要好得多
  • 应用解耦:一个主业务模块需要多个其他模块共同完成,如果一一调用,若其中一个服务故障,有可能导致主业务失败。使用MQ后只需要主业务完成后发一条信息,其他模块便会按需执行,从而不影响主业务
  • 消息异步:主业务调用其他业务,若等待时间较长,其他业务可以响应给MQ,异步执行,主业务不用等待
  • 生产者:产生数据发送消息的程序是生产者
  • 交换机:接收生产者的消息,推送到队列当中,可以指定队列、多个队列或者丢弃
  • 队列:Rabbit内部使用的一个数据结构,用来存储生产者发送的消息,消费者从队列中接收数据
  • 消费者:接收消息。一个应用程序既可以是消费者又可以是生产者
  • web默认页面:http://localhost:15672

工作队列

  • 工作队列:将任务发给多个消费者。
    主要防止资源密集型任务堆积。消息分发使用轮询的方式
  • 消息应答
    • 自动应答:消息发出就应答完成,消息丢失概率很大,只适用于消费者可以高效消费消息时使用
    • 手动应答:可以批量应答
  • 消息自动重新入队:即使消费者处理过程中断未做出响应,MQ将消息重新排队,发给别的消费者处理,消费者死亡不会导致消息丢失
  • 消息持久化:MessageProperties.PERSISTENT_TEXT_PLAIN

消息发布方式

  • 不公平分发:channel.basicQos(1); //采用能者多劳的方式分发任务
  • 预取值分发:channel.basicQos(2);

发布确认

生产者发送消息到队列中,队列将消息储存到硬盘上才能将消息持久化,如果刚发出去没来得及存就宕机会导致发布的消息丢失,所以需要做发布确认,就是队列将消息保存在磁盘上之后告诉生产者确定保存在磁盘上。

生产者将信道设置成 confirm 模式,一旦信道进入 confirm 模式,所有在该信道上面发布的消息都将会被指派一个唯一的 ID

一旦消息被投递到所有匹配的队列之后,broker就会发送一个确认给生产者(包含消息的唯一 ID),这就使得生产者知道消息已经正确到达目的队列

如果消息和队列是可持久化的,那么确认消息会在将消息写入磁盘之后发出,broker 回传给生产者的确认消息中 delivery-tag 域包含了确认消息的序列号,此外 broker 也可以设置basic.ack 的 multiple 域,表示到这个序列号之前的所有消息都已经得到了处理

策略
  • 单个发布确认:串行发布
  • 批量发布确认:
  • 异步发布确认:利用回调函数来传递消息,可靠性和效率是最高的
    • 异步未确认消息:
      • 将未确认消息放到一个基于内存的能被发布线程访问的队列,比如说ConcurrentLinkedQueue这个队列在confirm callbacks与发布线程之间进行消息传递
      • 先在发布的消息中记录要发消息的总和,然后在确认发布中删除,打印未确认的有哪些
      • ConcurrentSkipListMap:
        • 线程安全有序的hash 适用于高并发情况
        • 1.轻松将序列号和消息关联
        • 2.批量删除条目, 只需要给到序列号

发布订阅模式

    概念
        生产者发布的消息不会直接发送到队列,只能先发送到交换机,交换机的工作内容非常简单,一方面接收生产者信息,然后推入到队列中去,交换机必须确切的知道如何处理消息,是应该把这些消息放到特定队列还是说把他们放到许多队列,还是丢弃,这由交换机的类型来决定
        各种队列
            默认队列
            临时队列
                channel.queueDeclare().getQueue();
                创建队列的名称为随机,
            绑定
                交换机和队列进行绑定,并且根据RoutingKey关联
    发布订阅模式
        消费者
            声明交换机
            声明队列
            绑定
            接收消息
            处理消息
        生产者
            声明交换机
            发出消息
    路由模式/直接
        生产者
            指定routingKey发出消息
        消费者
            声明交换机
            声明队列
            绑定并声明routingKey
            接收消息
            处理消息
    主题模式
        *代表一个key,#代表0或多个单词
        死信队列
            生产者将消息投递到交换机或者直接到队列中,消费者取出消息消费,无法被消费的消息被成为死信
            死信来源
                消息存活时间过期
                    AMQP.BasicProperties build = new AMQP.BasicProperties().builder().expiration("10000").build();
                队列达到了最大长度
                    x-max-length
                    主队列死亡,超出最大长度的为死信
                消息被拒绝
                    开启手动应答
                    channel.basicReject(message.getEnvelope().getDeliveryTag(),false);//false不放回队列
            		map.put("x-dead-letter-exchange",DEAD_EX);
					map.put("x-dead-letter-routing-key","YD");
					map.put("x-message-ttl",10000);
        延迟队列
            队列内部是有序的,延迟队列是用来存放需要在指定时间被处理的消息的队列
            延迟消息需要排序,若第二条消息的延迟低于第一条,那么第二条跟第一条一起发出
发布确认高级
    概念
        防止交换机和队列无法正常工作导致消息丢失
    开启配置
        spring-rabbit-publisher-confirm-type: correlated
        spring-rabbit-publisher-returns: true
    实现接口
        RabbitTemplate.ConfirmCallback
    注入方法
        @PostConstruct
    备份交换机
        发布确认交换机配置
            map.put("alternate-exchange",BACKUP_EXCHANGE_NAME);
        备份交换机和消息回退同时开启,备份交换机优先级更高
其他
    幂等性
        可以使用redis生成全局ID,消费前判断消息是否被消费过
    优先级队列
        map.put("x-max-priority",10);
        AMQP.BasicProperties build = new AMQP.BasicProperties.Builder().priority(5).build();
        0-255越大越优先
    惰性队列
        正常消息保存在内存中,惰性队列保存在硬盘上。惰性队列的内存开销非常小,只存有一些磁盘的索引,但是效率非常低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值