MQ选型比较

MQ介绍

MQ使用场景

  • 异步通信
  • 解耦
  • 冗余
  • 扩展性
  • 过载保护
  • 可恢复性
  • 顺序保证
  • 缓冲
  • 数据流处理

MQ模型

Pub/Sub发布订阅(广播):使用topic作为通信载体
Pub/Sub
Producer/Consumer: 使用queue作为通信载体
Producer/Consumer

MQ组成

  • Broker:消息服务器,作为server提供消息核心服务
  • Producer: 消息生产者,业务的发起方,负责生产消息传输给broker,
  • Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
  • Topic: 主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播
  • Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
  • Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

常用协议

AMQP协议

AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
优点:可靠、通用

MQTT协议

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

STOMP协议

STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。
优点:命令模式(非topic\queue模式)

XMPP协议

XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

其他基于TCP/IP自定义的协议

有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。

开源方案选型

方案介绍

RabbitMQ

使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。

Keywords:Erlang、重量级、企业级

ActiveMQ

Apache下的一个子项目。使用Java完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少量代码就可以高效地实现高级应用场景。可插拔的传输协议支持,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

RocketMQ

阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0 版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,主要多用于订单交易系统。2017年,Apache 软件基金会官方宣布,阿里巴巴捐赠给 Apache 社区的开源项目 RocketMQ 从 Apache 社区正式毕业,成为 Apache 顶级项目(TLP)。Apache RocketMQ 是国内首个非 Hadoop 生态体系的顶级项目,开源至今,RocketMQ 已经被国内外数百家企业广泛使用。

具有以下特点:

  • 能够保证严格的消息顺序
  • 提供针对消息的过滤功能
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力

官方提供了一些不同于kafka的对比差异:
https://github.com/alibaba/RocketMQ/wiki/rmq_vs_kafka

Kafka

Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具有以下特性:
快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
高堆积:支持topic下消费者较长时间离线,消息堆积量大;
完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现负载均衡;
支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

ZeroMQ

又称ØMQ、0MQ、ZMQ,号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中经常使用,偏重于实时数据通信场景。ZMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,开发成本高。因此ZeroMQ具有一个独特的非中间件的模式,更像一个socket library,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序本身就是使用ZeroMQ API完成逻辑服务的角色。但是ZeroMQ仅提供非持久性的队列,如果down机,数据将会丢失。如:Twitter的Storm中使用ZeroMQ作为数据流的传输。
ZeroMQ套接字是与传输层无关的:ZeroMQ套接字对所有传输层协议定义了统一的API接口。默认支持 进程内(inproc) ,进程间(IPC) ,多播 ,TCP协议,在不同的协议之间切换只要简单的改变连接字符串的前缀。可以在任何时候以最小的代价从进程间的本地通信切换到分布式下的TCP通信。ZeroMQ在背后处理连接建立,断开和重连逻辑。
特性:

  • 无锁的队列模型
    对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。
  • 批量处理的算法
    对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。
  • 多核下的线程绑定,无须CPU切换
    区别于传统的多线程并发模式,信号量或者临界区, zeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销。

Redis

使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

使用场景建议

MQ TPS量级(持久化) 场景 备注
Rabbitmq 3500-4000msg/s 非海量高可靠性场景 协议丰富兼容性强,功能完善,消息格式比较大,速度较慢,消息持久化对性能影响明显
ZeroMq >800000msg/s 高并发连接场景,如:在线游戏 偏重于网络开发,开发成本高,高级功能需自行实现,不建议做传统MQ应用
ActiveMq ~3600msg/s 非海量高可靠场景 相对Rabbitmq较轻量级,性能相近,完整JMS支持、配置较复杂
Redis ~15000msg/s 高吞吐低延迟 轻量级MQ的快速简单实现,容灾与负载等功能需自行完善
KafkaInput ~70000msg/s 日志等海量数据流 非典型MQ,更偏重于流式数据批处理

性能对比

待测试

商业方案

AWS

AWS SNS(Amazon Simple Notification Service)、SQS(Amazon Simple Queue Service)。

Amazon SQS 和 Amazon SNS 都是 AWS 中的消息发送服务,但为开发人员提供了不同的优势。Amazon SNS 允许应用程序通过“推送”机制向多个订阅者发送时间关键型消息,并且无需定期检查或“轮询”更新。Amazon SQS 是供分布式应用程序使用的消息队列服务,它通过轮询模式交换消息,可用于解耦收发组件。Amazon SQS 使应用程序的分布式组件可以灵活地收发消息,并且不要求每个组件同时可用。

一种常见的模式是使用 SNS 将消息发布到 Amazon SQS 队列,进而以可靠的方式将消息异步发送到一个或多个系统组件。

  • SNS重点在推送,需要接收组件同时可用
  • SQS更多是一个消息队列服务,需要使用组件通过轮询模式交换消息,不要求每个组件同时可用

Ucloud MQ–UKafka

阿里云MQ–ONS

青云 MQ–kafka

参考:
https://reedf.gitbooks.io/mq/content/mqxuan_xing/redis.html
https://aws.amazon.com/cn/sns/faqs/