MQ消息队列(应用场景,产品对比)

3,515 阅读8分钟

一、什么是消息队列(MQ)

MessageQueue 是一个广泛应用在互联网项目中且非常重要的技术, MessageQueue 通常被用来解决在高并发压力下类似于流量削峰、服务解耦、消息通讯、最终消息一致性等这样的问题。

二、什么场景下使用MQ呢?

MQ 可应用在多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、手游、视频、物联网、车联网等。

从应用功能上来讲。例如:

  • 日志监控,作为重要日志的监控通信管道,将应用日志监控对系统性能影响降到最低。
  • 消息推送,为社交应用和物联网应用提供点对点推送,一对多广播式推送的能力。
  • 金融报文,发送金融报文,实现金融准实时的报文传输,可靠安全。
  • 电信信令,将电信信令封装成消息,传递到各个控制终端,实现准实时控制和信息传递。

从功能角度考虑:

  • MQ 在实际应用中常用的使用场景主要有异步处理,应用解耦,流量削锋和消息通讯四个场景

2.1 异步处理

场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种:

1.正常串行的方式

  • 注册信息写入数据库
  • 发送注册邮件
  • 发送注册短信

总共耗时150ms

2.并行方式(开启异步线程)

  • 注册信息写入数据库
  • 注册邮件+短信

总共耗时100ms

假设三个业务节点每个使用 50 毫秒钟,不考虑网络等其他开销,则串行方式的时间是 150 毫秒,并行的时间可能是 100 毫秒。 因为 CPU 在单位时间内处理的请求数是一定的,假设 CPU1 秒内吞吐量是 100 次。则串行方式 1 秒内 CPU 可处理的请求量是 7 次(1000/150)。并行方式处理的请求量是 10 次(1000/100)

小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?

答:引入消息队列,将不是必须的业务逻辑,异步处理,改造后的架构如下:

按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是 50 毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是 50 毫秒。因此架构改变后,系统的吞吐量提高到每秒 20 QPS。比串行提高了 3 倍,比并行提高了两倍。而且主流消息队列都支持集群,也可以解决处理慢的情况。

当然了,也不光注册这个场景,还有上传文件啊,解析Excel啊,都可以考虑引入队列,然后搞一个传输中心就可以了。

2.2 应用解耦

场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图:

在这里插入图片描述

传统模式的缺点:假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合

如何解决以上问题呢?引入应用消息队列后的方案,如下图:

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功

库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作

假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦

2.3 流量削峰

流量削锋也是消息队列中的常用场景,一般在秒杀或抢够活动中使用广泛。
应用场景:秒杀活动,一般会因为流量过大,应用系统配置承载不了这股瞬间流量,导致系统直接挂掉,即传说中的“宕机”现象。为解决这个问题,我们会将那股巨大的流量拒在系统的上层,即将其转移至 MQ 而不直接涌入我们的接口,此时MQ起到了缓冲作用。

2.4 日志处理

日志处理是指将消息队列用在日志处理中,比如 Kafka 的应用,解决大量日志传输的问题。架构简化如下

在这里插入图片描述

  • 日志采集客户端,负责日志数据采集,定时写入kafka队列

  • kafka消息队列,负责日志数据的接收,储存和转发

  • 日志处理应用:订阅并消费kafka数据

  • 常用的日志收集架构有:

  • ELK/EFK

三、MQ产品对比

目前主流的MQ主要有:

  • RabbitMQ
  • RocketMQ
  • kafka
  • Activemq

3.1 MQ对比

**MQ**
**描述**
RabbitMQ
erLang开发(高并发语音),对消息堆积的支持不算太好,当大量消息积压的时候,会导致Rabbit性能下降。每秒钟可以处理几万到几十万条消息。
RocketMQ
java开发,面向互联网集群化功能丰富,对在线业务的响应时延做了很多的优化,大多数情况。而且由于是java开发,如果想进行定制化扩展也比较方便
Kafka
Scala开发,面向日志功能丰富,性能最高。当你的业务场景中,每秒钟消息数量没有那么多的时候,kafka的时延反而会比较高,所以,Kafka不太适合在线业务场景。
Activemq
java开发,简单,稳定,性能不如前面三个。小型系统用也ok,但是不推荐。

3.2 主流MQ的优缺点

RabbitMQRocketMQKafkaActivemq
协议AMQPAMQP自行设计AMQP
跨语言支持支持支持支持
优点单机吞吐量: 万级 健壮、稳定、医用、跨平台、支持多种语言; 功能支持: MQ功能完备 高扩展性: 支持事务 单机吞吐量:十万级 可用性: 非常高,分布式 架构: 消息可靠性高 功能支持:MQ功能完备 高扩展性:支持事务 单机吞吐量:百万级 可用性:分布式的非常高 依赖ZK可动态扩展节点高性能高吞吐,消息可指定追溯 单机吞吐量:万级 可用性:非常高 功能支持: MQ功能完备 高扩展性
缺点Elang语言难度大,很难扩展,研发人员较少目前只支持java及c++;严格的顺序机制,不支持消息优先级,不支持标准协议项目比较陈旧,官方社区在5.X之后对其维护越来越少
综合评价适用于稳定性要求优先的企业级应用阿里系,国内互联网公司使用居多在日志和大数据方向使用较多小型系统比较适用,但是因为维护越来越少,建议不用

中小型软件公司,建议选 RabbitMQ,一方面,erlang 语言天生具备高并发的特性,而且他的管理界面用起来十分方便。正所谓,成也萧何,败也萧何!他的弊端也在这里,虽然RabbitMQ 是开源的,然而国内有几个能定制化开发 erlang 的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的 bug,这点对于中小型公司来说十分重要。不考虑 rocketmq 和 kafka 的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以 kafka 排除。可以考虑阿里的 rocketmq.

大型软件公司,根据具体使用在 rocketMq 和 kafka 之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对 rocketMQ,大型软件公司也可以抽出人手对 rocketMQ 进行定制化开发,毕竟国内有能力改 JAVA 源码的人,还是相当多的。至于 kafka,根据业务场景选择,如果有日志采集功能,肯定是首选 kafka 了。具体该选哪个,看使用场景。

我们在进行中间件选型时,一般都是通过下面几点来进行产品选型的:

 1)性能
2)功能支持程度
3)开发语言(团队中是否有成员熟悉此中间件的开发语言,市场上此种语言的开发人员是否好招)
4)有多少公司已经在生产环境上实际使用过,使用的效果如何
5)社区的支持力度如何
6)中间件的学习程度是否简单、文档是否详尽
7)稳定性
8)集群功能是否完备

如果从以上 8 点来选型一个消息队列,作为一名熟悉 java 的程序员,当遇到重新选择消息队列的场景时,我会毫不犹豫的选型 rocketmq,除了监控管理功能不友好外,从其它方面来说,它真的是一款非常优秀的消息队列中间件。而且如果你的项目是用java编写的话,使用rocketmq在排错以及优化上,都可以自行进行定制。