消息队列(Message Queue)

引言

上几篇博客简单的讲述了 go 语言连接 kafka,以及写 mysql 操作过程。但是对于初学者而言,可能仅仅是知道 mysql 是一个数据库,对 kafka 则一头雾水。其实 kafka 是一个比较常用的消息队列(Message Queue,MQ),在本篇博客中,将消息队列进行说明。

消息队列

消息队列作为中间件,是分布式应用间交换信息的重要组件。消息队列可驻留在内存或磁盘上, 队列可以存储消息直到它们被应用程序读走。通过消息队列,应用程序可以在不知道彼此位置的情况下独立处理消息,或者在处理消息前不需要等待接收此消息。所以消息队列可以解决应用解耦、异步消息、流量削锋等问题,是实现高性能、高可用、可伸缩和最终一致性架构中不可以或缺的一环。下面对消息队列就直接使用MQ表示。

消息队列常用的使用场景:

  • 非实时性:当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。主要解决了应用耦合、异步处理、流量削锋等问题。
  • 应用耦合:多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败。(如:订单->库存)
  • 异步处理:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间。(点对多场景,广播场景(注册发短信,发邮件)等等)
  • 限流削峰:应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况;(根据服务承受度设置队列大小,超过了就返回活动结束了,咱们经常各大商城秒杀,心里还没有点B数吗)减少压力,避免服务挂掉。
  • 消息驱动的系统:系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理。(分工处理(各自对应相应的队列),灵活应用(收到就处理/定时处理))

消息队列是异步RPC(远过程调用)的主要手段之一。有两种模式:

  1. 点对点:每个消息只有一个消费者(Consumer),不可重复消费(一旦被消费,消息就不再在消息队列中)
  2. 发布/订阅:微信公众号(Topic),大伙(订阅者)订阅关注之后,微信公众号运营平台(发布者)发布信息后,大伙微信就都收到信息了,这里其实还分pull/push的。一个是主动推送,一个是被动拉取

基于发布/订阅模式做扩展就是横向扩展,多个队列及消费分组订阅(提高消费能力)。

  • pull:主动权在于消费方,优点是按需消费,而且服务端队列堆积的消息处理也相对简单;缺点就是消息延迟;
  • push:主动权就在服务方了,优点是实时性高,服务端可以统一管理来进行负载,不过也容易导致慢消费;缺点就是发送消息的状态是集中式管理,压力大

对于顺序消息,这种场景有限且成本太高的方式就得慎重考虑,对那种全局有序但允许出现小误差的场景(日志推送),pull模式就非常适合了

常用消息队列

在比较常见的消息队列产品主要是 ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ,当然还有很多其他的产品。

常用消息队列对比

1、ZeroMQ

ZeroMQ 基于 C 开发,号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZeroMQ 能够实现 RabbitMQ 不擅长的高级 / 复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这 MQ 能够应用成功的挑战。ZeroMQ 具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用 ZeroMQ 程序库,可以使用 NuGet 安装,然后你就可以愉快的在应用程序之间发送消息了。但是 ZeroMQ 仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。其中,Twitter 的 Storm 0.9.0 以前的版本中默认使用 ZeroMQ 作为数据流的传输(Storm 从 0.9 版本开始同时支持 ZeroMQ 和 Netty 作为传输模块)。

2、 RabbitMQ

RabbitMQ 是使用 Erlang 编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。同时实现了 Broker 构架,这意味着消息在发送给客户端时先在中心队列排队。对路由,负载均衡或者数据持久化都有很好的支持。

3、ActiveMQ

ActiveMQ 是 Apache 出品的、采用Java语言编写的完全基于JMS1.1规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。ActiveMQ 是 Apache 下的一个子项目。 类似于 ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于 RabbitMQ,它少量代码就可以高效地实现高级应用场景。

支持OpenWire、Stomp、AMQP v1.0、MQTT v3.1、REST、Ajax、Webservice等多种协议;完全支持JMS1.1和J2EE 1.4规范(事务、持久化、XA消息);支持持久化到数据库。但是ActiveMQ不够轻巧,而且对于队列较多的情况支持不好。目前市场份额没有后面三种消息中间件多,其最新架构被命名为 Apollo。

4、Apollo

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

5、kafka

Kafka 基于 Scala 和 Java 开发,是 Apache 下的一个子项目,是一个高性能跨语言分布式发布 / 订阅消息队列系统,而 Jafka 是在 Kafka 之上孵化而来的,即 Kafka 的一个升级版。具有以下特性:快速持久化,可以在 O(1) 的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到 10W/s 的吞吐速率;完全的分布式系统,Broker、Producer、Consumer 都原生自动支持分布式,自动实现负载均衡;支持 Hadoop 数据并行加载,对于像 Hadoop 的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka 通过 Hadoop 的并行加载机制统一了在线和离线的消息处理。Apache Kafka 相对于 ActiveMQ 是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。

6、RocketMQ

RocketMQ 基于 Java开发,是阿里开源的消息中间件,目前在 Apache 孵化,使用 Java 开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ 思路起源于 Kafka,但并不是简单的复制,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog 分发等场景,支撑了阿里多次双十一活动。

因为是阿里内部从实践到产品的产物,因此里面很多接口、api并不是很普遍适用。其可靠性毋庸置疑,而且与Kafka一脉相承,性能强劲,支持海量堆积。

7、Redis

Redis 是一个基于 Key-Value 对的 NoSQL 数据库,开发维护很活跃。虽然它是一个 Key-Value 数据库存储系统,但它本身支持 MQ 功能,所以完全可以当做一个轻量级的队列服务来使用。

选型

实际开发中消息中间件选型基于几个方面:

  1. 功能:优先级队列、延迟队列、死信队列、消费模式 (pull/push)、广播消费、消息回溯、消息堆积+持久化、消息追踪、消息过滤、多协议支持、跨语言支持、流量控制、消息顺序性、安全机制、消息幂等性等等。
  2. 性能:一般是指其吞吐量(统一大小的消息体和不同大小的消息体生产和消耗能力),性能和功能很多时候是相悖的,要有取舍。
  3. 高可靠、高可用:高可靠,主要在于消息的持久化。如果是从系统的角度来看就得从整体的维度去衡量。高可用,主要在于一个是对外部服务的依赖性,依赖也分强依赖和弱依赖,一个在于本身的备份机制所带来的保障性。
  4. 运维:通常有审核评估、监控、报警提醒、容灾、扩容、升级部署等等,一方面看中间件支撑的维度,一方面就看结合自动化运维的难易度。
  5. 社区力度及生态发展:使用开源框架总会掉坑里,一方面需要自身的实力,另一方面需要社区的支持和整个生态环境的发展状态。
  6. 成本: 尽量贴合团队自身的技术栈体系。

结语

目前,消息队列产品的种类繁多,而且每一种都在某一领域占有一席之地。

开发人员在选用消息队列的时候,应当根据团队的技术战体系和业务的场景,慎重选择适合的消息队列。

参考链接

https://blog.csdn.net/liuxinghao/article/details/60875715
https://juejin.im/post/5b32044ef265da59654c3027

猜你喜欢

转载自blog.csdn.net/bingfeilongxin/article/details/87775276