RabbitMq的一些概念,持久化、队列排他、自动删除、消息确认机制、消息ACK、消费消息的模式

Stella981
• 阅读 664

一、队列持久化的概念

队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库。

二、排他

简单理解就是在连接关闭时是否会删除队列(无论队列中有没有消息) 

三、自动删除

当队列中有消息时,无论是否排他,关闭连接都不会删除队列,此时消费者消费完消息后再断开消费者,队列会被自动删除。(这里如果有多个消费者消费同一个队列,则需要所有消费者都断开后才能自动删除) 

四、消息确认机制 Message acknowledgment

在实际应用中,可能会发生消费者收到Queue中的消息,但没有处理完成就宕机(或出现其他意外)的情况,这种情况下就可能会导致消息丢失。为了避免这种情况发生,我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理。这里不存在timeout概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开。 这里会产生另外一个问题,如果我们的开发人员在处理完业务逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug——Queue中堆积的消息会越来越多;消费者重启后会重复消费这些消息并重复执行业务逻辑…。pub message是没有ack的。

消息一旦被消费者接收,队列中的消息就会被删除。RabbitMQ怎么知道消息被接收了呢?

如果消费者领取消息后,还没执行操作就挂掉了呢?或者抛出了异常?消息消费失败,但是RabbitMQ无从得知,这样消息就丢失了!

因此,RabbitMQ有一个ACK机制。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。 

五、消息ACK的两种情况

  • 自动ACK
    • 消息一旦被接收,消费者自动发送ACK 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
  • 手动ACK
    • 消息接收后,不会发送ACK,需要手动调用 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了。

 

六、Rabbitmq消费消息的模式

rabbitmq的消费模式分为两种: 推(Push)模式和拉(Pull)模式。推模式采用Basic.Consume进行消费,而拉模式则是调用Basic.Get模式。 

  • Push模式

  • mq主动将消息推送给消费者(消费者需提供一个消费接口)

  • mq属于主动方,消费者属于一种被动消费,一旦有消息到达mq,会触发mq推送机制,将消息推送给消费者,不管消费者处于何种状态。

  • 优点:

    • 消费者代码较少:对于消费者来说,只需提供一个消费接口给mq即可;mq将接收到的消息,随即推送到指定的消费接口
    • 消息实时性比较高:对于消费者来说,消息一旦到达mq,mq会立即推送给消费者
  • 缺点:

    • 消费者属于被动方,消息量比较大时,对消费者性能要求比较高;若消费者机器资源有限,可能会导致压力过载,引发宕机的情况。
    • 对消费者可用性要求比较高:当消费者不可用时,会导致很push失败,在mq方需要考虑至少推送成功一次。
  • Pull模式 

  • 消息消费的过程:

    • 消费端采用轮询的方式,从mq服务中拉取消息进行消费
    • 消费完成通知mq删除已消费成功的消息
    • 继续拉取消息消费
  • 对于消费者来说,是主动方,可以采用线程池的方式,根据机器的性能来增加或缩小线程池的大小,控制拉取消息的速度,可以很好的控制自身的压力。

  • 优点:

    • 消费者可以根据自己的性能主动控制消息拉去的速度,控制自己的压力,不至于把自己弄跨
    • 实时性相对于push方式会低一些
    • 消费者属于主动方,控制权更大一些
  • 缺点:

    • 消费方需要实现消息拉取的代码
    • 消费速度较慢时,可能导致mq中消息积压,消息消费延迟等。

七、消费模式的最佳实践 

  • 消费者性能较好,对实时性要求比较高的,可以采用push的方式
  • 消费者性能有限,建议采用pull的方式
  • 整体上来说,主要在于消费者的性能,机器的性能如果没有问题,push和pull都是可以的
点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
RabbitMQ如何通过持久化保证消息99.99%不丢失?
1\.本篇概要要解决该问题,就要用到RabbitMQ中持久化的概念,所谓持久化,就是RabbitMQ会将内存中的数据(Exchange交换器,Queue队列,Message消息)固化到磁盘,以防异常情况发生时,数据丢失。其中,RabblitMQ的持久化分为三个部分:1.交换器(Exchange
Stella981 Stella981
3年前
MQ对比之RabbitMQ & Redis
消息队列选择:RabbitMQ&RedisRabbitMQRabbitMQ是一个由erlang开发的AMQP(AdvancedMessageQueue)的开源实现的产品,RabbitMQ是一个消息代理,从“生产者”接收消息并传递消息至“消费者”,期间可根据规则路由、缓存、持久化消息。“生产者”也即message
Stella981 Stella981
3年前
RabbitMQ存储和队列结构
本文讲解RabbitMQ的存储,主要有以下内容:1.存储原理2.队列结构3.惰性队列存储原理首先确认一个点,持久化和非持久化的消息都会落地磁盘,区别在于持久化的消息一定会写入磁盘(并且如果可以在内存中也会有一份),而非持久化的消息只有在内存吃紧的时候落地磁盘。两种类型消息的落盘都是在Rabb
Stella981 Stella981
3年前
RabbitMQ系列三 (深入消息队列)
消息持久化是RabbitMQ最为人津津乐道的特性之一,RabbitMQ能够在付出最小的性能代价的基础上实现消息的持久化,最大的奥秘就在于RabbitMQ多层消息队列的设计上。下面,本文就从MessageQueue的设计和消息在MessageQueue的生命周期两个方面全面介绍 RabbitMQ的消息队列。RabbitMQ完全实现
Stella981 Stella981
3年前
RabbitMQ小技巧
导读在使用RabbitMQ消息中间件时,因为消息的投递是异步的,默认情况下,RabbitMQ会删除那些无法路由的消息。为了能够检出消息是否顺利投递到队列,我们需要相应的处理机制。今天就来验证一下相关的验证机制。!RabbitMQ小技巧确定消息投递情况RabbitMQ小技巧确定消息投递情况(https://imgblog.csdnim
Stella981 Stella981
3年前
RabbitMQ 简介
概述RabbitMQ是基于AMQP实现的一个开源消息组件,主要用于在分布式系统中存储转发消息,由因高性能、高可用以及高扩展而出名的Erlang语言写成。特点高可靠:RabbitMQ提供了多种多样的特性让你在可靠性和性能之间做出权衡,包括持久化、发送应答、发布确认以及高可用性。高可用队列:支持跨机器集群,支持队列安全镜像
Stella981 Stella981
3年前
RabbitMQ 三种方式的TTL
TTL说明RabbitMQ支持三种方式PerQueueMessageTTL(为进入队列的每一条消息设置一个TTL)QueueTTL(队列的TTL,如果在设置的TTL时间内,没有消费者连接,没有消息发送,RabbitMQ会默认其是将要抛弃不用的,会考虑在TTL到期后删除掉该队列)PerM
Stella981 Stella981
3年前
RabbitMq学习(二)RabbitMQ的消息确认机制
一.为什么有消息确认机制在RabbitMq中,一个消息从产生到最终的消息接受,中间大致会有三个环节,首先是消息到达交换机、然后是消息通过交换机到达队列,最后消费者消费绑定的队列消息。 但是在这个过程中,如果出现网络或者系统的异常,就会导致消息不能被正常消费。如果不能正常消费消息,会造成两方面的问题。 1.1在服务端消息到
Stella981 Stella981
3年前
RabbitMQ消息持久化和消息确认机制
消息持久化消息在传输过程中,可能会出现各种异常失败甚至宕机情况,为了保证消息传输的可靠性,需要进行持久化,也就是在数据写在磁盘上。消息队列持久化包括三部分:1.Message持久化,也就是发送时消息持久化。(Message包含body,body为我们需要发送的消息具体内容,一般以json字符串发送,消费端
融云IM即时通讯 融云IM即时通讯
18小时前
融云IM干货丨IM服务消息推送,客户端版本更新后,如何确保消息不丢失?
确保客户端版本更新后消息不丢失,可以采取以下几种策略:消息持久化:确保消息被存储在可靠的存储介质中,如数据库或磁盘,这样即使客户端或服务端发生故障,消息也不会丢失。对于RabbitMQ等消息队列,需要开启持久化机制,将消息持久化到硬盘上,即使服务重启也能从