一、概述
什么是MQ?
MQ全称为Message Queue, 消息队列(MQ)
MQ:生产者往消息队列中写消息,消费可以读取队列中的消息。
消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一
系列功能。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开
发RocketMQ等。
二、消息中间件的组成
1 . Broker
消息服务器,作为server提供消息核心服务
2 . Producer
消息生产者,业务的发起方,负责生产消息传输给broker,
3 . Consumer
消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
4 . Topic
主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的 广播
5 . Queue
队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
6 . Message
消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
如下:RocketMQ Producer-Broker-Consumer架构图
三、 消息中间件模式分类
1 . 点对点(point to point, queue)
PTP点对点:使用queue作为通信载体
说明:
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。
消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,
但是对一个消息而言,只会有一个消费者可以消费。
2 . 发布/订阅(publish/subscribe,topic)
Pub/Sub发布订阅(广播):使用topic作为通信载体
说明:
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到
topic的消息会被所有订阅者消费。
两种模式对比:
(1).queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消
费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。
(2).topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者
都能得到一个消息的拷贝。
四、消息中间件的优势
1 . 系统解耦
交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。
2 . 提高系统响应时间
例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送几个逻辑才能完成;通过MQ架
构设计,就可将紧急重要(需要立刻响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,
供消费者处理。
3 . 为大数据处理架构提供服务
通过消息作为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。
4 . Java消息服务——JMS
Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,
用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
JMS中的P2P和Pub/Sub消息模式:点对点(point to point, queue)与发布订阅(publish/subscribe,topic)最初是由
JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)。
五、消息中间件应用场景
1 . 异步通信
有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理
它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
2 . 解耦
降低工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。通
过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化
时,可以独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
3 . 冗余
有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被
完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中,在把一个消息从队列中
删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
4 . 扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改
变代码、不需要调节参数。便于分布式扩容。
5 . 过载保护
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量无法提取预知;如果以为了能处理这类瞬间峰
值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突
发的超负荷的请求而完全崩溃。
6 . 可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,
加入队列中的消息仍然可以在系统恢复后被处理。
7 . 顺序保证
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处
理。
8 . 缓冲
在任何重要的系统中,都会有需要不同的处理时间的元素。消息队列通过一个缓冲层来帮助任务最高效率的执行,该缓冲
有助于控制和优化数据流经过系统的速度,以调节系统响应时间。
9 . 数据流处理
分布式系统产生的海量数据流,如:业务日志、监控数据、用户行为等,针对这些数据流进行实时或批量采集汇总,然后
进行大数据分析是当前互联网的必备技术,通过消息队列完成此类数据收集是最好的选择。
六、 常见消息中间件MQ介绍
1 .RocketMQ
阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计
思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所
有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,目前主要
多用于订单交易系统。
具有以下特点:
(1).能够保证严格的消息顺序
(2).提供针对消息的过滤功能
(3).提供丰富的消息拉取模式
(4).高效的订阅者水平扩展能力
(5).实时的消息订阅机制
(6).亿级消息堆积能力
2 .RabbitMQ
使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使得它变
的非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在
发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进
行企业级的ESB整合。
3 . 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等。
4 . Kafka
Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具有以下特性:
(1).快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
(2).高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
(3).高堆积:支持topic下消费者较长时间离线,消息堆积量大;
(4).完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
(5).支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是
一个可行的解决方案。