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. 使用flask搭建微信公众号:完成token的验证

    上一篇文章讨论了官方给的例子验证token失败的解决方法:微信公众号token验证失败 想了一下,还是决定不适用web.py这个框架.因为搜了一下他的中文文档不多,学起来可能会有点麻烦.而且看着他没有 ...

  2. 利用java程序构造mysql测试数据

    package com.baidu.mysql;import java.sql.*; public class MysqlJdbc { /** * @param args */ public stat ...

  3. Eclipse GitHub SSH2 key配置

    1. 用Eclipse自带git插件进行配置我们的用户名和密码,即是自己github注册用户. 2.windows -- perferences--General--Network Commectio ...

  4. 【2019.8.9 慈溪模拟赛 T2】摘Galo(b)(树上背包)

    树上背包 这应该是一道树上背包裸题吧. 众所周知,树上背包的朴素\(DP\)是\(O(nm^2)\)的. 但对于这种体积全为\(1\)的树上背包,我们可以通过记\(Size\)优化转移时的循环上界,做 ...

  5. MySQL实战45讲学习笔记:第四十四讲

    一.引子 这是我们专栏的最后一篇答疑文章,今天我们来说说一些好问题. 在我看来,能够帮我们扩展一个逻辑的边界的问题,就是好问题.因为通过解决这样的问题,能够加深我们对这个逻辑的理解,或者帮我们关联到另 ...

  6. snappy 安装

    1 下载snappywget https://kojipkgs.fedoraproject.org//vol/fedora_koji_archive00/packages/snappy/1.1.0/1 ...

  7. RestController 能不能通过配置关闭

    https://stackoverflow.com/questions/29958231/can-a-spring-boot-restcontroller-be-enabled-disabled-us ...

  8. 「ASCII 流程图」工具——Graph Easy

    https://juejin.im/post/5a09c43451882535c56c6bbf 「ASCII 流程图」工具——Graph Easy // 1. brew install graphvi ...

  9. Mybatis中的Mapper.xml映射文件sql查询接收多个参数

    ​ 我们都知道,在Mybatis中的Mapper.xml映射文件可以定制动态SQL,在dao层定义的接口中定义的参数传到xml文件中之后,在查询之前mybatis会对其进行动态解析,通常使用#{}接收 ...

  10. powershell与linux bash对比

    转自Github/Powershell Bash PowerShell Description ls dir, Get-ChildItem List files and folders tree di ...