1. 如何保证消息尽量发送成功?

问题描述: 如果没有启动消费者,重启了RabbitMQ服务,队列和消息都会丢失。

解决方案: 针对这个问题,有以下几个机制可以解决:

  1. 生产者确认;
  2. 持久化;
  3. 手动ACK。

生产者确认

首先,我们要确保生产者能成功地将消息发送到RabbitMQ服务器。

默认情况下生产者发送消息并不会返回任何状态信息,也就是它并不知道消息有没有正确地到达服务器。

针对这个问题,RabbitMQ提供了两种解决方案:

  1. 事务机制;
  2. 通过发送方确认机制(publisher confirm);

事务机制相关的方法主要有三个:

  1. channel.txSelect:用于将当前的channel设置成事务模式;
  2. channel.txCommit:用于提交事务;
  3. channel.txRollback:用于回滚事务.

用过数据库的人对事务一词肯定不陌生,在RabbitMQ中也是类似的,只有消息被RabbitMQ服务端成功接收,事务才能提交成功,否则就会触发异常,可以对异常进行捕获处理。

事务机制是阻塞形式的,一条消息发送之后会使消息端阻塞,以等待RabbitMQ的回应,才能发送下一个消息。

使用事务机制会影响RabbitMQ的性能,因此还是推荐使用发送方确认机制。

发送方确认机制是指生产者将channel设置成confirm模式,所有在该信道上发布的消息都会被指派一个唯一ID(从1开始),一旦消息被投递到RabbitMQ服务器之后,RabbitMQ就会发送一个包含了消息唯一ID的确认(Basic.Ack)给生产者,使生产者知道消息已经正确到达了目的地。

如果RabbitMQ因为内部错误导致消息丢失,就会发送一条nack(Basic.Nack)命令,生产者可以在回调方法中处理该nack命令。

发送方确认机制是异步的,一旦发布一条消息,生产者可以在等待信道返回的同时发送下一条消息,当消息确认时,可以在回调方法中处理该确认消息。因此,总体效率会更好。

相关的方法:

  1. channel.confirmSelect();
  2. channel.waitForConfirms;
  3. channel.addConfirmListener;

当然confirm机制也可以分为:普通confirm,批量confirm,异步confirm。

普通confirm可事务机制差不多,就是发送一条,就调用waitForConfirms确认一次;批量confirm就是发送多条后,再调用waitForConfirms确认一次;异步confirm就是注册两个回调分别处理Ack和NAck确认。

事务机制和生产者确认机制是互斥的,不能共存!

发送成功的含义是消息能到达RabbitMQ交换机,并且能有匹配的队列接收。

总体效率上,异步confirm会更好。

2. 如何进行消息持久化?

所谓持久化,就是RabbitMQ将内存中的数据(比如交换机、队列、消息等)固化到磁盘,以防止异常情况的发生时造成数据丢失。

RabbitMQ持久化分为:

  1. 交换机持久化;
  2. 队列持久化;
  3. 消息持久化

交换机的持久化

在创建Exchange时设置durable参数参数。

channel.exchangeDeclare(EXCHANGE_NAME, "direct", true);

队列的持久化

同样也是设置设置durable参数。

持久化的队列会存盘,在服务器重启的时候可以保证不丢失相关信息。

channel.queueDeclare(QUEUE_NAME, true, false, false, null);

消息的持久化

即使交换机、队列持久化不会因为重启丢失,但是存储在队列中的消息仍然会丢失。

解决的办法就是设置消息的投递模式为2,即代表持久化(JAVA)。

理论上,可以将所有的消息都设置为持久化,但是这会严重影响RabbitMQ性能,因为写入到磁盘的速度可比写入到内存的速度慢非常多。因此,在选择是否要持久化消息时,需要在可靠性和吞吐量之间做一个权衡。

然而,将交换机、队列、消息都设置持久化之后仍然不能够保证百分百不会丢失数据。因为有些消息可能还没来得及落盘,就发生了宕机、重启等异常情况。

如何保证消息被正确消费

这部分要处理的场景是: 当消费者接收到消息后,还没处理完业务逻辑,消费者挂掉了,此时消息等同于丢失了。

为了确保消息被消费者成功消费,RabbitMQ提供了消息确认机制,主要通过显示Ack模式来实现。

默认情况下,RabbitMQ会自动把发送出去的消息置为确认,然后从内存(或磁盘)删除,但是我们在使用时可以手动设置autoAck为False的,当然具体做法各个语言都不一样。

需要注意的时,如果设置autoAck为false,也就意味者每条消息需要我们自己发送ack确认,RabbitMQ才能正确标识消息的状态。

消息队列的优缺点

优点:

  1. 解耦和复用,易扩展;
  2. 异步;
  3. 削峰;

缺点:

  1. 系统可用性降低,复杂度提高,mq要是挂了,影响太大;
  2. 存在数据一致性问题

选用RabbitMQ的理由

目前还是有很多种消息队列的,各有特点。

对于选用RabbitMQ的理由,大概因为:延时低是它最大的特点,同时单机吞吐量也很不错;也能进行分布式集群扩展;社区非常活跃。

RabbitMQ的几个常见问题的更多相关文章

  1. RabbitMQ 离线安装(带视频)

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 疯狂创客圈 高并 ...

  2. 【攻克RabbitMQ】常见问题

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/zlt995768025/article/ ...

  3. [Open Source] RabbitMQ 安装与使用

    前言 吃多了拉就是队列,吃饱了吐就是栈 使用场景 对操作的实时性要求不高,而需要执行的任务极为耗时:(发送短信,邮件提醒,更新文章阅读计数,记录用户操作日志) 存在异构系统间的整合: 安装 下载 Er ...

  4. RabbitMQ可靠性投递及高可用集群

    可靠性投递: 首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响.如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率. 要保证消 ...

  5. centos 7 rabbitmq 3.7.12 erlang 20.3源码安装

    1.下载erlang 官网地址 http://www.erlang.org/download 挑选合适的版本 然后 建议20.3运行命令 wget http://erlang.org/download ...

  6. Spring Cloud Stream消费失败后的处理策略(四):重新入队(RabbitMQ)

    应用场景 之前我们已经通过<Spring Cloud Stream消费失败后的处理策略(一):自动重试>一文介绍了Spring Cloud Stream默认的消息重试功能.本文将介绍Rab ...

  7. RabbitMQ 安装与使用

    RabbitMQ 安装与使用   前言 吃多了拉就是队列,吃饱了吐就是栈 使用场景 对操作的实时性要求不高,而需要执行的任务极为耗时:(发送短信,邮件提醒,更新文章阅读计数,记录用户操作日志) 存在异 ...

  8. rabbitmq集群部署及配置

    消息中间件rabbitmq,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步.本篇将以rabbitmq+HA方式进行部署. 一.原理介绍 rabbitmq是依据erlang的分 ...

  9. 关于 RabbitMQ 的 Dead-Letters-Queue “死信队列”

      来自一个队列的消息可以被当做‘死信’,即被重新发布到另外一个“exchange”去,这样的情况有: 消息被拒绝 (basic.reject or basic.nack) 且带 requeue=fa ...

随机推荐

  1. pushgateway

    下载pushgateway wget https://github.com/prometheus/pushgateway/releases/download/v0.9.0/pushgateway-0. ...

  2. linux学习(三)系统目录结构

    登录系统后,在当前命令窗口下输入命令: ls / 你会看到如下图所示: 树状目录结构: 以下是对这些目录的解释: /bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot: ...

  3. Centos 7 LAMP+wordpress

    一.简介        LAMP--->Linux(OS).Apache(http服务器),MySQL(有时也指MariaDB,数据库) 和PHP的第一个字母,一般用来建立web应用平台. 它是 ...

  4. vscode (1.41.0版本,1.41.1版本)node_modules部分TS声明文件@types包会导致该版本没JS语法提示

    正常提示如下: 然而我的提示没了,本以为是插件问题,把所有插件禁用不行!卸载重装vscode还是不行!!但是其他电脑的1.41.1版本,同样代码确没问题!!!简直日了*了 折腾大半天,发下问题如下: ...

  5. python进阶之命名空间与作用域

    命名空间 Namespace Namespace命名空间,命名空间是一个字典(dictionary),它的键就是变量名,它的值就是那些变量的值.命名空间的一大作用是避免名字冲突. python使用命名 ...

  6. 家用环境下部署wifidog认证服务器(java版)

    本文所讲的是基于一个java版wifidog认证服务器的开源项目,在windows环境下搭建wifidog认证服务器配合apfree固件实现用户名密码的认证. 大致步骤如下: 一,准备 1.搭建硬件及 ...

  7. phpize安装PHP扩展

    安装编译完成php源码后忘记安装一些扩展可以通过phpize来安装 拿lnmp1.6安装举例 安装完成lnmp后发现有些扩展没有 lnmp1.6的安装脚本会在lnmp1.6里生成src,里面是lnmp ...

  8. 物联网架构成长之路(42)-直播流媒体入门(RTMP篇)

    1. 安装RTMP流媒体服务器 以前其实我是利用Nginx-RTMP-module搭建过RTMP流媒体服务器,并实现了鉴权功能.参考https://www.cnblogs.com/wunaozai/p ...

  9. SpringMVC+ajax文件上传实例教程

    原文地址:https://blog.csdn.net/weixin_41092717/article/details/81080152 文件上传文件上传是项目开发中最常见的功能.为了能上传文件,必须将 ...

  10. SEO-------- 了解

    SEO(Search Engine Optimization) 译为:搜索引擎优化,是一种透过了解搜索引擎的运作规则来调整网站,以及提高目的的网站在有关搜索引擎内的排名方式. 目的:为了让用户更快的搜 ...