当前位置: 首页 > news >正文

八股训练--RabbitMQ

一、经典问题

1.为什么要用MQ?

MQ的作用主要是3个,

  第一个是流量削峰:当某个活动举行时,访问量可能是平时的几百倍,可能一下会把服务器弄崩溃,所以通过MQ的形式,引入中间者,客户端将请求都发到MQ这里,服务器根据自身的容量去MQ中取请求进行处理,这样起了流量削峰的作用。

  第二个是应用解耦:当一个应用中有许多系统,订单系统,库存系统,支付系统等,任何一个子系统出现了故障,都会造成下单操作的故障,引入了MQ之后,一个子系统故障了,另外的子系统仍然可以进行相应的操作。

  第三个是异步处理:当A调用了B方法之后,B方法要执行很久,但A还有许多方法还要执行,就可以使用MQ进行异步的方式执行B方法,A继续执行其他方法,之后B方法执行完成之后就通知A一次,就节省了运行时间。

2.常见MQ的区别

区别RabbitMQRocketMQKafKa
语言ErlangJavaScala & Java
支持语言

几乎支持所有语言

Java,C++不成熟多种语言
单机吞吐量万级3十万级1十万级2
消息延迟微秒级毫秒级毫秒以内
可用性高,基于主从架构非常高,分布式结构非常高,分布式结构,一个数据多个副本
消息可靠性  - 可以做到零丢失可以做到零丢失
优势支持所有语言,吞吐量万级,功能齐全接口简单易用,吞吐量大,分布式使用方便超高吞吐量,ms的延迟,可用性有保障
劣势吞吐量较低,erlang语言不易定制开发,二次开发

只支持Java和C++,C++还不成熟

有可能进行消息的重复消费
应用都有使用大规模,复杂的业务大数据的实时计算和日志采集

3.RabbitMQ各组件功能

1.Server:接收客户端的连接,实现AMQP的实体服务。

2.Connection:连接,应用程序和Server的网络连接,TCP连接

3.Channel:一个信道中有多个Connection,减轻了TCP connection的开销

4.Message:消息

5.VirtualHost:虚拟主机,可以有多个,一个虚拟主机里面有许多交换机和队列,但名称不能相同

6.交换机:按照路由规则将消息映射到对应的队列中。如果路由不到,就返回给消费者或者直接丢弃,常见类型有direct,fanout,topic,headers四种

7.队列:保存消息,给消费者消息

8.绑定:交换机和队列之间的路由规则

4.RabbitMQ的工作原理

  生产者连接到Server,并开启一个信道,建立许多连接,生产者将消息发送给broker server,然后brokersever根据virtualhost中的交换机和队列的路由规则保存在队列中,消费者和中间者建立连接了之后,从队列中取消息进行一定的消费。

5.RabbitMQ的工作模式

1.simple模式:

  生产者将消息直接发送到队列中,消费者监听队列中存在消息,就直接取出消费掉,队列之后将消息删除。

  隐患:消息可能没有被消费者正确处理,但队列仍然将消息删除了,造成了消息的丢失,这时候设置手动的ack比较合适。

2.work Queues模式:

  生成者将消息发送到队列中,有多个消费者去抢夺这个消息,多并发的情况下就设置一个开关,保证消息只能被一个消费者消费

3.publish/subscribe发布订阅模式

  消费者监听队列,生产者将消息发给broker,由交换机将消息转发到绑定每个交换机的每个队列,每个绑定交换机的队列都会收到消息

4.routing路由模式

  只有当交换机和队列的key能够匹配之后,交换机才将消息转发到对应的队列中,之后绑定队列的消费者才能消费

5.topic主题模式(路由模式的一种)

  存在模糊匹配的方式

6.RabbitMQ消息丢失的情况有哪些?

1.生产者发送消息到broker server时发生丢失

2.broker server 存储的消息丢失

3.broker server 存储的消息分发给消费者时丢失

7.消息丢失的原因和解决方法

1.生产者发送消息到broker server时发生丢失:

  原因:1.发送过程中存在网络问题   2.代码本身逻辑问题

  解决方法:发送方确认机制(publisher confirm):生产者将信道设置成confirm模式,一旦信道进入这个confirm模式,信道上面的消息就会被指派一个唯一id,一旦消息被投递到队列中,broker就会返回一个确认消息给生产者(包含消息的唯一id),这就确保了消息的成功传递(confirm模式最大的好处就是它是异步的,一旦发布了一条消息,生产者可以继续发送消息,消息被确认了之后,生产者会调用回调方法来确认,如果broker server因为自身错误丢失了消息就会返回一个nack,生产者之后再重新做相应的处理)

  发布确认的情况:

1.单独发布确认:一条消息只有被确认了之后,才能继续发送消息,如果指定时间没有返回确认信息就会抛异常

2.批量发布确认:一次性发布一批消息,但如果发送故障导致发布出现问题之后,就无法知道是哪个消息出现了问题,就导致需要重新发一整批消息,同步操作,会阻塞消息的发布

3.异步发布确认:逻辑虽然比前两个复杂,但是因为异步提高了许多效率,将消息的确认异步处理,发送消息之后仍然可以继续发送消息。

  还可以使用AMQP的事务处理,但是这样的方式效果不是特别的好,因为这个事务是同步的,一旦有一条消息丢失了之后,就会阻塞整个发送的过程。跟单独发布类似了

2.Broker Server 中存储的消息丢失:

原因:消息没有持久化,服务器重启的时候导致消息丢失

  解决方式:1.消息回退:通过设置mandatory参数可以在当消息传递过程中不可达目的地时将消息返回给生产者。对于这些无法路由的消息就设定一个备份交换机,然后将消息存储到备份交换机的队列中,这时候之后就手动地对这些队列中的消息进行处理

  2.设置持久化:当MQ接收到消息的时候,通过持久化的方式将消息存储到硬盘中

3.RabbitMQ 发给消费者时消息丢失:

原因:1.消费者接收到消息之后,还没来得及处理消息,消费者机器就宕机了

2.处理消息存在异常

解决方案:默认采用了自动应答的方式,要想消息在消费过程中不丢失,需要把手动应答转换成自动应答。

8.RabbitMQ消息基于什么传输

  由于TCP连接的创建和销毁开销较大,且并发数会受到系统资源的限制,RabbitMQ采用信道的方式来传输数据。信道是建立在真实的TCP连接内的虚拟连接,每个tcp上的信道数量是没有限制的。

9.RabbitMQ支持消息幂等性?

  支持的,当生产者给mq发送一条消息的时候,mq内部都会生成一个inner-msg-id,作为去重的依据(消息投递失败并重传),防止重复的消息进入队列。消费同理,要求消费体中必须要有一个bizid,避免一条消息被重复消费。

10.RabbitMQ消息持久化的条件

1.声明队列必须设置为持久化durable设置为true

2.消息推送投递模式必须设置持久化,deliveryMode设置为2(持久)

3.消息到达持久化的交换机

4.消息到达持久化的队列

11.RabbitMQ死信队列的介绍

定义:由于一些原因导致queue种的某些消息无法被正常消费,这些消息没有后续的处理,就变成了死信消息

来源:消息TTL过期,(队列达到最大值,消息无法加入到队列中),消息被拒绝

用处:用于实现延迟队列

12.RabbitMQ延迟队列的介绍

用来存放在指定时间被处理的队列

使用场景:

1.订单在10分钟内未支付自动取消

2.用户注册之后,3天没有登录就发短信提醒

3.用户发起退款,3天内商家没有处理,就直接通知运营人员

4.预定会议后,开始前10分钟通知各个人员进行参会

实现条件:1.消息设置TTL  2.存在死信队列

13.RabbitMQ如何处理消息堆积

  当出现消息挤压之后,先处理宕机的消费者,然后创建原先N倍的队列,将堆积的消息都轮询到这些队列中,然后再创建N倍的消费者,每一个消费者对应一个队列,快速地把堆积的消息给消费了之后,恢复到原来的模式。(这种做法就相当于临时将queue的资源和消费者的i资源扩大了N倍,消费的速度也变为了N倍)

14.RabbitMQ如何处理消息中丢失的数据

  在流量的低峰期的时候,写一个程序去手动查询那些丢失的信息,然后将消息重新发送到mq中,让消费者进行消费

15.RabbitMQ如何处理长时间未处理导致写满的情况?

  和上面的情况类似,先写一个程序直接去MQ中消费消息,消费一个就丢弃一个,先降低MQ的压力,等到流量低峰期时,就去手动地查询丢失的数据

16.如何设计一个消息队列

这个问题可以观看我以前的博客:Java项目--仿RabbitMQ的消息队列_04Koi.的博客-CSDN博客

这里面详细讲解了如何简单设计一个消息队列,感谢观看!

http://www.dtcms.com/a/274432.html

相关文章:

  • LVS-NAT模式配置
  • 《Java 虚拟机内幕:从垃圾回收到类加载的深度解析》
  • 微积分核心考点全解析
  • pnpm 的 resolution-mode 配置 ( pnpm 的版本解析)
  • 上位机知识篇---Docker
  • 静态路由综合实验报告册
  • HashMap简介
  • 五星出东方洛老师:gma绘制的洛阳市瀍河回族区的地图和兴趣点
  • 高精加法-P1601 A+B Problem(高精)
  • intellij idea的重命名shift+f6不生效(快捷键被微软输入法占用)
  • 决策树算法在医学影像诊断中的广泛应用
  • 知识科普丨详述agent含义
  • 【深度学习系列】ResNet网络原理与mnist手写数字识别实现
  • 浏览器重绘与重排
  • JAVA ---Excel高效导入(去重1000万数据对比)
  • 聊聊微服务架构中的双token
  • Junit多线程的坑
  • Python爬虫动态IP代理报错全解析:从问题定位到实战优化
  • 【牛客刷题】超级圣诞树(递归法和分形复制法)
  • 实时数仓和离线数仓还分不清楚?看完就懂了
  • SpringCloud 运用(5)—— sentinel限流与seata分布式事务
  • 「备忘」查询日志
  • Spring Boot整合MyBatis+MySQL实战指南(Java 1.8 + 单元测试)
  • 从 JavaFX WebView 迁移至 JxBrowser
  • 【科研绘图系列】R语言绘制系统发育树和柱状图
  • 以科技赋能未来,科聪持续支持青年创新实践 —— 第七届“科聪杯”浙江省大学生智能机器人创意竞赛圆满落幕
  • 宝塔 php支持sqlserver
  • 稀疏激活大模型推理优化:突破效率瓶颈的曙光
  • JavaScript VMP (Virtual Machine Protection) 分析与调试
  • 动态规划初步(完全背包)