首页 > 技术文章 > RabbitMQ解析

LZXX 2022-02-28 15:07 原文

1.MQ实现了什么,解耦,异步,削峰
解耦:以接口模式给其他系统发送数据,配置麻烦,系统变动,相关配置就要改变,队列这是生产消费模式,只需要生产,其他系统要消费就自己拿 
异步:用户>系统>队列>多个其他系统,  系统只要把请求给了队列,就可以返回给用户,没队列则每个系统都要去请求
削峰:大量并发请求,可以插入队列,让队列平滑请求,减少服务器压力
2.队列的优缺点
可用性降低:加了一层队列,那么多一层风险,
复杂度提高:一致性,不被重复消费,消息可靠传输
一致性:用户>系统>队列>多个其他系统。请求从队列到多个系统,假如其中一个写入失败,数据就不一致
3.如何保证RabbitMQ消息的顺序性?
将原来的一个queue拆分成多个queue,每个queue都有一个自己的consumer。该种方案的核心
是生产者在投递消息的时候根据业务数据关键值(例如订单ID哈希值对订单队列数取模)来将需要
保证先后顺序的同一类数据 发送到同一个queue当中。
4.消息怎么路由
消息提供方->路由->一至多个队列消息发布到交换器时,消息将拥有一个路由键(routing key),
在消息创建时设定。通过队列路由键,可以把队列绑定到交换器上。消息到达交换器后,
RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);
常用的交换器主要分为一下三种:
1. fanout:如果交换器收到消息,将会广播到所有绑定的队列上
2. direct:如果路由键完全匹配,消息就被投递到相应的队列
3. topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通
配符 
5.如何保证消息不被重复消费 1..生产时消息重复,2.消费时消息重复。
1.生产消息重复: 生产》mq,mq确认的时候出现网络波动,生产没有收到确认,实际mq已经接收到了消息。
这时候生产就会重发一遍。生产如果消息未被确认,或确认失败,可以使用定时任务+redis/db,来进行消息重试
2.消费成功后,给mq确认出现网络波动,mq没有接收到确认。mq就会继续给消费投递之前的消息,这时候消息着就接收到了两条一样的消息
解决:
  1.每个消息带1个全局唯一ID,
  2.消费者get到消息后根据id去redis查是否存在 不存在则消费,并写入redis,存在则直接丢弃
6.如何确保消息接收方消费了消息
1.将信道设置成confirm模式,信道会发送1个消息唯一id,
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到
达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。 
接收方确认也是异步的,只有消费者确认了mq才会把消息从队列删除
7.如何保证mq消息丢失
生产者丢失消息
confirm模式:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一
的ID(从1开始),一旦消息被投递到所有匹配的队列之后;rabbitMQ就会发送一个ACK给生产者
(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;如果rabbitMQ没能
处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。
消息队列丢数据:
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制
配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁
盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。 
8.mq为什么不应该对所有message使用持久化?
1.必然导致性能下载,持久化是写磁盘的,和写内存相差10倍
 所以,是否要对 message 进行持久化,需要综合考虑性能需要,以及可能遇到的问题。若想达到
100,000 条/秒以上的消息吞吐量(单 RabbitMQ 服务器),则要么使用其他的方式来确保
message 的可靠 delivery ,要么使用非常快速的存储系统以支持全持久化(例如使用 SSD)。另
外一种处理原则是:仅对关键消息作持久化处理(根据业务重要程度),且应该保证关键消息的量
不会导致性能瓶颈。 
9.如何保证mq的高可用?
mq基于主从模式做高可用,有三种模式:单机,集群,镜像集群
单机一般就是demo,生产基本不会用
普通集群:多台机器多个mq实例(每个机器启动1个mq)。队列只会放在1个mq上,但是每个mq都会同步队列的元数据(队列的一些配置,通过元数据定位到队列所在的实例)。
消费的时候,连接到了另外的mq,那么这个mq就会从队列所在的mq上拉数据过来
提高吞吐量,集群中多个节点服务某个队列的读写操作。
镜像集群模式: 
这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群
模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是
说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意
思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。
RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次
创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
这样的好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue
的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能
开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一
个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整
数据。
10.mq队列满了,消息积压怎么处理?
例:每次消费都写mysql,mysql挂了,消费就不动了,或者消费慢,生产极快
1.修复consumer慢的问题,停掉现有的consumer
2.新建topic放10倍的quenue和10倍的消费者去消费原先的挤压数据,之后回归正常的架构
11.mq设置过期时间,消息过期了怎么办?
1.增加数据库中间表,让它丢失,然后再晚上的时候从中间表找出来重新写进去
12.死信队列
消息被拒(Basic.Reject /Basic.Nack) 且 requeue = false。
消息TTL过期。
队列满了,无法再添加。
1.死信队列的数据,看业务处理
3.rabbitMQ的角色
Broker: 简单来说就是消息队列服务器实体
Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的
queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范
围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型
的例子就是不同的应用可以跑在不同的 vhost 中)。
Producer: 消息生产者,就是投递消息的程序
Consumer: 消息消费者,就是接受消息的程序
Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话
任务 
 
4.RabbitMQ  5种工作模式
1.simple(最简单的收发模式) 消费监听消费队列,有消息就被队列拿走
 
缺点:消费没被正确取来,消息就消费了造成消息丢失。这里可以设置成 手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出
2.work工作模式(资源的竞争)C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息

缺点:高并发情况下,默认会产生某 一个消息被多个消费者共同使用,可以设置一个开关syncronize)保证f消息只能被一个消费者使 用)。

3.publish/subscribe发布订阅(共享资源)每个消费者监听自己的队列

生产者将消息发给队列,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队
列都将接收到消息。

 4.routing路由模式 只能匹配上路由key对应的消息队列,对应的消费者才能消费消息

 

消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对
象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;
根据业务功能定义路由字符串
从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。
业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可
以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误; 

 5.topic 主题模式(路由模式的一种)  增加匹配功能

 

 

* , # 代表通配符* 代表多个单词, # 代表一个单词
路由功能添加模糊匹配
消息产生者产生消息,把消息交给交换机
交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费
mq选择
 
 
 
1.中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;
2.大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。
3.大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃
度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。 
 

Active MQ

RabbitMQ

RocketMQ

Kafka

单机 吞吐 星

万级,比

RocketMQ、

Kafka低一个

数量级

ActiveMQ

10万级,支撞高吞吐

10万级,高吞吐,一般配合大数据类的 系统来进行实时数据计算、日志采集等场 景

topic

数星 对吞 吐的影

 

 

topic可以达到几百/几千的级 另U,吞吐量会有较小幅度的下 降,这是RocketMQ的一大优 势,在同等机器下.可以支撑大 是的topic

topic从几十到几百个时候,吞吐星会大 幅度下降,在同等机器下,Kafka尽量保 证topic数量不要过多,如果要支撑大规 模的topic ,需要増加更多的机器资源

时效

ms级

钢级忑

RabbitMQ 的一大特 点,延迟最

ms级

延退在ms级以内

可用

,基于主 从给实现 高B用

ActiveMQ

非常高,分布式架构

非常高,分布式,一个数据多个副本,少 数机器宕机r不会丢失数据,不会导致不 可用

消息 可靠

有较低的概 率丢失数据

球不丢

经过参数优化配置,可以做到0 丢失

RocketMQ

功能 支持

MQ领域的 功能极其完 备

基于erlang 开发,并发 能力很强, 性

延时很低

MQ功能较为完善,还是分布式 的,扩展性好

功能较为简单,主要支持简单的MQ 能,在大数据领域的实时计算以及日志采 ?Ml模使用

推荐阅读