RabbitMQ相关知识展览

1. 常见MQ产品

Kafka:分布式消息系统,高吞吐量。
RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好。
RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会。
ActiveMQ:基于JMS。

2. RabbitMQ用途

2.1 服务解耦合

服务A产生数据,服务B、C、D需要这些数据,那我们可以在A服务中直接调用B、C、D服务,把数据传递到下游服务即可。
但是,如果不止3个服务呢,如果有几十甚至几百个下游服务,A中调用服务的代码量会很大,代码维护极为困难。

这是因为服务之间耦合度过于紧密。
调用服务
我们使用RabbitMQ去解耦合。
服务A只需要向消息中间件去传送数据,而不需要考虑谁需要用这些数据。下游的服务可以自行选择从消息中间件中订阅相应的数据,也可以随时取消订阅。
解耦合

2.2 流量削峰

假设我们有一个应用。平时访问量每秒处理300个请求。我们用一台服务器就能完成它。

在这里插入图片描述

而在访问高峰期。访问量可能会在平时的10倍以上,达到每秒3000个请求。那么,单台服务器肯定无法完成任务,我们考虑使用十台服务器。来分散访问的压力。
但是这种访问高峰期,可能每天只会出现几分钟。我们使用十台服务器的话,会造成很多资源的浪费。
在这里插入图片描述

这种情况我们可以使用RabbitMQ的流量削峰。在某一高峰期,瞬间出现的大量请求会被送往消息队列中间件,排队等待被处理。这时我们的应用可以缓慢的从消息队列中间件中拿取数据进行处理,避免瞬时性的压力。

这是消息队列中间件典型的应用场景。
在这里插入图片描述

2.3 异步调用

例如客户点外卖的场景。支付后要发送支付成功的通知,然后寻找外卖小哥进行配送,寻找外卖小哥这个过程中耗时可能是十几秒或几十秒,在高峰期可能更长。这样就会造成整条调用链路的响应十分缓慢。

在这里插入图片描述

我们引入消息队列中间件,这样的话在成功短信通知发送之后,就可以直接进入消息队列中间件,这样的话,链路整条调用就完成了,订单系统会很快的获得响应。大大减少了响应的时间。

寻找外卖小哥的应用可以以异步的方式从消息队列中接受任务,再执行耗时的寻找操作。
在这里插入图片描述

3. RabbitMQ名词概念

RabbitMQ是一个消息中间件,用于处理来自客户端间的异步消息。服务端将要发送的消息放入到队列池中,接收端可以根据RabbitMQ的转发机制接收服务端发来的消息。RabbitMQ根据转发规则进行消息的转发,缓冲和持久化操作。

3.1 Exchange

接收生产者发送的消息,并根据Binding规则将消息路由给服务器中的队列ExchangeType决定了Exchange路由消息的行为,在RabbitMQ中ExchangeType常见的有direct、Fanout和Topic三种。

在这里插入图片描述

3.2 Message Queue

消息队列我们发送给RabbitMQ的消息,最后都会到达各种queue,并且存储在其中,等待消费者来取。如果路由找不到相应的queue,则数据会丢失。

3.3 Binding Key

这个表示的是Exchange与Message Queue通过Binding Key进行联系的,确定消息存储到哪个队列中。一个消息队列可以绑定多个Binding Key。

3.4 Routing Key

生产者在将消息发送给Exchange的时候,一般会指定一个Routing Key,来指定这个消息的路由规则,这个Routing Key需要与ExchangeType和Binding Key联合使用才能生效,我们的生产者只需要通过指定Routing Key来决定消息流向哪里。

4. Exchange类型

4.1 direct

生产者分发信息给Exchange交换机时,会指定一个Routing Key,而Exchange与消息队列Queue通过Binding Key进行对应,direct这种交换机要求Routing Key和Binding Key必须完全匹配,例如一个消息队列绑定到交换机的Binding Key是dog,那么它只转发Routing Key为dog的消息,而不会转发dog.wolf、tiny.dog等。

在这里插入图片描述

4.2 fanout

这种广播方式是最简单,也是转发消息最快的。它不需要处理路由键,也不需要绑定键,它要做的只是简单地将队列绑定到交换机上,生产者分发消息给Exchange交换机时,每个消息都会被转发到与该fanout交换机绑定的所有消息队列上。
在这里插入图片描述

4.3 topic

topic交换机通过模式匹配分配消息,将路由键和某个模式进行匹配。使用topic交换机时,对于Routing Key的格式有所要求,必须是由 . 分隔的多个单词,例如“abc.def.ghi”、“asia.china.news”。Routing Key可以有任意多的单词,最长为255字节。topic交换机的Binding Key含有两个特殊符号,符号“#”匹配0个或多个单词,符号“*”匹配正好一个单词,这两个符号必须出现在 . 的左边或者右边。

在这里插入图片描述

5. RabbitMQ经典八股文

5.1 如何保证消息队列高可用?

RabbitMQ基于主从做高可用性,使用镜像集群模式实现。

镜像集群模式和普通集群模式区别:创建的queue里的消息都会存在于多个实例上,每次你写消息到queue中时,都会自动和多个实例的queue进行消息同步。
这样设计的优点是任何一台机器宕机不影响其他机器使用,缺点是(1)性能开销大:一台机器的消息同步所有机器,网络带宽压力和消耗很大。(2)扩展性差:如果一个queue的负载很重,即使加一台机器,新的机器同样包含这个queue的所有数据,无法给其分担压力。

5.2 如何保证消息消费的幂等性?

首先我们要知道什么是幂等性。
幂等性指的是无论你执行多少次请求,得到的结果都是一样的。例如,你向数据库中插入两条相同的数据,数据库里只会保存一条,这就体现了系统的幂等性。

要保证消息消费时的幂等性,也就是指消息不能被重复消费。

  1. 对于MySQL:在每次insert操作之前,可以先根据主键去查询,如果数据存在就不执行insert操作转而执行update操作。
  2. 对于Redis:Redis具有天然的幂等性,一个key只能对应一条数据,不会出现多次消费。
  3. 对于复杂业务:比如某个订单已经被消费过,下次重复消费时,先根据订单id去Redis或MySQL查,如果没有消费过就处理,如果消费过就直接返回,避免重复操作。

几个重要的点

  1. 消息队列无法帮你做到消息的幂等性,消费端的幂等性需要基于业务场景实现。
  2. 消息队列要保证消息不能丢失,至少要被消费一遍。
  3. 幂等性并不是指只能消费一次,是可以重复消费的,但是重复消费后得到的结果要和消费一次相同。
  4. 是否要保证幂等性,需要根据实际业务进行考量。

5.3 如何保证消息的可靠性传输?

为什么消息传输会不可靠?一般来说,是消息在传输过程中产生了丢失的问题。
丢失又分为:生产者丢失消息、消息队列丢失消息、消费者丢失消息。

  1. 生产者丢失消息
    使用RabbitMQ的confirm模式确保生产者不丢失消息。所有在channel信道上发布的消息都将会被指派一个唯一的ID,一但消息被投递到匹配的队列中,RabbitMQ会发送一个ACK信号给生产者,确保消息已经正常到达队列。

  2. 消息队列丢失消息
    开启消息持久化的配置。这步操作可以和confirm模式一同使用,在消息持久化到磁盘后,再给生产者发送ACK信号。

  3. 消费者丢失消息
    把自动确认消息模式改为手动确认消息即可。

5.4 如何保证消息的顺序性

首先我们要知道为什么会出现顺序错乱。
例如一条消息队列有三个消费者进行消费,他们的执行顺序是增加、修改、删除,但是执行顺序混乱了,变成了删除、修改、增加,显然是出了问题的。

对RabbitMQ来说,消费者集群部署,不同的消费者消费到了同一订单的不同消息,但是他们的执行速度可能不同,所以就导致会出现执行顺序出现了错乱。
例如下图,数据放入MySQL的顺序和在消息队列的顺序就不一样了。
在这里插入图片描述

那么如何解决这个问题呢?在RabbitMQ中,出现消息顺序错乱的原因就是多个消费者消费同一个queue的消息,那么我们解决这个问题,可以给RabbitMQ创建多个queue,每个消费者固定消费一个queue的消息。由于同一个queue消息一定是有序的,那么消息只会被一个消费者顺序消费,保证了消息的顺序性。

在这里插入图片描述

5.5 大量消息积压在MQ里怎么办?

这种情况,属于是线上的故障问题,原因是消费者端坏掉了,无法及时消费堆积在MQ中的消息。
解决办法千万不要说修复消费者端的问题,让他恢复消费速度,等待MQ里的消息被消费完毕,这样的话无法快速解决问题,还会耽误很多时间去消费数据。

一般这个时候,我们采用的办法就是紧急扩容。
临时建立好原本10倍的queue数量,然后将原本的queue中的消息轮询写入临时建立好的10倍的queue,接着临时征用10倍的机器部署consumer,每一批消费者消费一个临时queue的数据。这样的话就能以正常速度的10倍来消费数据了。
等积压的数据快速消耗完成,就可以恢复原先部署的架构,重新用原先的消费者端来消费消息。

5.6 RabbitMQ、kafka、RocketMQ、ActiveMQ区别?

特性ActiveMQRabbitMQRocketMQkafka
开发语言JavaerlangJavascala
单机吞吐量万级万级十万级十万级
时效性ms级us级(最快)ms级ms级
可用性高(主从架构)高(主从架构)非常高(分布式架构)非常高(分布式架构)
其余不推荐使用了并发能力强,性能极好,延时低阿里巴巴开发,功能较完善,扩展性佳为大数据领域提供,一般大公司用的较多
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值