RabbitMQ的几个常见问题
1. 如何保证消息尽量发送成功?
问题描述: 如果没有启动消费者,重启了RabbitMQ服务,队列和消息都会丢失。
解决方案: 针对这个问题,有以下几个机制可以解决:
- 生产者确认;
- 持久化;
- 手动ACK。
生产者确认
首先,我们要确保生产者能成功地将消息发送到RabbitMQ服务器。
默认情况下生产者发送消息并不会返回任何状态信息,也就是它并不知道消息有没有正确地到达服务器。
针对这个问题,RabbitMQ提供了两种解决方案:
- 事务机制;
- 通过发送方确认机制(publisher confirm);
事务机制相关的方法主要有三个:
- channel.txSelect:用于将当前的channel设置成事务模式;
- channel.txCommit:用于提交事务;
- channel.txRollback:用于回滚事务.
用过数据库的人对事务一词肯定不陌生,在RabbitMQ中也是类似的,只有消息被RabbitMQ服务端成功接收,事务才能提交成功,否则就会触发异常,可以对异常进行捕获处理。
事务机制是阻塞形式的,一条消息发送之后会使消息端阻塞,以等待RabbitMQ的回应,才能发送下一个消息。
使用事务机制会影响RabbitMQ的性能,因此还是推荐使用发送方确认机制。
发送方确认机制是指生产者将channel设置成confirm模式,所有在该信道上发布的消息都会被指派一个唯一ID(从1开始),一旦消息被投递到RabbitMQ服务器之后,RabbitMQ就会发送一个包含了消息唯一ID的确认(Basic.Ack)给生产者,使生产者知道消息已经正确到达了目的地。
如果RabbitMQ因为内部错误导致消息丢失,就会发送一条nack(Basic.Nack)命令,生产者可以在回调方法中处理该nack命令。
发送方确认机制是异步的,一旦发布一条消息,生产者可以在等待信道返回的同时发送下一条消息,当消息确认时,可以在回调方法中处理该确认消息。因此,总体效率会更好。
相关的方法:
- channel.confirmSelect();
- channel.waitForConfirms;
- channel.addConfirmListener;
当然confirm机制也可以分为:普通confirm,批量confirm,异步confirm。
普通confirm可事务机制差不多,就是发送一条,就调用waitForConfirms确认一次;批量confirm就是发送多条后,再调用waitForConfirms确认一次;异步confirm就是注册两个回调分别处理Ack和NAck确认。
事务机制和生产者确认机制是互斥的,不能共存!
发送成功的含义是消息能到达RabbitMQ交换机,并且能有匹配的队列接收。
总体效率上,异步confirm会更好。
2. 如何进行消息持久化?
所谓持久化,就是RabbitMQ将内存中的数据(比如交换机、队列、消息等)固化到磁盘,以防止异常情况的发生时造成数据丢失。
RabbitMQ持久化分为:
- 交换机持久化;
- 队列持久化;
- 消息持久化
交换机的持久化
在创建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才能正确标识消息的状态。
消息队列的优缺点
优点:
- 解耦和复用,易扩展;
- 异步;
- 削峰;
缺点:
- 系统可用性降低,复杂度提高,mq要是挂了,影响太大;
- 存在数据一致性问题
选用RabbitMQ的理由
目前还是有很多种消息队列的,各有特点。
对于选用RabbitMQ的理由,大概因为:延时低是它最大的特点,同时单机吞吐量也很不错;也能进行分布式集群扩展;社区非常活跃。
RabbitMQ的几个常见问题的更多相关文章
- RabbitMQ 离线安装(带视频)
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 疯狂创客圈 高并 ...
- 【攻克RabbitMQ】常见问题
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/zlt995768025/article/ ...
- [Open Source] RabbitMQ 安装与使用
前言 吃多了拉就是队列,吃饱了吐就是栈 使用场景 对操作的实时性要求不高,而需要执行的任务极为耗时:(发送短信,邮件提醒,更新文章阅读计数,记录用户操作日志) 存在异构系统间的整合: 安装 下载 Er ...
- RabbitMQ可靠性投递及高可用集群
可靠性投递: 首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响.如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率. 要保证消 ...
- centos 7 rabbitmq 3.7.12 erlang 20.3源码安装
1.下载erlang 官网地址 http://www.erlang.org/download 挑选合适的版本 然后 建议20.3运行命令 wget http://erlang.org/download ...
- Spring Cloud Stream消费失败后的处理策略(四):重新入队(RabbitMQ)
应用场景 之前我们已经通过<Spring Cloud Stream消费失败后的处理策略(一):自动重试>一文介绍了Spring Cloud Stream默认的消息重试功能.本文将介绍Rab ...
- RabbitMQ 安装与使用
RabbitMQ 安装与使用 前言 吃多了拉就是队列,吃饱了吐就是栈 使用场景 对操作的实时性要求不高,而需要执行的任务极为耗时:(发送短信,邮件提醒,更新文章阅读计数,记录用户操作日志) 存在异 ...
- rabbitmq集群部署及配置
消息中间件rabbitmq,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步.本篇将以rabbitmq+HA方式进行部署. 一.原理介绍 rabbitmq是依据erlang的分 ...
- 关于 RabbitMQ 的 Dead-Letters-Queue “死信队列”
来自一个队列的消息可以被当做‘死信’,即被重新发布到另外一个“exchange”去,这样的情况有: 消息被拒绝 (basic.reject or basic.nack) 且带 requeue=fa ...
随机推荐
- 【cf1111】C. Creative Snap (dfs+dp)
传送门 简单的dfs+dp即可解决.根本不用动态开点 /* * Author: heyuhhh * Created Time: 2019/11/13 10:12:42 */ #include < ...
- 【Spring AOP】AOP核心概念(二)
1. 横切关注点 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点. 2. 切面(aspect)-- 本质上仅仅是一个类 类是对物体特征的抽象,切面就是对横切关注点的抽象. 3. 连接点 ...
- hdu6494 dp
http://acm.hdu.edu.cn/showproblem.php?pid=6494 题意 一个长n字符串(n,1e4),'A'代表A得分,'B'代表B得分,'?'代表不确定,一局比赛先得11 ...
- 小白专场-堆中的路径-python语言实现
目录 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/nickchen121/p/11407287.h ...
- 【大数据】SparkSql 连接查询中的谓词下推处理 (一)
本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/YPN85WBNcnhk8xKjTPTa2g 作者:李勇 目录: 1.SparkSql 2.连接查询和 ...
- python threading Future源码解析
1. Future内部还是用了condition这个锁 2. Cancel # future在执行时,会一直更新这个状态 def cancel(self): """Can ...
- Kubernetes Deployment(部署无状态应用)
Kubernetes Deployment(部署无状态应用) Pod与controllers的关系 • controllers:在集群上管理和运行容器的对象 • 通过label-selector相关联 ...
- WebApplicationInitializer启动分析
从Servlet 3.0 开始Tomcat已经支持注解式的配置.了解下,在注解的配置方式下,Web是怎样启动起来的. 通过注解配置一个Web应用 下面是一个通过注解实现一个简单的Web应用 publi ...
- java架构之路(mysql底层原理)Mysql之Explain使用详解
上篇博客,我们详细的说明了mysql的索引存储结构,也就是我们的B+tree的变种,是一个带有双向链表的B+tree.那么我今天来详细研究一下,怎么使用索引和怎么查看索引的使用情况. 我们先来简单的建 ...
- C# 重载 overload,重写override覆盖
重载overload 派生类和基类的方法同名,其中访问修饰符(public,private,protected,internal,protected internal),返回类型,参数类型,个数,顺序 ...