这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
消息队列概述
消息队列(Message Queue,简称MQ)是指保存消息的一个容器,其实本质就是一个保存数据的队列。
消息队列是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性的系统架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。
应用场景
消息队列主要用于在分布式系统中存储转发消息,下面主要介绍消息队列在实际应用中常见的使用场景,包括异步处理,应用解耦,流量削峰和日志处理等。
异步处理
异步处理是将一些非核心的业务流程以异步并行的方式执行,从而减少请求响应时间,提高系统吞吐量。以下单为例,用户下单后需要生成订单记录、修改库存记录、通知商家等一系列业务处理。假设三个业务节点的处理时延如下图所示,不考虑网络等其他开销,并行的时间明显小于串行的时间。这样就大大提高了系统的吞吐量。
应用解耦
应用解耦是解除应用系统之间的耦合依赖。通过消息队列,使得每个应用系统不必受其他系统影响,可以更独立自主。
流量削峰
这种场景中系统的峰值流量往往集中于一小段时间内,所以为了防止系统被短时间内的峰值流量冲垮,往往采用消息队列来削弱峰值流量,相当于消息队列做了一次缓冲,
日志处理
日志处理也是消息队列一个常见的使用场景,解决大量日志传输的问题。
设计架构
MQ 的整体架构一般涉及三类角色,分别是 Producer 消息生产者,Broker 消息处理中心,Consumer 消息消费者,如下图所示。
Producer 消息生产者:负责产生和发送消息到 Broker;
Broker 消息处理中心:负责消息存储、确认、重试等,一般其中会包含多个队列;
Consumer 消息消费者:负责从 Broker 中获取消息,并进行相应处理;
消息传递模式
消息队列一般有为两种消息传递模式:点对点模式或者发布/订阅模式。
点对点模式:消息生产者将消息发送到队列中,消息消费者从队列中接收消息。消息可以在队列中进行异步传输。它的特点在于:
- 每个消息只用一个消费者,即一旦被消费,消息就不再在消息队列中;
- 生产者和消费者之间在时间上没有依赖关系;
- 消费者在成功接收消息后需向队列应答成功;
发布/订阅模式:发布订阅模式是通过一个内容节点来发布和订阅消息,这个内容节点称为主题(topic),消息发布者将消息发布到某个主题,消息订阅者订阅这个主题的消息,主题相当于一个中介。主题是的消息的发布与订阅相互独立,不需要进行基础即可保证消息的传递,发布/订阅模式在消息的一对多广播是采用。消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
消息队列产品选型
Kafka
Kafka 是 Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,基本架构如下图所示
Kafka 具有以下特性:
- 快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
- 高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
- 高堆积:支持topic下消费者较长时间离线,消息堆积量大;
- 完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
- 支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。
它的优点在于:
- 客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;
- 高性能:单机写入TPS约在100万条/秒,消息大小10个字节;
- 提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;
- 支持批量操作;
- 消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
- 有优秀的第三方KafkaWeb管理界面Kafka-Manager;
- 在日志领域比较成熟,被多家公司和多个开源项目使用。
但也存在一些明显的缺点:
- Kafka单机超过64个队列/分区时,Load时会发生明显的飙高现象。队列越多,负载越高,发送消息响应时间变长;
- 使用短轮询方式,实时性取决于轮询间隔时间;
- 消费失败不支持重试;
- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
- 社区更新较慢。
RocketMQ
RocketMQ 是阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,目前主要多用于订单交易系统。
RocketMQ 的特点包括:能够保证严格的消息顺序、提供针对消息的过滤功能、提供丰富的消息拉取模式、高效的订阅者水平扩展能力、实时的消息订阅机制、亿级消息堆积能力。
它的优点在于:
- 单机支持1万以上持久化队列;
- RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,而访问时,直接从内存读取。
- 模型简单,接口易用(JMS的接口很多场合并不太实用);
- 性能非常好,可以允许大量堆积消息在Broker中;
- 支持多种消费模式,包括集群消费、广播消费等;
- 各个环节分布式扩展设计,支持主从和高可用;
- 开发度较活跃,版本更新很快。
缺点在于:
- 支持的 客户端语言不多,目前是Java及C++,其中C++还不成熟;
- RocketMQ社区关注度及成熟度也不及rabbitMQ等;
- 没有Web管理界面,提供了一个 CLI (命令行界面) 管理工具带来查询、管理和诊断各种问题;
- 没有在MQ核心里实现JMS等接口;
参考资料: