RabbitMQ干货分享:RabbitMQ核心概念及工作原理

RabbitMQ干货分享:RabbitMQ核心概念及工作原理

什么是MQ

MQ全称是Message Queue,消息的队列,因为是队列,所以遵循FIFO 先进先出的原则,它是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。

为什么使用MQ

①流量削峰:解决高并发问题

例如秒杀活动,可能会在短时间内产生大量请求同时打到服务端,如果后端对每个请求都进行数据库读写操作,定会造成服务器压力过大,产生服务异常甚至不可用。我们可以通过使用MQ实现流量缓冲,将所有请求先放入消息队列中,服务端每次处理业务先从消息队列获取,从而实现流量削峰,解决高并发问题。

0c56e77dd64d26ad355fc7ee7e362c99

②应用解耦:提升系统可用性

例如电商应用中有订单系统、库存系统、物流系统、支付系统,当用户创建订单后,先后调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单失败。引入消息队列后,系统间耦合调用的问题会减少,任何一个子系统出现故障都不会影响用户下单,子系统故障恢复后,会继续处理消息,提升系统可用性。

af6590d82eedbd0beb867a2171f82620

③异步处理:提升响应速度

当用户在客户端提交了一个同步请求,后端处理需要耗时很久才能响应,这对用户体验来说无疑是致命的。如果说用户并不关心请求是否处理完成,对于一些耗时的非事务性的业务处理,可以使用消息队列异步请求的方式,将请求信息放入消息队列,直接返回客户端响应,后端监听队列自行处理,提升响应速度。

983f918d7339795cb9d99b7ef6fe6a89

常见MQ分类

d4c3603f7dc5ea0a36736ceefdd403ef

①Kafka

号称大数据的杀手锏,谈到大数据领域内的消息传输,则绕不开Kafka,这款为大数据而生的消息中间件,以其百万级TPS的吞吐量名声大噪,迅速成为大数据领域的宠儿,在数据采集、传输、存储的过程中发挥着举足轻重的作用。

优点:单机写入TPS约在百万条/秒,最大的优点,就是吞吐量高。时效性ms级可用性非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用,消费者采用Pull方式获取消息,消息有序,通过控制能够保证所有消息被消费且仅被消费一次;有优秀的第三方Kafka Web管理界面Kafka-Manager;在日志领域比较成熟,被多家公司和多个开源项目使用;主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集场景中大规模使用。

缺点:单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,Load越高,发送消息响应时间变长,使用短轮询方式,实时性取决于轮询间隔时间,消费失败不支持重试;支持消息顺序,但是一台代理宕机后,就会产生消息乱序,社区更新较慢。

②ActiveMQ

ActiveMQ是一款非常古老的MQ。

优点:单机吞吐量万级,时效性ms级,可用性高,基于主从架构实现高可用性,消息可靠,丢失数据的概率较低。

缺点:官方社区现在对ActiveMQ 5.x维护越来越少, 高吞吐量场景较少使用。

③RocketMQ

RocketMQ是阿里巴巴开源产品,用Java语言实现,在设计时参考了Kafka,并做出些改进,被阿里巴巴广泛应用。

优点:单机吞吐量十万级,可用性非常高,分布式架构,消息可以做到0丢失,MQ功能较为完善,扩展性好,支持10亿级别的消息堆积,不会因为堆积导致性能下降。

缺点:支持的客户端语言不多,目前是java及C++,其中C++不成熟;社区活跃度一般,没有在MQ核心中实现JMS等接口,有些系统要迁移需要修改大量代码。

④RabbitMQ

2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。

优点:由于erlang语言的高并发特性,性能较好;吞吐量到万级,MQ功能比较完备、健壮、稳定、易用、跨平台、支持多种语言,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX文档齐全;开源提供的管理界面非常棒,用起来很好用,社区活跃度高,更新频率相当高。

缺点:商业版需要收费,学习成本较高

参考资料:

https://www.imooc.com/article/290040

https://rocketmq.apache.org/docs/motivation/

RabbitMQ工作原理

be5b301459ae15f404193aa10bfcde52

  • 生产者(Producer)通过信道(Channel)把消息发送给交换机(Exchange),当创建交换机时需要指定类型(四种类型:直接Direct,扇出Fanout ,主题Topic ,消息头Headers );
  • 交换机(Exchange)接收消息并且负责对消息进行路由,交换机根据消息的属性来把消息分发到不同的队列(Queue)上;
  • 消息(Message)会一直留在队列里直到被消费者(Consumer)消费。

RabbitMQ核心概念

  • 生产者(Producer):发送消息的应用。
  • 消费者(Consumer):接收消息的应用。
  • 队列(Queue):存储消息的缓存。
  • 消息(Message):由生产者通过RabbitMQ发送给消费者的信息。
  • 连接(Connection):连接RabbitMQ和应用服务器的TCP连接。
  • 信道(Channel):连接里的一个虚拟通道,通过消息队列发送或者接收消息时,都是通过信道进行的。
  • 交换机(Exchange):交换机负责从生产者那里接收消息,并根据交换类型分发到对应的消息队列里。
  • 绑定(Binding):绑定是队列和交换机的一个关联连接。
  • 路由键(Routing Key):路由键是供交换机查看并根据键来决定如何分发消息到队列的一个键,路由键可以说是消息的目的地址。
  • 代理(Broker):接收和分发消息的应用,RabbitMQ Server就是Message Broker。
  • 虚拟主机(Virtual host):出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue 等。

RabbitMQ的高级应用

①死信队列

553353bbdf8b48a29390a558a154b212

死信队列(DLX,Dead-Letter-Exchange),利用DLX,当消息在一个队列中变成无法被消费的消息(dead message)之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX。

消息变成死信的几种情况:

1、 消息被拒绝(channel.basicReject/channel.basicNack)并且request=false;

2、 消息在队列的存活时间超过设置的生存时间(TTL)时间;

3、 队列达到最大长度(队列满了,无法再添加数据到队列中)。

DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。

死信队列的设置:

1、首先,需要设置死信队列的Exchange和queue,然后进行绑定;

2、然后,我们进行正常声明交换机、队列、绑定,只不过我们需要在队列机上一个参数即可:arguments.put(“x-dead-letter-exchange”,”dlx.exchange”);这样消息在过期、被拒绝、队列在达到最大长度时,消息就可以直接路由到死信队列。

②延迟队列

6342ab021b7b8e3f7582a5294708639c

基于rabbitmq_delayed_message_exchange插件,实现延迟队列效果。它是一种新的交换类型,该类型消息支持延迟投递机制消息传递后并不会立即投递到目标队列中,而是存储在mnesia(一个分布式数据系统)表中,当达到投递时间时,才投递到目标队列中。使用延迟队列,可以有效解决定时任务带来的系统压力以及业务处理时效性等问题。

应用场景:

  • 订单在30分钟之内未支持,则自动取消订单
  • 工单在60分钟之内仍未处理,则发送消息提醒
  • 预定会议室后,在预定时间前10分钟,通知提醒各参会人员
  • ………………………………

③队列幂等性

1e3caea18be38fc4e06460c668fc7ccb

幂等性的实质是:对于一个资源,不管你请求一次还是请求多次,对该资源本身造成的影响应该是相同的,不能因为重复相同的请求而对该资源重复造成影响。注意关注的是请求操作对资源本身造成的影响,而不是请求资源返回的结果。

MQ消费者的幂等性一般使用全局ID或者写个唯一标识(比如流水号/时间戳/UUID/订单号)来判断该消息是否已消费过,也可以利用redis执行setnx命令,天然具有幂等性,从而实现不重复消费(推荐使用redis)。

④优先级队列

优先级队列,也就是具有高优先级的队列,优先级高的消息具备优先被消费的特权。通过队列的 x-max-priority 参数设置队列的最大优先级,之后在发送消息时通过 priority 属性再设置当前消息的优先级。优先级应在 0 和 255 之间,推荐1 ~ 10。

  • 优先级默认最低为0,最高为队列设置的最大优先级;
  • 对于单条消息来谈优先级是没有什么意义的。假如消费者的消费速度大于生产者的速度且Broker中没有消息堆积的情况下,对发送的消息设置优先级就没有什么意义,因为生产者刚发完一个消息就被消费者消费了,相当于Broker中至多只有一条消息。

⑤惰性队列

b1d0cde57563225b80fe0e6803928600

惰性队列会尽可能地将消息存入磁盘中,而在消费者消费消息时才会被加载到内存中,它支持更多的消息存储。

队列具备两种模式:default 和 lazy。默认的为 default 模式,在队列声明的时候可以通过“x-queue-mode”参数来设置队列的模式,取值为“default”和“lazy”。

给TA打赏
共{{data.count}}人
人已打赏
干货分享

分布式锁主流实现方案有哪些?(Redis分布式锁详细介绍原理和实现)

2023-8-27 15:16:42

干货分享

大数据、数据仓库、数据中台三者的区别有哪些?

2023-8-27 18:20:17

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索
打开微信,扫描左侧二维码,关注【旅游人lvyouren】,发送【101】获取验证码,输入获取到的验证码即可解锁复制功能,解锁之后可复制网站任意一篇文章,验证码每月更新一次。
提交