RabbitMQ简介

1.什么是MQ

MQ全称为Message Queue-消息队列,是一种应用程序对应用程序的消息通信,一端只管往队列不断发布信息,另一端只管往队列中读取消息,发布者不需要关心读取消息的谁,读取消息者不需要关心发布消息的是谁,各干各的互不干扰。(简单理解就是两个应用之间的数据传输)

2.为什么使用MQ

2.1 解耦

引入MQ后,不需要关心发布者及消费者之间的关系,这两者不需要彼此联系,减少系统之间的直接依赖。

2.2 异步

对于数据量大或者处理耗时长的操作,可以引入MQ 实现异步通信,减少客户端的等待,提升响应速度。

2.3 削峰

对于会出现瞬间的流量峰值的系统,可以引入MQ 实现流量削峰,达到保护应用和数据库的目的。

3.各消息中间件的比较

四大主流MQ(kafka、ActiveMQ、RabbitMQ、RocketMQ)

ActiveMQ

RabbitMQ

RocketMQ

kafka

吞吐量

万级

万级

十万级

十万级

时效性

ms级

微妙级

这是RabbitMQ的一大特点,延迟是最低的

ms级

ms级

特性

  • 优点

单机吞吐量万级,时效性 ms 级,可用性高

  • 缺点

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

  • 优点

由于 erlang 语言的高并发特性,性能较好,MQ 功能比较完备,健壮、稳定、易用,社区活跃度高;更新频率相当高

  • 缺点

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

  • 优点

单机吞吐量十万级,可用性非常高,分布式架构,消息可以做到 0 丢失,MQ 功能较为完善

  • 缺点

支持的客户端语言不多,目前是 java 及 c++,其中 c++不成熟;社区活跃度一般。

  • 优点

性能卓越,吞吐量高。在大数据领域的实时计算以及日志采集被大规模使用

  • 缺点

消费失败不支持重试,社区更新较慢;

应用场景

ActiveMQ支持任何消息传递用例的能力和灵活性,比较适合小型吞吐量比较小的公司进行使用。

结合 erlang 语言本身的并发优势,性能好时效性微秒级,社区活跃度也比较高,如果你的数据量没有那么大,中小型公司优先选择功能比较完备的 RabbitMQ。

天生为金融互联网领域而生,适用于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰。

Kafka 主要特点是追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务。

4.消息发送类型(基于RabbitMQ说明)

4.1 简单模式

RabbitMQ简介

4.1.1 概念

生产者和消费者在发送和接收消息时,只需要指定队列名称,而不需要指定交换机。(单发送单接收)

4.1.2 使用场景

简单的发送与接收,没有特别的处理。

4.1.3 隐患

消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除。

消息可能没有被消费者正确处理,就已经从队列中消失了,造成消息的丢失。

这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出。

4.1.4 代码例

RabbitMQ简介

手动确认 代码简要说明:

开启手动确认

RabbitMQ简介

消费者:

RabbitMQ简介

4.2 队列模式

RabbitMQ简介

4.2.1 概念

一个生产者将消息发给多个消费者,在多个消费者之间分配消息,类似轮询发送消息,每个消息都只发给一个消费者。(单发送多接收)

4.2.2 使用场景

一个发送端,多个接收端,如分布式的任务派发。特别适合在集群环境中做异步处理,能最大程序发挥每一台服务器的性能。在高并发情况下,队列里面的消息很容易产生积压,此模式可以扩容消费者进行负载均衡处理消息。

4.2.3 隐患

C1、C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息

高并发情况下,默认会产生某一个消息被多个消费者共同使用,所以在处理消息之前要对消息进行加锁及判断该消息是否被处理, 保证一条消息只能被一个消费者使用

4.2.4 代码例

RabbitMQ简介

4.3 发布订阅模式(扇形交换机 Fanout)

RabbitMQ简介

4.3.1 概念

指定交换机 不指定路由,将消息发送给多个队列(发送一条消息,绑定的队列都能接收到消息)

4.3.2 使用场景

发布/订阅模式中,交换机将无差别的将所有消息送入与之绑定的队列,所有消费者拿到的消息完全相同。

中国气象局提供“天气预报”送入交换机,网易、新浪、百度、搜狐等门户接入通过队列绑定到该交换机,自动获取气象局推送的气象数据。

4.3.3 代码例

RabbitMQ简介

RabbitMQ简介

4.4 路由模式(直连交换机 Direct)

RabbitMQ简介

4.4.1 概念

路由(Routing)模式是在发布订阅模式基础上的变种,发布订阅模式是无条件将所有消息分发给所有消费者队列。路由模式则是 Exchange 根据 Routing Key 有条件的将数据筛选后发给消费者队列。

4.4.2 使用场景

监控日志,对于不同级别日志来说,对于 error 级别的日志信息可能是我们需要特别关注的,会被单独的消费者进行处理,此时交换机分发消息是有条件的进行分发,这个就是根据 Routing Key 进行不同的消息分发。

4.4.3 代码例

RabbitMQ简介

RabbitMQ简介

4.5 主题模式(主题交换器 Topic)

RabbitMQ简介

4.5.1 概念

和4.4中的路由模式类型类似 只是可以根据通配符,匹配路由键转发消息。

4.5.2 使用场景

iphone 促销活动可以接收主题为 iphone 的消息,如 iphone12、iphone13 等

在实际使用场景中, 路由模式的效率是高于主题模式,实际工作中可以使用路由模式解决的问题就尽量不要采用主题模式。

4.5.3 代码例

创建队列

两个队列test-queue和test-queue2,其中队列test-queue负责接收路由键以insert结尾的消息

其中队列test-queue2负责接收路由键以update结尾的消息。

RabbitMQ简介

RabbitMQ简介

RabbitMQ简介

4.6 RPC模式

RabbitMQ简介

4.6.1 概念

和上述不同的是,生产者可接收到消费者的返回值

MQ 本质上都是异步通讯的,作为生产者将消息送达消息队列后,他的任务就完成了。至于消费者什么时候消费的,生产者是不关心的。所以这种模式在实际工作中不怎么用。

4.6.2 使用场景

对于消息可靠性要求较高,比如订单支付 钱包扣款,需要等待消费者返回数据,再进行处理。

4.6.3 代码例

RabbitMQ简介

5.总结

5.1 交换机类型

上面的 订阅发布模式、路由模式以及主题模式使用到了不同的交换机,分别是:

  • 扇形交换机 Fanout

  • 直连交换机 Direct

  • 主题交换器 Topic

5.1.1 扇形交换机 Fanout

扇形交换机没有路由键的概念,只需将队列绑定在交换机上,发送到交换机上的消息会转发到交换机所以绑定的队列里面,类似广播,只要打开收音机都能接收到广播消息。扇形交换机应用于发布订阅模式。

5.1.2 直连交换机 Direct

直连交换机被应用在路由模式下,该交换机需要通过特定的routingKey来绑定队列,交换机只有接收到了匹配的routingKey才会将消息转发到对应的队列中,否则就不会转发消息。

5.1.3 主题交换器 Topic

主题模式是将路由键根据一个主题进行分类,和直连模式不同的是,直连模式绑定特定的路由键,而主题模式使用通配符绑定路由键,绑定键有两种:* 表示可以匹配仅一个,#表示可以匹配零个或多个。

5.2 MQ存在的问题有哪些?

5.2.1 消息丢失

各种原因,网络问题,mq故障等,需要保证可靠性传输

解决:消费者手动确认

5.2.2 消息重复

对于重复消费,我们需要改造业务处理逻辑,使得在重复消息的情况下也不会影响最终的结果。

对于要处理的消息,要确认是否已经处理过。常规通过唯一标识符,来区分是否处理过。

  1. 如果一个业务是只读业务,或者是更新的业务,那么多次读取或者多次更新相同的数据基本上都没什么问题。

  2. 如果业务需要插入数据,但是插入的数据中有唯一key能够区分(比如订单编号或流水号),那么业务逻辑就可以变成在插入前先查询这个唯一key是否在数据库中,如果存在说明此前已经成功消费了这条消息,不再消费,否则就是没有成功消费,继续消费。

  3. 通过数据库的方式来防止重复消费的都属于“强校验”类型,会一定程度上影响数据库性能,通常涉及到金钱的都需要强校验,如果不需要强校验,那么使用Redis来代替也行,比如消费者消费时将id或者唯一标识作为key存入Redis,消费者消费时先判断是否存在id。

上面的都是通用的办法,但处理重复消费的问题,始终要根据具体业务来考虑自己的解决办法。(本地数据库表或Redis缓存消费成功的业务标识,每次处理前先进行校验,保证幂等。)

5.2.3 消息堆积

队列中消息不能被及时的消费,导致大量堆积在队列里面

解决:提高消费者的处理能力(队列模式 扩容消费者),增加MQ的服务器资源,cpu、内存、磁盘,提高mq处理能力。

6.参照资料

https://developer.aliyun.com/article/769883

https://developer.aliyun.com/article/759354

https://developer.aliyun.com/article/1102487

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/f8b4ad8ccf.html