安装

使用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管理页面

http://127.0.0.1:15672/

概念介绍

组件概念

  • 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,也就意味着不仅可以匹配字符串类型,也可以匹配其他类型数据。规则可以分为所有键值对匹配或者单一键值对匹配。

消息模式和交换机的对应关系如下:


2021-10-20-11-17-31

消费模式

消费模式分为推模式(Basic Consume)和拉模式(channel basicGet)

代码demo

了解完上述概念后,还是要用代码实践一下,以加深自己的理解。幸运的是rabbitmq官方提供了完整的代码demo,并且包含多种语言版本。
所以可以直接下载官方示例学习:

https://github.com/rabbitmq/rabbitmq-tutorials

比如下面是python代码中的hello world例子


20211025142123

进阶

备份交换器

生产者在发送消息的时候如果不设置 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%不丢失。

  1. 从消费者端,防止消费者收到消息还没来得及处理就宕机的情况,需要将autoAck设置为false
  2. 从生产者断,防止发送到rabbitmq后还没来的及落盘rabbitmq就宕机的情况,可以在生产者端引入事务机制或者发送方确认机制来保证消息己经正确地发送并存储RabbitMQ 中(前提还要保证在调用 channel.basicPublish 方法的时候交换器能够将消息正确路由到相应的队列之中)或者引入镜像队列来保证高可用

消息的有序性

很多资料上说rabbitmq可以保证消息的有序,其实是不严谨的。在不使用任何 RabbitM 高级特性 ,也没有消息丢失、网络故障之类异常的情况发生,并且只有一个消费者的情况下,最好也只有一个生产者的情况下可以保证消息的顺序性。如果有多个生产者同时发送消息,无法确定消息到达 Broker 的前后顺序,也就无法验证消息的顺序性。

如果要保证消息的顺序性,需要业务方使用 RabbitMQ 之后做进一步的处理,比如在消息体内添加全局有序标识(类似SequenceID) 来实现。

惰性队列

RabbitMQ 3.6.0 版本开始引入了惰性队列 lazy Queue 的概念。惰性队列会尽可能地将消息存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中,它的一个重要的设计目标是能够支持更长的队列即支持更多的消息存储。当消费者由于各种各样的原因(比如消费者下线、宕机或者由于维护而关闭等〉致使长时间内不能消费消息而造成堆积时惰性队列就很有必要了。

面试资料和电子书

上面进阶的内容可能只是零散的知识点,如果想比较成体系的深入了解的话,还是建议读本关于rabbitmq的书,个人比较推荐《RabbitMQ实战指南》(电子书看文末)。
看完后如果还想查漏补缺,或者应对面试,可以看一下网上的知识点总结或者最新的面试题汇总。(我自己搜集汇总了一下,避免重复浪费时间,大家可以看文末获取)


20211025154244

学习的最好方法就是实践,建议大家像上面写的那样在自己机器上安装学习一下,不要只停留在纸面上。

最后因为电子书和面试题都是PDF,所以我都上传到了网盘,大家可以关注我回复:rabbitmq,获取电子书和最新面试题汇总和一些优化实验报告


RabbitMQ:从入门到搞定面试官的更多相关文章

  1. 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?

    大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...

  2. 搞定面试官 - 你可以介绍一下在 MySQL 中,哪些情况下 索引会失效嘛?

    大家好,我是程序员啊粥,前边给大家分享了 *MySQL InnoDB 索引模型 在 MySQL InnoDB 中,为什么 delete 删除数据之后表数据文件大小没有变 如何计算一个索引的长度 如何查 ...

  3. 金三银四,2018最新iOS面试题,由它可以搞定面试官?

    序言 这些资料,你一定会用到!我相信很多人都在说,iOS行业不好了,iOS现在行情越来越难了,失业的人比找工作的人还要多.失业即相当于转行,跳槽即相当于降低自己的身价.那么做iOS开发的你,你是否在时 ...

  4. 【搞定面试官】try中有return,finally还会执行吗?

    本篇文章我们主要探讨 一下如果try {}语句中有return,这种情况下finally语句还会执行吗?其实JVM规范是对这种情况有特殊规定的,那我就先上代码吧! public class Final ...

  5. 【搞定面试官】- Synchronized如何实现同步?锁优化?(1)

    前言 说起Java面试中最高频的知识点非多线程莫属.每每提起多线程都绕不过一个Java关键字--synchronized.我们都知道该关键字可以保证在同一时刻,只有一个线程可以执行某个方法或者某个代码 ...

  6. 搞定面试官:咱们从头到尾再说一次 Java 垃圾回收

    接着前几天的两篇文章,继续解析JVM面试问题,送给年后想要跳槽的小伙伴 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题..... 万万没想到,JVM内存区域的面试题也可以问 ...

  7. 【搞定面试官】谈谈你对JDK中Executor的理解?

    ## 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1.5 提供了自己的多线程框架 ...

  8. 【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?

    前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...

  9. 搞定面试官 - 可以介绍一下在 MySQL 中你平时是怎么使用 COUNT() 的嘛?

    大家好,我是程序员啊粥. 相信在大家的工作中,有很多的功能都需要用到 count(*) 来统计表中的数据行数.同时,对于一些大数据的表,用 count 都是瑟瑟发抖,往往会结合缓存等进行处理. 那么, ...

随机推荐

  1. Tars | 第7篇 TarsJava Subset最终代码的测试方案设计

    目录 前言 1. SubsetConf配置项的结构 1.1 SubsetConf 1.2 RatioConfig 1.3 KeyConfig 1.4 KeyRoute 1.5 SubsetConf的结 ...

  2. 再谈java线程

    线程状态 描述 当线程被创建并启动之后,它既不是已启动就进入到了执行状态,也不是一直处于执行状态.在线程的声明周期中有六中状态. java api中java.lang.Thread.State这个枚举 ...

  3. Maven专题3——生命周期与插件

    三套生命周期 Maven有3套相互独立的生命周期,用户可以调用某个生命周期的阶段,而不会对其他生命周期产生影响. 每个生命周期包含一些有先后顺序的阶段,后面的阶段依赖于前面的阶段,意味着用户调用后面的 ...

  4. DFS模板

    DFS模板 题型分类:我们可以将DFS题分为两大类: 1 . 地图型:这种题型将地图输入,要求完成一定的任务.因为地图的存在.使得题意清楚形象化,容易理清搜索思路.AOJ 869-迷宫(遍历地图,四向 ...

  5. mysql给数据库表里某个字段赋随机值

    UPDATE sxz_goods set sales_volume_base = round(rand() * 50) + 1 where sales_volume_base =0 ORDER BY ...

  6. Linux系列(35) - 光盘yum源搭建(2)

    光盘搭建yum源 背景 当前Linux服务器没有网络,yum源下载好了,在光盘中 step-01 挂载光盘 mkdir /mnt/cdrom #建立挂载点 mount /dev/cdrom /mnt/ ...

  7. win10系统显示此电脑

    今天电脑开机后发现从任务栏进入"文件资源管理器",直接卡死,重启电脑也没有用. 我想到是不是从"此电脑"进入不会卡死,试了一下果真没有卡死. 使用win10系统 ...

  8. C# 在PPT中添加数学公式

    本次内容介绍在C#程序中给PPT幻灯片添加Latex数学公式,添加公式前,首先需要在幻灯片中插入一个Shape形状,在形状的段落中通过方法Paragraphs.AddParagraphFromLate ...

  9. 浅谈语音质量保障:如何测试 RTC 中的音频质量?

    日常音视频开会中我们或多或少会遭遇这些场景:"喂喂喂,可以听到我说话吗?我听你的声音断断续续的","咦,我怎么可以听到回声?","太吵啦,我听不清楚你 ...

  10. 使用VUE+原生PHP完成搜索后分页的效果

    html代码: <!doctype html> <html lang="en"> <head> <meta charset="U ...