消息队列总结

前言

在近年来的互联网企业面试中,消息队列的出场率越来越高。而在实际工作中,我们不仅要知道怎么使用消息队列,更应该去思考为什么要使用消息队列,消息队列的优缺点是什么以及如果我来设计系统架构,我会选择使用哪一种消息中间件。这也是Java工程师成长为架构师的必由之路。

你为什么要使用消息队列?

解耦

未使用消息队列时:有BCD系统依赖A系统,A系统向要给BCD传输数据则必须调用BCD的接口,编写相关代码,此时如果又有E系统需要A发消息,则A必须再编写代码调用E系统接口;同样,如果系统C不需要A发消息了,则A又要修改相关代码…此时系统A与其他系统耦合度高,维护起来非常麻烦

使用消息队列时:A系统(生产者)只需要发送消息到MQ中,BCDE(消费者)如需要数据就自己去中间件里消费,不需要数据就取消消费即可。通过消息中间件的Pub/Sub模式,系统A与其他系统解耦

异步

不使用消息队列服务器时:用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。

使用消息队列服务器时:用户的请求数据发送给消息队列之后立即返回,再由消息队列的消费者从消息队列中获取数据,异步写入数据库,由于消息队列服务器处理速度快于数据库,响应速度大幅提升。

削峰

高并发场景下,大量请求涌入系统A,在高峰期对MySQL的瞬时压力达到5000条/s,导致MySQL能承受2000条/s,导致MySQL挂掉,系统A瘫痪。当高峰期过了之后,低峰期并发量很低,系统A几乎又没有任何压力了。

此时,就需要使用MQ来进行削峰。有了MQ后,用户在高峰期的请求压力全部打在MQ上,然后系统A再以2000条/s的速度从MQ中慢慢拉取请求,不超过自己的处理上限,则高峰时段大量请求积压在MQ中,系统A会匀速处理这些请求,只要高峰期一过,系统A就会快速解决掉积压的消息,从而实现削峰。即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务

电子商务一些秒杀、促销活动中,合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击。

使用消息队列的缺点?

系统可用性降低

必须确保MQ的正常运转,MQ一旦发生故障,整个系统瘫痪,非常严重。能力越大责任越大,不仅适用MQ,也适用开发人员。

系统复杂度提高

在生产环境下增加了系统复杂性,需要考虑消息重复消费、消息丢失、确保消息传递顺序等问题。

一致性问题

当消息没有被消费者正确地消费时,会导致请求和响应的数据总量不一致。

ActiveMQ、RabbitMQ、RocketMQ、Kafka都有什么区别?适合哪些场景?

吞吐量 可用性 可靠性 功能性 社区活跃度
ActiveMQ 十万级(最低) 低概率丢消息 MQ领域功能完备,但不适合大规模吞吐量使用场景 成熟,但不活跃
RabbitMQ 十万级 低概率丢消息 基于erlang开发,并发能力很强,延迟微秒级,其他三个都是毫秒级。管理界面友好
RocketMQ 百万级 非常高,分布式架构 通过优化可以0丢失 MQ领域功能较完备,分布式,扩展性好 较高
Kafka 百万级 非常高,分布式架构 通过优化可以0丢失 功能较简单,大数据领域的实时计算以及日志采集被大规模使用

JMS 和 AMQP

JMS

JMS(JAVA Message Service,java消息服务)是java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。JMS(JAVA Message Service,Java消息服务)API是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。它使分布式通信耦合度更低,消息服务更加可靠以及异步性。

ActiveMQ 就是基于 JMS 规范实现的

JMS的消息模型和消息正文格式-请参考这篇文章:点我

AMQP

AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准 高级消息队列协议(二进制应用层协议),是应用层协议的一个开放标准,为面向消息的中间件设计,兼容 JMS。基于此协议的客户端与消息中间件可传递消息,是跨语言、跨平台的。

RabbitMQ 就是基于 AMQP 协议实现的

AMQP的消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本质来讲,后四种和JMS的pub/sub模型没有太大差别,仅是在路由机制上做了更详细的划分;

消息正文格式:仅支持 byte[] 消息类型。

总结

系统中引入消息队列的作用主要有以下三点:

  • 解耦:通过消息中间件的Pub/Sub模式,使系统解耦,提高了代码的可维护性;
  • 异步:用户请求到达消息队列后就返回,返回的同时消费者消费消息,对数据库进行操作,提升了系统响应速度;
  • 削峰:减轻数据库在高并发场景下的压力,将短时间高并发产生的消息存储在消息队列中,并在非高峰期快速处理掉积压消息。

但是,引入消息队列也会带来以下问题:

  • 系统可用性降低:一旦消息中间件宕机,整个系统瘫痪
  • 系统复杂度提高:需要考虑消息重复消费、消息丢失、确保消息传递顺序等问题
  • 数据一致性问题

四种消息中间件总结:

  • ActiveMQ:最早的MQ,现在用的不多了。社区也不活跃。不推荐使用。
  • RabbitMQ:基于erlang开发,并发能力很强,延迟微秒级完备的管理界面。适合并发量要求不是很高的场景。开源社区很活跃,出问题易维护。
  • RocketMQ:阿里出品开源项目,可定制,且有阿里实际业务场景考验。但社区活跃度相对一般,使用需要承担社区黄掉的风险。推荐对技术有自信的公司使用。
  • Kafka:用Kafka适应大数据领域的实时计算、日志采集等场景,已是业内标准。社区活跃度很高。缺点是有可能消息重复消费,对数据准确度造成轻微影响。

注:本系列文章是来自中华石杉老师课程的整理和总结。






扫一扫,关注我的微信公众号↓

0%