消息队列(MQ)

一、 消息队列(MQ)

消息队列(Message Queue)在互联网公司使用的越来越多,主要用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息队列实现系统之间的双向解耦,生产者往消息队列中发送消息,消费者从队列中拿取消息并处理,生产者不用关心是谁来消费,消费者不用关心谁在生产消息,从而达到系统解耦的目的,也大大提高了系统的高可用性和高并发能力。

目前在生产环境,使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、RocketMQ等。

二、 工作模式

2.1 点对点模式

每个消息只有一个消费者(Consumer),一旦被消费,便从消息队列中删除。

发送者和消费者间没有依赖性,发送者发送消息后,不管有没有消费者,并不会影响下一次发送消息。

2.2 发布订阅模式

每个消息可以有多个订阅者;每个订阅者都可以接收到主题的所有消息;

生产者依然不会关心有没有消费者,只管发送消息。

两种模型区别:一份消息是否能被多次消费;如果发布订阅模式只有一个订阅者,那么两个模型基本一样;所以发布订阅模型在功能层面是兼容点对点模式的;

三、 MQ应用场景

消息队列的应用场景较多,以前三个最为典型:

  • 1.异步处理

  • 2.应用解耦

  • 3.流量削锋

  • 4.消息通讯

  • 5.排序保证

3.1 异步处理

假定用户注册后,需要发注册邮件和注册短信给注册用户,传统的做法有两种

  • 1、串行的方式;

  • 2、并行的方式 ;

(1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西。

(2)并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。

假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。

虽然并性已经提高的处理时间,但是,前面说过邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入数据库后就返回。

(3)消息队列:引入消息队列后,把发送邮件、短信不是必须的业务逻辑进行异步处理。

由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。

3.2 应用解耦

假定双11购物节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口。

不过这种做法有一个缺点:订单系统和库存系统高耦合。当库存系统出现故障时,订单就会失败。

引入消息队列后:

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:订阅下单的消息,获取下单消息,进行库操作。就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失。


 

3.3 流量削峰

流量削峰一般在秒杀活动中应用广泛。

秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。

一般有两个作用:

  • 1、可以控制活动人数,超过此一定阀值的订单直接丢弃

  • 2、可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单)

1、用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面。

2、秒杀业务根据消息队列中的请求信息,慢慢做后续处理即可。

 

4 消息队列缺点

  1. 系统可用性降低:系统引入的外部依赖越多,越容易挂掉。本来就是 A 系统调用 BCD 三个系统的接口就好了,原本ABCD 四个系统好好的,没啥问题。你把加个 MQ 进来了 ,让A发布消息,BCD订阅消息,如果 MQ 出问题了呢?BCD的功能就都不会执行了。

  2. 系统复杂度提高:需要保证,消费者有没有重复消费信息?重要信息丢失怎么办?信息需要有先后顺序怎么办?一系列的问题都需要考虑并解决,此时业务逻辑的复杂度就上来了。

  3. 一致性问题:你访问 A 系统,处理完后给你返回成功,同时向消息队列发布信息,但这时你已经收到处理结果了,以为成功了。但如果 BCD 三个系统收到信息后,它们之间有的处理失败的,这时ABCD的数据就不一致了。

所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,系统复杂度提升了一个数量级,也许是复杂了 10 倍。

合理的使用消息队列,确实会给系统带来很大的优势。但也并不是所有的系统都适合加入消息队列。

5 常用消息中间件

5.1 ZeroMQ

ZeroMQ号称是“史上最快的消息队列”,基于c语言开发的,可以在任何平台通过任何代码连接,通过inproc、IPC、TCP、TIPC、多播传送消息,支持发布-订阅、推-拉、共享队列等模式,高速异步I/O引擎。

根据官方的说法,ZeroMQ是一个简单好用的传输层,像框架一样的可嵌入的socket类库,使Socket编程更加简单、简洁、性能更高,是专门为高吞吐量/低延迟的场景开发的。ZeroMQ与其他MQ有着本质的区别,它根本不是消息队列服务器,更类似与一个底层网络通讯库,对原有Socket API进行封装,在使用的时候引入对应的jar包即可,可谓是相当灵活。

同时,因为它的简单灵活,如果我们想作为消息队列使用的话,需要开发大量代码。而且,ZeroMQ不支持消息持久化,其定位并不是安全可靠的消息传输,所以还需要自己编码保证可靠性。简而言之一句话,ZeroMQ很强大,但是想用好需要自己实现。

5.2 Rabbitmq

RabbitMQ 2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。

主要特性:

  1. 可靠性: 提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性机制、投递确认、发布者证实和高可用性机制;

  2. 灵活的路由: 消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,你甚至可以实现自己的交换机类型,并且当做RabbitMQ的插件来使用;

  3. 消息集群:在相同局域网中的多个RabbitMQ服务器可以聚合在一起,作为一个独立的逻辑代理来使用;

  4. 队列高可用:队列可以在集群中的机器上进行镜像,以确保在硬件问题下还保证消息安全;

  5. 多种协议的支持:支持多种消息队列协议;

  6. 多语言支持:服务器端用Erlang语言编写,支持只要是你能想到的所有编程语言;

  7. 管理界面: RabbitMQ有一个易用的用户界面,使得用户可以监控和管理消息Broker的许多方面;

  8. 跟踪机制:如果消息异常,RabbitMQ提供消息跟踪机制,使用者可以找出发生了什么;

  9. 插件机制:提供了许多插件,来从多方面进行扩展,也可以编写自己的插件;

优点:

  1. RabbitMQ 使用erlang语言开发,由于erlang语言的特性,mq 性能较好,高并发;

  2. 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;

  3. 有消息确认机制和持久化机制,可靠性高;

  4. 高度可定制的路由;

  5. 管理界面较丰富,在互联网公司也有较大规模的应用;

  6. 社区活跃度高;

缺点:

    1. 尽管结合erlang语言本身的并发优势,性能较好,但是不利于做二次开发和维护;

    2. 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;

    3. 需要学习比较复杂的接口和协议,学习和维护成本较高;

5.3 ActiveMQ

ActiveMQ介于ZeroMQ和RabbitMQ之间。类似于ZeroMQ,它可以部署于代理模式和P2P(点对点)模式。类似于RabbitMQ,它易于实现高级场景,而且只需付出低消耗。被誉为消息中间件的“瑞士军刀”。

支持OpenWire、Stomp、AMQP v1.0、MQTT v3.1、REST、Ajax、Webservice等多种协议;完全支持JMS1.1和J2EE 1.4规范(事务、持久化、XA消息);支持持久化到数据库。但是ActiveMQ不够轻巧,而且对于队列较多的情况支持不好,据说还有丢消息的情况。

目前已经有了其下一代消息产品Apollo。

Apache称Apollo为最快、最强健的STOMP服务器。支持STOMP、AMQP、MQTT、OpenWire协议,支持Topic、Queue、持久订阅等消费形式,支持对消息的多种处理,支持安全性处理,支持REST管理API。。。功能列表很长,最大的弊病就是目前市场接收度不够,所以使用的并不广泛。

STOMP:简单"流"文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。

5.4 kafka

Apache Kafka是一个分布式消息发布订阅系统。它最初由LinkedIn公司基于独特的设计实现为一个分布式的提交日志系统( a distributed commit log),之后成为Apache项目的一部分。Kafka系统快速、可扩展并且可持久化。它的分区特性,可复制和可容错都是其不错的特性。

主要特性:

  1. 快速持久化,可以在O(1)的系统开销下进行消息持久化;

  2. 高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;

  3. .完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;

  4. 支持同步和异步复制两种HA;

  5. 支持数据批量发送和拉取;

  6. zero-copy:减少IO操作步骤;

  7. 数据迁移、扩容对用户透明;

  8. 无需停机即可扩展机器;

  9. 其他特性:严格的消息顺序、丰富的消息拉取模型、高效订阅者水平扩展、实时的消息订阅、亿级的消息堆积能力、定期删除机制;

优点:

  1. 客户端语言丰富,支持java、.net、php、ruby、python、go等多种语言;

  2. 性能卓越,单机写入TPS约在百万条/秒,消息大小10个字节;

  3. 提供完全分布式架构, 并有replica机制, 拥有较高的可用性和可靠性, 理论上支持消息无限堆积;

  4. 支持批量操作;

  5. 消费者采用Pull方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;

  6. 有优秀的第三方Kafka Web管理界面Kafka-Manager;

  7. 在日志领域比较成熟,被多家公司和多个开源项目使用;

缺点:

  1. Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长

  2. 使用短轮询方式,实时性取决于轮询间隔时间;

  3. 消费失败不支持重试;

  4. 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;

  5. 社区更新较慢;

5.5 RocketMQ

RocketMQ 是阿里巴巴在 2012 年开源的消息队列产品,用 Java 语言实现,在设计时参考了 Kafka,并做出了自己的一些改进,后来捐赠给 Apache 软件基金会,2017 正式毕业,成为 Apache 的顶级项目。RocketMQ 在阿里内部被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,Binglog 分发等场景。经历过多次双十一考验,它的性能、稳定性和可靠性都是值得信赖的。

RocketMQ 有着不错的性能,稳定性和可靠性,具备一个现代的消息队列应该有的几乎全部功能和特性,并且它还在持续的成长中。

RocketMQ 有非常活跃的中文社区,大多数问题可以找到中文的答案。RocketMQ 使用 Java 语言开发,源代码相对比较容易读懂,容易对 RocketMQ 进行扩展或者二次开发。

RocketMQ 对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,如果你的应用场景很在意响应时延,那应该选择使用 RocketMQ。

RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。

RocketMQ 的劣势是与周边生态系统的集成和兼容程度不够。

5.6 对比总结

根据上面的对比得出以下结论:

1)、中小型软件公司,建议选RabbitMQ

因为erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。正所谓,成也萧何,败也萧何!他的弊端也在这里,虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要

不考虑kafka的原因是,中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除

不考虑rocketmq的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐

2)、大型软件公司,根据具体使用在rocketMQ和kafka之间二选一

大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对rocketMQ,大型软件公司也可以抽出人手对rocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人,还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。具体该选哪个,看使用场景。

  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值