消息队列和rabbitMQ

it2025-10-11  11


title: 消息队列和rabbitMQ date: 2020-08-02 13:50:19 categories: 消息队列 tags: rabbitMQ


消息队列和rabbitMQ

消息中间件概述

消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异

步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开

发RocketMQ等。

MQ的优点

简答 异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。流量削锋 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。日志处理 - 解决大量日志传输。消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

解耦、异步、削峰是什么?。

解耦:A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。

就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。

异步:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。

削峰:减少高峰时期对服务器压力。

消息的顺序问题

消息有序指的是可以按照消息的发送顺序来消费。假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到 S2,如果要保证 M1 先于 M2 被消费,怎么做?

解决方案:

保证生产者 - MQServer - 消费者是一对一对一的关系

缺陷:

并行度就会成为消息系统的瓶颈(吞吐量不够)更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞的问题。 (2)通过合理的设计或者将问题分解来规避。不关注乱序的应用实际大量存在队列无序并不意味着消息无序 所以从业务层面来保证消息的顺序而不仅仅是依赖于消息系统,是一种更合理的方式。

消息的重复问题

造成消息重复的根本原因是:网络不可达。

所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?

消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一

编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日

志表中,那么就不再处理这条消息。

幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

RbbitMQ

实现mq的协议

MQ是消息通信的模型。实现MQ的大致有两种主流方式:AMQP,JMS.

AMQP:AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是一个进程间传递异步消息的网络协议。

JMS: JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两

个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS

提供支持(百度百科给出的概述)。我们可以简单的理解:两个应用程序之间需要进行通信,我们使用一个JMS服务,进行中间的转发,

通过JMS 的使用,我们可以解除两个程序之间的耦合。(如ActiveMQ,RocketMQ)

RbbitMQ:基于AMQP协议。使用erlang语言开发,稳定性好。它是应用程序之间的通信方法,消息队列在分布式系统中应用十分广泛。(生产者,消费者)

RbbitMQ的六种工作模式

简单模式,work模式,Publish/Subscribe发布与订阅模式,Routing路由模式,Topics主题模式,RPC远程调用模式。

消息自动确认机制

默认情况下,生产者生产的消息平均分配给每一个消费者。

simple模式(即最简单的收发模式)

点对点

1消息产生消息,将消息放入队列

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

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

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

应用场景:聊天(中间有一个过度的服务器;p端,c端)

work模式

消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2,同时监听同一个队列,消息被消费?C1 C2共同争抢当前的消息队列内容,谁

先拿到谁负责消费消息(隐患,高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize,与同步锁的性能

不一样) 保证一条消息只能被一个消费者使用)

某个消费者宕机的情况下:

关闭自动确认。在业务代码执行完成时手动确认。

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

应用场景:红包;

大项目中的资源调度(任务分配系统不需知道哪一个任务执行系统在空闲,直接将任务扔到消息队列中,空闲的系统自动争抢)

Publish/Subscribe发布与订阅模式

广播。通过指定交换机发给 所有与此交换机绑定的队列(交换机类型fanout)

消息产生者将消息放入交换机,交换机发布订阅把消息发送到所有消息队列中,对应消息队列的消费者拿到消息进行消费

相关场景:邮件群发,群聊天,广播(广告)

Routing路由模式

通过指定交换机 发给所有与此交换机下指定的路由键绑定的队列(交换机类型direct)

Topics主题模式(动态路由)

通过指定交换机 发给所有与此交换机下指定的(路由键通配符,如a.*)绑定的队列(交换机类型topic)

消息基于什么传输?

由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道

**是建立在真实的 TCP 连接内的虚拟连接,**且每条 TCP 连接上的信道数量没有限制

参考

RabbitMQ面试题(总结最全面的面试题):https://juejin.cn/post/6844904125935665160

RabbitMQ的六种工作模式:https://www.cnblogs.com/Jeely/p/10784013.html

最新回复(0)