RabbitMQ:从入门到搞定面试官
安装
使用docker安装,注意要安装tag后缀为management的镜像(包含web管理插件),我这里使用的是rabbitmq:3.8-management
1、 拉取镜像
shell
docker pull rabbitmq:3.8-management
¨G0G
shell
docker run --name rabbitmq --hostname rabbitmq -d -p 15672:15672 -p 5672:5672 rabbitmq:3.8-management
3、 访问web管理页面
概念介绍
组件概念
- Broker:简单来说就是消息队列服务器实体。
- Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
- Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
- Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
- Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
- vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
- producer:消息生产者,就是投递消息的程序。
- consumer:消息消费者,就是接受消息的程序。
- channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
6种消息模式和4种交换机
消息模式:
- Simple Work Queue (简单工作队列):也就是常说的点对点模式,一条消息由一个消费者进行消费。(当有多个消费者时,默认使用轮训机制把消息分配给消费者)。
- Work Queues (工作队列):也叫公平队列,能者多劳的消息队列模型。队列必须接收到来自消费者的手动ack才可以继续往消费者发送消息。
- Publish/Subscribe (发布订阅模式):一条消息被多个消费者消费。
- Routing(路由模式):有选择的接收消息。
- Topics (主题模式):通过一定的规则来选择性的接收消息
- RPC 模式:发布者发布消息,并且通过 RPC 方式等待结果。目前这个应该场景少,而且代码也较为复杂,本章不做细讲。
交换机类型:
- direct(直连交换机):将队列绑定到交换机,消息的 routeKey 需要与队列绑定的 routeKey 相同。
- fanout (扇形交换机):不处理 routeKey ,直接把消息转发到与其绑定的所有队列中。
- topic(主题交换机):根据一定的规则,根据 routeKey 把消息转发到符合规则的队列中,其中#用于匹配符合一个或者多个词(范围更广), * 用于匹配一个词。
- headers (头部交换机):根据消息的 headers 转发消息而不是根据 routeKey 来转发消息, 其中 header 是一个 Map,也就意味着不仅可以匹配字符串类型,也可以匹配其他类型数据。规则可以分为所有键值对匹配或者单一键值对匹配。
消息模式和交换机的对应关系如下:

消费模式
消费模式分为推模式(Basic Consume)和拉模式(channel basicGet)
代码demo
了解完上述概念后,还是要用代码实践一下,以加深自己的理解。幸运的是rabbitmq官方提供了完整的代码demo,并且包含多种语言版本。
所以可以直接下载官方示例学习:
https://github.com/rabbitmq/rabbitmq-tutorials
比如下面是python代码中的hello world例子

进阶
备份交换器
生产者在发送消息的时候如果不设置 mandatory 参数 那么消息在未被路由的情况下将会丢失,如果设置了 mandatory 参数,那么需要添加 ReturnListener 的编程逻辑,生产者的代码将变得复杂。如果既不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备份交换器,这样可以将未被路由的消息存储在 RabbitMQ 中,再在需要的时候去处理这些消息。
消息过期时间
目前有两种方式设置消息的过期时间,一是通过队列属性设置,二是通过消息单独设置。如果两种方式同时使用,以最小值为准。
队列过期时间
通过 channel queueDeclare 方法中的 expires 参数可以控制队列被自动删除前处于未使用状态的时间。未使用的意思是队列上没有任何的消费者,队列也没有被重新声明,并
且在过期时间段内也未调用过Basic Get命令。
死信队列(DLX)
DLX ,全称为 Dead-Letter-Exchange ,可以称之为死信交换器。当消息在一个队列中变成死信 (dead message) 之后,它能被重新被发送到另一个交换器中,这个交换器就是 DLX ,绑定 DLX 的队列就称之为死信队列。
消息变成死信一般由于以下几种情况:
- 消息被拒绝
- 消息过期
- 队列达到最大长度(最大长度默认是多大?怎么设置?)
DLX 是一个正常的交换器,和一般的交换器没有区别,它能在任何的队列上被指定际上就是设置某个队列的属性。当这个队列中存在死信时 RabbitMQ 就会自动地将这个消息新发布到设置的 DLX ,进而被路由到另一个队列,即死信队列。可以监听这个队列中的消息、以进行相应的处理。
延时队列
在rabbitmq中可通过过期时间(TTL)和死信队列(DLX)实现延时队列
优先级队列
可设置队列支持的最大优先级,然后发送消息时设置消息的优先级。但是要注意这种情况只在消费者能力小于生产者,有消息堆积时有效。
持久化
RabbitMQ的持久化分为3个部分:交换器的持久化、队列的持久化和消息的持久化。但是如果将所有消息持久化,将会严重影响rabbitmq的性能。
即使将交换器、队列和消息都设置了持久化,也不能保证消息100%不丢失。
- 从消费者端,防止消费者收到消息还没来得及处理就宕机的情况,需要将autoAck设置为false
- 从生产者断,防止发送到rabbitmq后还没来的及落盘rabbitmq就宕机的情况,可以在生产者端引入事务机制或者发送方确认机制来保证消息己经正确地发送并存储RabbitMQ 中(前提还要保证在调用 channel.basicPublish 方法的时候交换器能够将消息正确路由到相应的队列之中)或者引入镜像队列来保证高可用
消息的有序性
很多资料上说rabbitmq可以保证消息的有序,其实是不严谨的。在不使用任何 RabbitM 高级特性 ,也没有消息丢失、网络故障之类异常的情况发生,并且只有一个消费者的情况下,最好也只有一个生产者的情况下可以保证消息的顺序性。如果有多个生产者同时发送消息,无法确定消息到达 Broker 的前后顺序,也就无法验证消息的顺序性。
如果要保证消息的顺序性,需要业务方使用 RabbitMQ 之后做进一步的处理,比如在消息体内添加全局有序标识(类似SequenceID) 来实现。
惰性队列
RabbitMQ 3.6.0 版本开始引入了惰性队列 lazy Queue 的概念。惰性队列会尽可能地将消息存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中,它的一个重要的设计目标是能够支持更长的队列即支持更多的消息存储。当消费者由于各种各样的原因(比如消费者下线、宕机或者由于维护而关闭等〉致使长时间内不能消费消息而造成堆积时惰性队列就很有必要了。
面试资料和电子书
上面进阶的内容可能只是零散的知识点,如果想比较成体系的深入了解的话,还是建议读本关于rabbitmq的书,个人比较推荐《RabbitMQ实战指南》(电子书看文末)。
看完后如果还想查漏补缺,或者应对面试,可以看一下网上的知识点总结或者最新的面试题汇总。(我自己搜集汇总了一下,避免重复浪费时间,大家可以看文末获取)

学习的最好方法就是实践,建议大家像上面写的那样在自己机器上安装学习一下,不要只停留在纸面上。
最后因为电子书和面试题都是PDF,所以我都上传到了网盘,大家可以关注我回复:rabbitmq,获取电子书和最新面试题汇总和一些优化实验报告。

RabbitMQ:从入门到搞定面试官的更多相关文章
- 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?
大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...
- 搞定面试官 - 你可以介绍一下在 MySQL 中,哪些情况下 索引会失效嘛?
大家好,我是程序员啊粥,前边给大家分享了 *MySQL InnoDB 索引模型 在 MySQL InnoDB 中,为什么 delete 删除数据之后表数据文件大小没有变 如何计算一个索引的长度 如何查 ...
- 金三银四,2018最新iOS面试题,由它可以搞定面试官?
序言 这些资料,你一定会用到!我相信很多人都在说,iOS行业不好了,iOS现在行情越来越难了,失业的人比找工作的人还要多.失业即相当于转行,跳槽即相当于降低自己的身价.那么做iOS开发的你,你是否在时 ...
- 【搞定面试官】try中有return,finally还会执行吗?
本篇文章我们主要探讨 一下如果try {}语句中有return,这种情况下finally语句还会执行吗?其实JVM规范是对这种情况有特殊规定的,那我就先上代码吧! public class Final ...
- 【搞定面试官】- Synchronized如何实现同步?锁优化?(1)
前言 说起Java面试中最高频的知识点非多线程莫属.每每提起多线程都绕不过一个Java关键字--synchronized.我们都知道该关键字可以保证在同一时刻,只有一个线程可以执行某个方法或者某个代码 ...
- 搞定面试官:咱们从头到尾再说一次 Java 垃圾回收
接着前几天的两篇文章,继续解析JVM面试问题,送给年后想要跳槽的小伙伴 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题..... 万万没想到,JVM内存区域的面试题也可以问 ...
- 【搞定面试官】谈谈你对JDK中Executor的理解?
## 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1.5 提供了自己的多线程框架 ...
- 【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?
前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...
- 搞定面试官 - 可以介绍一下在 MySQL 中你平时是怎么使用 COUNT() 的嘛?
大家好,我是程序员啊粥. 相信在大家的工作中,有很多的功能都需要用到 count(*) 来统计表中的数据行数.同时,对于一些大数据的表,用 count 都是瑟瑟发抖,往往会结合缓存等进行处理. 那么, ...
随机推荐
- Linux - centos7.X 安裝 Python 3.7
说明 全部操作都在 root 用户下执行 安装编译相关工具 yum -y groupinstall "Development tools" yum -y install zlib- ...
- C# Dapper基本三层架构使用 (三、DAL)
数据访问层(DAL),主要是存放对数据类的访问,即对数据库的添加.删除.修改.更新等基本操作 首先需要在UI层App.Config配置文件中增加连接字符串,如下所示 <connectionStr ...
- outerHTML和outerText的赋值是异步的
用JavaScript操作DOM时,经常有生成复杂HTML结构的需求.此时,通常不是用标准DOM接口(如createElement().setAttribute().append()等)来语句式地生成 ...
- 缓存一致性?get💡
大家好,我是老三,今天又是被算法致郁的一天,写篇文章缓一缓. 这篇文章,我们来看看缓存一致性问题. 缓存一致性 我接下来会巴巴说一堆缓存一致性,但是-- 作为一名暴躁老哥,我先把结论撂这了! 缓存和数 ...
- Java-枚举(Enum)
1.枚举概述 枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常熟.当一个变量有几种固定可能的取值时,就可以将其定义为枚举类型. 1.1 声明枚举 Java中枚举是一个特殊的类,使用enum关 ...
- Java基础系列(7)- 标识符和关键字
关键字 标识符 Java所有的组成部分都需要名字.类名.变量名.方法名都称为标识符 首字母以字母(A-Z或者a-z),美元符号($),或者下划线(_)开头 首字母之后可以用字母.美元符号.下划线.数字 ...
- Nginx系列(3)- 负载均衡
负载均衡 Nginx提供的负载均衡策略有两种: 内置策略为轮询.加权轮询.ip hash 扩展策略,就天马行空了,只有你想不到的没有它做不到的 轮询 加权轮询(根据权重来) iphash对客户端请求 ...
- python风格对象
对象表示形式 python提供了两种获取对象字符串表示形式的标准方式 repr() //便于开发者理解的方式返回对象的字符串表示形式(一般来说满足obj==eval(repr(obj) ...
- P7294-[USACO21JAN]Minimum Cost Paths P【单调栈】
正题 题目链接:https://www.luogu.com.cn/problem/P7294 题目大意 \(n\times m\)的网格,当你在\((x,y)\)时你有两种选择 花费\(x^2\)的代 ...
- P4590-[TJOI2018]游园会【dp套dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...