RabbitMQ

在这里插入图片描述

交换机

  • direct(默认)
    消息携带RoutingKey,将会路由到绑定该exchange并且完全匹配BindingKey的queue中
    在这里插入图片描述

  • fanout
    只要绑定该exchange的queue都将收到消息,但只有在线的consumer才能接收到消息
    在这里插入图片描述

  • topic
    在direct的基础上进行了拓展,同样是将消息路由到BindingKey和RoutingKey相匹配的队列中,不同的是,BindingKey和RoutingKey都由 “.” 进行分隔的字符串.BindingKey可以用 “*” 和 “#” 做匹配. “*” 表示匹配一个单词, “#” 匹配多个单词
    在这里插入图片描述


数据存储与处理

  • RabbitMQ存储层包含两个部分:队列索引和消息存储

    • 队列索引 (rabbit_queue_index)
      如是否已被消费者接收,是否已被消费者确认.每个 *.idx 文件中有固定的segment_entry_count条记录,默认为16384, 0.idx , 1.idx , 2.idx…
      注意 !!! mq启动时会将索引文件加入到内存中 ; 当message小于 4096B 时会直接存储到 *.idx 文件中,而且每个index从磁盘中读取消息的时候,至少要在内存中维护一段文件,所以设置 queue_index_embed_msgs_below 时要小心,一点点增大可能导致内存爆炸式增长,默认就是4096B
  • 持久化消息
    持久化消息在到达队列是写入磁盘,同时会在内存中保存一份备份,当内存紧张时,消息将会从内存中消除.存储到内存中主要目的是提高一定效率
    持久化消息存储到名为: msg_store_persistent 文件夹中
    代码中设置 deliveryMode(2)

  • 非持久化消息
    非持久化消息一般只存在内存中,当内存压力大时,将会进行刷盘操作,以缓解内存压力
    非持久化消息当在刷盘时存储到名为: msg_store_transient 文件夹中

    • 消息存储在 *.rdq 文件中,当
      在这里插入图片描述
  • 读取消息
    读取消息时,先根据消息的msg_id,通过index找到对应的存储文件,如果文件未被锁住,直接打开,从指定位置读取消息.如果文件不存在或被锁住,则发送请求由store进行处理

  • 消息删除与文件合并
    消息被确认后会被标记,当被标记的数量大于等于阈值时,将会与另一个文件合并,前提两个文件中已被标记的占比均 达到指定阈值,garbage_fraction默认为0.5,消息的顺序不会被打乱.步骤:

    • 锁定将要合并的两个文件
    • 先整理前面文件的有效数据,再整理后面文件的有效数据
    • 将后面文件的有效数据写到前面的文件中
    • 更新消息到ETS表中
    • 删除后面的文件

队列

  • RabbitMQ队列的四种状态

    alpha:  消息索引和消息内容都存在内存中,最耗内存,很少消耗CPU
    beta:   消息索引存内存,消息内容存磁盘
    gama:   消息索引在内存和磁盘中都有,消息内容存磁盘
    delta:  消息索引和内容都存磁盘,基本不消耗内存,但消耗更多的CPU和I/O
    

在这里插入图片描述

如图,当消费者消费时

  1. 首先会从Q4中获取消息,如果获取成功则返回
  2. 如果Q4为空,则尝试从Q3中获取消息,系统首先会判断Q3是否为空,如果为空则返回队列为空,即此时队列中无消息
  3. 如果Q3不为空,则取出Q3中的消息;然后在判断Q3和Delta中的长度,如果都为空,则可认为Q2,Delta,Q3,Q4全部为空,此时将Q1中的消息直接转移至Q4,下次直接从Q4中获取消息
  4. 如果Q3为空,Delta不为空,则将Delta的消息转移至Q3中,下次直接从Q3中获取消息.在将消息从Delta转移到Q3的过程中,是按照索引分段读取的,首先读取某一段,然后判断Q3Delta中消息的个数是否相等,如果相等,则可以判定此时Delta中已无消息,则直接将Q2和刚读取的消息一并放到Q3中,如果不相等,仅将此次读取到的消息转移到Q3.
  • 消息堆积

    • 增加更多的消费者,提高消费速度
    • 在消费者内开启线程池加快消息处理速度
    • 扩大队列容积,提高堆积上限
    • 从3.6.0开始,新增 Lazy Queues
      Lazy Queues特点
      接收到消息后直接存到磁盘中
      消费者要消费消息时才会从磁盘中读取并加载到内存
      支持数百万条的消息存储
  • 消息可靠性
    在这里插入图片描述

    可以从一下几点来保证消息的可靠性:

    1.客户端代码中的异常捕获,包括生产者和消费者
    2.AMQP/RabbitMQ的事务机制 ->  开销大,不推荐使用
    3.发送端确定机制(ACK) ->  可改用回调异步批处理的方式
    4.消息持久化机制 -> exchange持久化,queue持久化,消息持久化 
    5.Broker端的高可用集群
    6.消费者确认机制(ACK) -> 手动Ack / ackmode=AUTO (如果有异常重新返回到queue中)
    7.消费端限流
    8.消息幂等性 -> 如:像银行多次发送同一订单扣款信息,只执行一次 
    

    全局配置

    #最大重试次数 
    spring.rabbitmq.listener.simple.retry.max-attempts=5 
    #是否开启消费者重试
    spring.rabbitmq.listener.simple.retry.enabled=true 
    #重试间隔时间(单位毫秒) 
    spring.rabbitmq.listener.simple.retry.initial-interval=5000 
    #重试超过最大次数后,是否拒绝消息重新入列
    spring.rabbitmq.listener.simple.default-requeue-rejected=false 
    #ack模式 
    spring.rabbitmq.listener.simple.acknowledge-mode=manual
    
  • 消息可靠性保障

    1.消息生产者需要开启事务(不推荐)或者confirm机制,确保消息可以可靠的传输到RabbitMQ中
    2.消息生产者需要配合使用备份交换机来确保消息准确送达到队列中,进而能够保存下来而不被丢弃
    3.消息和队列都需要就行持久化处理.确保RabbitMQ服务器在遇到异常情况下不会造成消息丢失
    4.消费者在消费消息的同事需要将autoAck设置为false,然后通过手动确认的方式去确认已经正确的消费了消息,避免在消费端引起不必要的消息丢失.
    
  • TTL机制和死信队列
    外卖骑手接单、网约车司机接单、购物下单后15分钟内支付等场景
    当消费者外卖下单,该消息进入TTL-queue,当该队列内消息3分钟内没有被消费(即没有被骑手接单),将自动进入死信队列进行下一步处理,如:告知消费者"当前时段繁忙,正在抓紧派单,请稍后".
    以下几点会使消息进入到死信队列:

    消息长时间未被消费
    消息发送失败,queue禁止重新进入
    消息队列长队达到限制值
    

在这里插入图片描述


  • 延迟队列
    延迟队列类似闹钟提醒,消息不存在与queue中,而是直接存在于exchange中.
    RabbitMQ没有提供直接使用延迟队列的方法,需要使用 rabbitmq-delayed-message-exchange 插件来实现
    插件下载地址

其他章节 -> 跳转

end...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s_wei_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值