这是我参与「第五届青训营」伴学笔记创作活动的第 16 天
概述
消息队列是分布式系统中重要的组件,指保存消息的一个容器,其本质是保存数据的一个队列。主要解决应用解耦、异步消息、流量削峰等问题。本文主要基于参考资料对消息队列的概念以及常见的消息队列软件进行简要汇总。
使用场景
- 应用耦合:多应用间通过消息队列对同样消息进行处理,避免调用接口失败导致整个过程失败。
- 异步处理:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间。
- 限流削峰:广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况。
- 消息驱动系统:系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理。
消息队列模式
-
点对点模式
一个具体的消息只能由一个消费者消费,多个生产者可以向同一个消息队列发送消息,但是一个消息在被一个消费者处理的时候,这个消息在队列上会被锁住或者被移除并且其他消费者无法处理该消息。
-
发布/订阅模式
单个消息可以被多个订阅者并发的获取和处理,一般来说订阅有两种类型:
- 临时订阅:这种订阅只有在消费者启动并且运行的时候才存在。一旦消费者退出,相应的订阅以及尚未处理的消息就会丢失。
- 持久订阅:这种订阅会一直存在,除非主动去删除。消费者退出后,消息系统会继续维护该订阅,并且后续消息可以被继续处理。
主流的消息队列
目前主流的消息队列中间件主要包括Kafka、ActiveMQ、RabbitMQ 及 RocketMQ等,下文将对他们的概况以及优缺点做简要介绍。
Kafka
Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。
Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务。
-
优点:
- 高吞吐、低延迟:kakfa 收发消息非常快,每秒可以处理几十万条消息,它的最低延迟只有几毫秒;
- 高伸缩性: 每个主题(topic) 包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中;
- 持久性、可靠性: Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,Kafka 底层的数据存储是基于 Zookeeper 存储的,Zookeeper 我们知道它的数据能够持久存储;
- 容错性高: kafka是分布式的,一个数据多个副本,某个节点宕机,Kafka 集群能够正常工作;
- 消息有序:消费者采用Pull方式获取消息,消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
- 有优秀的第三方Kafka Web管理界面Kafka-Manager,在日志领域比较成熟,被多家公司和多个开源项目使用;
- 功能支持:功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用。
- 客户端语言丰富:支持Java、.NET、PHP、Ruby、Python、Go等多种语言。
-
缺点:
- Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长;
- 使用短轮询方式,实时性取决于轮询间隔时间;
- 消费失败不支持重试;
- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
- 社区更新较慢。
RabbitMQ
RabbitMQ 是由 RabbitMQ Technologies Ltd 开发并提供技术支持的开源软件。RabbitMQ 是 AMQP(Advanced Message Queuing Protocol)的标准实现。支持多种客户端,如 Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP 等,支持 AJAX、持久化。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
RabbitMQ 采用 Erlang 语言开发。结合erlang语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护。不过RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug。
-
优点:
- 异步消息传递:支持多种消息协议,消息队列,传送确认,灵活的路由到队列,多种交换类型;
- 支持几乎所有最受欢迎的编程语言:Java,C,C ++,C#,Ruby,Perl,Python,PHP等等;
- 可以部署为高可用性和吞吐量的集群;,跨多个可用区域和区域进行联合;
- 可插入的身份验证,授权,支持TLS和LDAP;
- 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件;
- 提供了一个易用的用户界面,使得用户可以监控和管理消息Broker,社区活跃度高。
-
缺点:
- erlang开发,很难去看懂源码,基本职能依赖于开源社区的快速维护和修复bug,不利于做二次开发和维护;
- RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重;
- 需要学习比较复杂的接口和协议,学习和维护成本较高。
RocketMQ
RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿里参考Kafka特点研发的一个队列模型的消息中间件,后开源给apache基金会成为了apache的顶级开源项目,具有高性能、高可靠、高实时、分布式特点。
RocketMQ尤其适用于可靠性要求很高的场景,特别是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。
-
优点:
- 支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型;
- 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递;
- 支持拉(pull)和推(push)两种消息模式;
- 单一队列百万消息的堆积能力;
- 支持多种消息协议,如 JMS、MQTT 等;
- 可靠的FIFO和严格的有序消息传递在同一队列中;
- 灵活的分布式横向扩展部署架构,满足至少一次消息传递语义;
- 提供 docker 镜像用于隔离测试和云集群部署;
- 提供配置、指标和监控等功能丰富的 Dashboard。
-
缺点:
- 支持的客户端语言不多,目前是Java及C++,其中C++不成熟
- 社区活跃度一般
- 没有在 mq 核心中去实现JMS等接口,有些系统要迁移需要修改大量代码
ActiveMQ
ActiveMQ 由 Apache 出品,据官网介绍,它是最流行和最强大的开源消息总线。ActiveMQ 是一个完全支持 JMS1.1 和 J2EE 1.4 规范的 JMS Provider 实现,非常快速,支持多种语言的客户端和协议,而且可以非常容易地嵌入到企业的应用环境中,并有许多高级功能。
-
优点:
- 支持来自Java,C,C++,C#,Ruby,Perl,Python,PHP的各种跨语言客户端和协议;
- 完全支持JMS客户端和Message Broker中的企业集成模式;
- 支持许多高级功能,如消息组,虚拟目标,通配符和复合目标;
- 完全支持JMS 1.1和J2EE 1.4,支持瞬态,持久,事务和XA消息;
- Spring支持,以便ActiveMQ可以轻松嵌入到Spring应用程序中,并使用Spring的XML配置机制进行配置;
- 专为高性能集群,客户端 - 服务器,基于对等的通信而设计;
- CXF和Axis支持,以便ActiveMQ可以轻松地放入这些Web服务堆栈中以提供可靠的消息传递;
- 可以用作内存JMS提供程序,非常适合单元测试JMS;
- 支持可插拔传输协议,例如in-VM,TCP,SSL,NIO,UDP,多播,JGroups和JXTA传输;
- 使用JDBC和高性能日志支持非常快速的持久性。
-
缺点:
- 官方社区现在对ActiveMQ 5.x维护越来越少,较少在大规模吞吐的场景中使用。