消息队列总结

消息队列

本文内容思惟导图:
消息队列总结

一 什么是消息队列

    咱们能够把消息队列比做是一个存放消息的容器,当咱们须要使用消息的时候能够取出消息供本身使用。消息队列是分布式系统中重要的组件,使用消息队列主要是为了经过异步处理提升系统性能和削峰、下降系统耦合性。目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ,咱们后面会一一对比这些消息队列。
    另外,咱们知道队列 Queue 是一种先进先出的数据结构,因此消费消息时也是按照顺序来消费的。好比生产者发送消息1,2,3...对于消费者就会按照1,2,3...的顺序来消费。可是偶尔也会出现消息被消费的顺序不对的状况,好比某个消息消费失败又或者一个 queue 多个consumer 也会致使消息被消费的顺序不对,咱们必定要保证消息被消费的顺序正确。
    除了上面说的消息消费顺序的问题,使用消息队列,咱们还要考虑如何保证消息不被重复消费?如何保证消息的可靠性传输(如何处理消息丢失的问题)?......等等问题。因此说使用消息队列也不是十全十美的,使用它也会让系统可用性下降、复杂度提升,另外须要咱们保障一致性等问题。

二 为何要用消息队列

    使用消息队列主要有两点好处:
        1.经过异步处理提升系统性能(削峰、减小响应所需时间);
        2.下降系统耦合性。
(1) 经过异步处理提升系统性能(削峰、减小响应所需时间)
                                                    经过异步处理提升系统性能
    在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的状况下数据库压力剧增,使得响应速度变慢。可是在使用消息队列以后,用户的请求数据发送给消息队列以后当即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。因为消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),所以响应速度获得大幅改善。
    经过以上分析咱们能够得出消息队列具备很好的削峰做用的功能——即经过异步处理,将短期高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 
举例:在电子商务一些秒杀、促销活动中,合理使用消息队列能够有效抵御促销活动刚开始大量订单涌入对系统的冲击。以下图所示:
    合理使用消息队列能够有效抵御促销活动刚开始大量订单涌入对系统的冲击,由于用户请求数据写入消息队列以后就当即返回给用户了,可是请求数据在后续的业务校验、写数据库等操做中可能失败。所以使用消息队列进行异步处理以后,须要适当修改业务流程进行配合,好比用户在提交订单以后,订单数据写入消息队列,不能当即返回用户订单提交成功,须要在消息队列的订单消费者进程真正处理完该订单以后,甚至出库后,再经过电子邮件或短信通知用户订单成功,以避免交易纠纷。这就相似咱们平时手机订火车票和电影票。
(2) 下降系统耦合性
    咱们知道若是模块之间不存在直接调用,那么新增模块或者修改模块就对其余模块影响较小,这样系统的可扩展性无疑更好一些。
咱们最多见的事件驱动架构相似生产者消费者模式,在大型网站中一般用利用消息队列实现事件驱动结构。以下图所示:
利用消息队列实现事件驱动结构
    消息队列使利用发布-订阅模式工做,消息发送者(生产者)发布消息,一个或多个消息接受者(消费者)订阅消息。 从上图能够看到消息发送者(生产者)和消息接受者(消费者)之间没有直接耦合,消息发送者将消息发送至分布式消息队列即结束对消息的处理,消息接受者从分布式消息队列获取该消息后进行后续处理,并不须要知道该消息从何而来。对新增业务,只要对该类消息感兴趣,便可订阅该消息,对原有系统和业务没有任何影响,从而实现网站业务的可扩展性设计。
消息接受者对消息进行过滤、处理、包装后,构形成一个新的消息类型,将消息继续发送出去,等待其余消息接受者订阅该消息。所以基于事件(消息对象)驱动的业务架构能够是一系列流程。
另外为了不消息队列服务器宕机形成消息丢失,会将成功发送到消息队列的消息存储在消息生产者服务器上,等消息真正被消费者服务器处理后才删除消息。在消息队列服务器宕机后,生产者服务器会选择分布式消息队列服务器集群中的其余服务器发布消息。
备注: 不要认为消息队列只能利用发布-订阅模式工做,只不过在解耦这个特定业务环境下是使用发布-订阅模式的。除了发布-订阅模式,还有点对点订阅模式(一个消息只有一个消费者),咱们比较经常使用的是发布-订阅模式。 另外,这两种消息模型是 JMS 提供的,AMQP 协议还提供了 5 种消息模型。

三 使用消息队列带来的一些问题

  • 系统可用性下降: 系统可用性在某种程度上下降,为何这样说呢?在加入MQ以前,你不用考虑消息丢失或者说MQ挂掉等等的状况,可是,引入MQ以后你就须要去考虑了!
  • 系统复杂性提升: 加入MQ以后,你须要保证消息没有被重复消费、处理消息丢失的状况、保证消息传递的顺序性等等问题!
  • 一致性问题: 我上面讲了消息队列能够实现异步,消息队列带来的异步确实能够提升系统响应速度。可是,万一消息的真正消费者并无正确消费消息怎么办?这样就会致使数据不一致的状况了!

4 JMS VS AMQP

4.1 JMS

4.1.1 JMS 简介

    JMS(JAVA Message Service,java消息服务)是java的消息服务,JMS的客户端之间能够经过JMS服务进行异步的消息传输。JMS(JAVA Message Service,Java消息服务)API是一个消息服务的标准或者说是规范,容许应用程序组件基于JavaEE平台建立、发送、接收和读取消息。它使分布式通讯耦合度更低,消息服务更加可靠以及异步性。

ActiveMQ 就是基于 JMS 规范实现的。
4.1.2 JMS两种消息模型
①点到点(P2P)模型
点到点(P2P)模型
    使用队列(Queue)做为消息通讯载体;知足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留直到被消费或超时。好比:咱们生产者发送100条消息的话,两个消费者来消费通常状况下两个消费者会按照消息发送的顺序各自消费一半(也就是你一个我一个的消费。)
② 发布/订阅(Pub/Sub)模型
发布/订阅(Pub/Sub)模型
发布订阅模型(Pub/Sub) 使用主题(Topic)做为消息通讯载体,相似于广播模式;发布者发布一条消息,该消息经过主题传递给全部的订阅者,在一条消息广播以后才订阅的用户则是收不到该条消息的。
4.1.3 JMS 五种不一样的消息正文格式
JMS定义了五种不一样的消息正文格式,以及调用的消息类型,容许你发送并接收以一些不一样形式的数据,提供现有消息格式的一些级别的兼容性。
  • StreamMessage -- Java原始值的数据流
  • MapMessage--一套名称-值对
  • TextMessage--一个字符串对象
  • ObjectMessage--一个序列化的 Java对象
  • BytesMessage--一个字节的数据流
4.2 AMQP
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准 高级消息队列协议(二进制应用层协议),是应用层协议的一个开放标准,为面向消息的中间件设计,兼容 JMS。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品,不一样的开发语言等条件的限制。
RabbitMQ 就是基于 AMQP 协议实现的。
4.3 JMS vs AMQP
对比方向
JMS
AMQP
定义
Java API
协议
跨语言
跨平台
支持消息类型
提供两种消息模型:①Peer-2-Peer;②Pub/sub
提供了五种消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本质来说,后四种和JMS的pub/sub模型没有太大差异,仅是在路由机制上作了更详细的划分;
支持消息类型
支持多种消息类型 ,咱们在上面提到过
byte[](二进制)
总结:
  • AMQP 为消息定义了线路层(wire-level protocol)的协议,而JMS所定义的是API规范。在 Java 体系中,多个client都可以经过JMS进行交互,不须要应用修改代码,可是其对跨平台的支持较差。而AMQP自然具备跨平台、跨语言特性。
  • JMS 支持TextMessage、MapMessage 等复杂的消息类型;而 AMQP 仅支持 byte[] 消息类型(复杂的类型可序列化后发送)。
  • 因为Exchange 提供的路由算法,AMQP能够提供多样化的路由方式来传递消息到消息队列,而 JMS 仅支持 队列 和 主题/订阅 方式两种。

五 常见的消息队列对比

对比方向
概要
吞吐量
万级的 ActiveMQ 和 RabbitMQ 的吞吐量(ActiveMQ 的性能最差)要比 十万级甚至是百万级的 RocketMQ 和 Kafka 低一个数量级。
可用性
均可以实现高可用。ActiveMQ 和 RabbitMQ 都是基于主从架构实现高可用性。RocketMQ 基于分布式架构。 kafka 也是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会致使不可用
时效性
RabbitMQ 基于erlang开发,因此并发能力很强,性能极其好,延时很低,达到微秒级。其余三个都是 ms 级。
功能支持
除了 Kafka,其余三个功能都较为完备。 Kafka 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准
消息丢失
ActiveMQ 和 RabbitMQ 丢失的可能性很是低, RocketMQ 和 Kafka 理论上不会丢失。
总结:
  • ActiveMQ 的社区算是比较成熟,可是较目前来讲,ActiveMQ 的性能比较差,并且版本迭代很慢,不推荐使用。
  • RabbitMQ 在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,可是因为它基于 erlang 开发,因此并发能力很强,性能极其好,延时很低,达到微秒级。可是也由于 RabbitMQ 基于 erlang 开发,因此国内不多有公司有实力作erlang源码级别的研究和定制。若是业务场景对并发量要求不是过高(十万级、百万级),那这四种消息队列中,RabbitMQ 必定是你的首选。若是是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,况且几乎是全世界这个领域的事实性规范。
  • RocketMQ 阿里出品,Java 系开源项目,源代码咱们能够直接阅读,而后能够定制本身公司的MQ,而且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。RocketMQ 社区活跃度相对较为通常,不过也还能够,文档相对来讲简单一些,而后接口这块不是按照标准 JMS 规范走的有些系统要迁移须要修改大量代码。还有就是阿里出台的技术,你得作好这个技术万一被抛弃,社区黄掉的风险,那若是大家公司有技术实力我以为用RocketMQ 挺好的
  • kafka 的特色其实很明显,就是仅仅提供较少的核心功能,可是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,并且分布式能够任意扩展。同时 kafka 最好是支撑较少的 topic 数量便可,保证其超高吞吐量。kafka 惟一的一点劣势是有可能消息重复消费,那么对数据准确性会形成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响能够忽略这个特性自然适合大数据实时计算以及日志收集。
相关文章
相关标签/搜索