【消息队列】消息中间件介绍

电商系统引发的思考

实现支付业务时使用串行操作(同步)

在这里插入图片描述

串行操作存在的问题

  1. 耦合度高:每次加入新的需求,都要修改原来的代码
  2. 性能下降:调用者需要等待服务提供者响应,如果调用链过长则响应时间等于每次调用的时间之和。
  3. 资源浪费:调用链中的每个服务在等待响应过程中,不能释放请求占用的资源,高并发场景下会极度浪费系统资源
  4. 级联失败:如果服务提供者出现问题,所有调用方都会跟着出问题,如同多米诺骨牌一样,迅速导致整个微服务群故障

根据上述的几个问题,在设计系统时可以明确要达到的目标

  • 要做到系统解耦,当新的模块接进来时,可以做到代码改动最小;能够解耦
  • 设置流量缓冲池,可以让后端系统按照自身吞吐能力进行消费,不被冲垮;能削峰
  • 强弱依赖梳理,能将非关键调用链路的操作异步化并提升整体系统的吞吐能力;

MQ可以解决以上问题

消息中间件【MQ(Message Queue)】

  • 消息中间件也可以称消息队列(Message Queue / MQ),用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。
  • 消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。
  • 简而言之,互联网场景中经常使用消息中间件进行消息路由、订阅发布、异步处理等操作,来缓解系统的压力。

在这里插入图片描述

  • MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据结构。一般用来解决 应用解耦,异步提速,流量削峰 等问题,实现高性能,高可用,可伸缩和最终一致性架构。
  • 我们把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。用于上下游传递消息。
  • 在互联网架构中,MQ 是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。使用了 MQ 之后,消息发送上游只需要依赖 MQ,不用依赖其他服务。

使用场景

1.应用解耦

  • 一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。
    在这里插入图片描述

2.异步提速

  • 性能提升,吞吐量提高,主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。
    在这里插入图片描述

3.流量削峰

  • 高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。

举个栗子

  • 如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。
  • 但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。
  • 使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。

在这里插入图片描述

4. 服务没有强依赖,不担心级联失败问题

在这里插入图片描述

MQ的优点和缺点

优点

  1. 解耦:一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。
  2. 异步:主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。
  3. 削峰:高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。

缺点

  1. 系统可用性降低。依赖服务也多,服务越容易挂掉。需要考虑MQ瘫痪的情况
  2. 系统复杂性提高。要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等
  3. 业务一致性。主业务和从属业务一致性的处理

MQ的消息通讯模型

  • MQ的消息通信模型:实现MQ的大致有两种主流方式:JMS、AMQP

JMS

  • JMS即Java消息服务(JavaMessage Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间或分布式系统中发送消息,进行异步通信。
  • JMS限定了必须使用Java语言。 JMS是定义了统一的接口,来对消息操作进行统一;

AMQP

  • AMQP是高级消息队列协议,是一个进程间传递异步消息的网络协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。
  • AMQP只是协议,不规定实现方式,因此是跨语言的。

MQ常用协议

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的功能。

MQ的通讯模式

点对点通讯

  • 点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。

多点广播

  • MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。
  • 可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。
  • MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。
  • 目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。

发布/订阅(Publish/Subscribe)模式

  • 发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。
  • 发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。
  • 在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。

集群(Cluster)

  • 为了简化点对点通讯模式中的系统配置,MQ提供 Cluster 的解决方案。
  • 集群类似于一个 域(Domain) ,集群内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用 Cluster 通道与其它成员通讯,从而大大简化了系统配置。
  • 此外,集群中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性

多线程异步和消息队列的区别

  • CPU消耗。多线程异步可能存在CPU竞争,而MQ不会消耗本机的CPU。
  • MQ 方式实现异步是完全解耦的,适合于大型互联网项目。
  • 削峰或者消息堆积能力。当业务系统处于高并发,MQ可以将消息堆积在Broker实例中,而多线程会创建大量线程,甚至触发拒绝策略。
  • 使用MQ引入了中间件,增加了项目复杂度和运维难度。

总的来说,规模比较小的项目可以使用多线程实现异步,大项目建议使用MQ实现异步

作用不同

  • 消息队列主要是用于不同模块或线程之间的数据传输和通信;线程队列则是用于线程的调度和管理。

结构不同

  • 消息队列的数据结构是先进先出(FIFO)的队列,数据按照时间顺序存储;线程队列则是以优先级作为依据的队列,根据线程的优先级进行排序,优先级高的线程先被执行。

使用场景不同

  • 消息队列通常被用于多线程编程中,将数据从一个线程传递到另一个线程,例如生产者消费者模型、线程池等场景;线程队列则是被用于线程调度的场景,例如操作系统调度线程、线程池等。

消息队列如何保证数据不丢失

持久化存储

  • 消息队列可以将消息存储在磁盘上,以便在故障发生时仍然能够恢复数据。
  • 当消息被接收并处理后,消息队列会将其从磁盘中删除。

确认机制

  • 消息队列提供了一种确认机制,即当消费者成功接收并处理一条消息时,会向消息队列发送一个确认消息,告诉消息队列该消息已经被成功处理。
  • 只有当消息被确认后,消息队列才会将其删除,确保消息不会丢失。

重试机制

  • 当消费者无法处理某条消息时,消息队列可以将该消息重新发送给消费者,直到消息被成功处理。
  • 这种重试机制可以确保消息不会因为一次处理失败而丢失。

高可用性

  • 消息队列通常会使用分布式架构,使得即使其中某些节点发生故障,整个系统仍然可以保持可用性,从而确保消息不会丢失。

数据备份

  • 消息队列还可以将消息备份到多个节点上,以防某个节点发生故障导致数据丢失。

主流的MQ产品

ActiveMQ

  • ActiveMQ 是Apache出品,功能强大的即时通讯和集成模式的开源服务器。
  • ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。

使用场景

ActiveMQ 采用消息推送方式,所以最适合的场景是默认消息都可在短时间内被消费。数据量越大,查找和消费消息就越慢,消息积压程度与消息速度成反比。

优点

  • 非常成熟,功能强大,在业内大量的公司以及项目中都有应用

缺点

  • 官方社区现在对 ActiveMQ 5.x 维护越来越少。
  • 偶尔会有较低概率丢失消息。
  • 而且确实主要是基于解耦和异步来用的,较少在大规模吞吐的场景中使用

RabbitMQ

  • 2007 年发布,是一个在 AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。
  • 社区:https://www.rabbitmq.com/news.html

优点

  • 由于 erlang 语言的高并发特性,性能较好;吞吐量到万级
  • MQ 功能比较完备,健壮、稳定、易用、跨平台、支持多种语言 如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持 AJAX 文档齐全;
  • 开源提供的管理界面非常棒,用起来很好用社区相对比较活跃,几乎每个月都发布几个版本;
  • 更新频率相当高;
  • 事务性好,常应用于金融领域的事务控制
    在这里插入图片描述

缺点

  • 商业版需要收费,学习成本较高
  • RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重。
  • 而且erlang开发,国内有几个公司有实力做erlang源码级别的研究和定制?如果说你没这个实力的话确实偶尔会有一些问题,你公司对这个东西的掌控很弱,基本只能依赖于开源社区的快速维护和修复bug。
  • 而且rabbitMQ集群动态扩展会很麻烦,不过这个我觉得还好。其实主要是erlang语言本身带来的问题。很难读源码,很难定制和掌控

RocketMQ

  • RocketMQ 出自阿里巴巴的开源产品,用 Java 语言实现,在设计时参考了 Kafka,并做出了自己的一些改进。被阿里巴巴广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理等场景。

优点

  • 接口简单易用,而且毕竟在阿里大规模应用过,有阿里品牌保障

  • 日处理消息上百亿之多,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便

  • 消息可以做到 0 丢失,MQ 功能较为完善,还是分布式的,扩展性好

  • 支持 10 亿级别的消息堆积,不会因为堆积导致性能下降

  • 还可以支持大规模的topic数量,支持复杂MQ场景。

  • 而且一个很大的优势在于,阿里出品都是java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控

  • 补充:社区活跃度相对一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准JMS规范走的,有些系统迁移要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的

缺点

  • 支持的客户端语言不多,目前是 java 及 c++,其中 c++不成熟;
  • 社区活跃度一般,没有在 MQ核心中去实现 JMS 等接口,有些系统要迁移需要修改大量代码

Kafka

  • 大数据的杀手锏,谈到大数据领域内的消息传输,则绕不开 Kafka,这款为大数据而生的消息中间件,以其百万级 TPS 的吞吐量名声大噪,迅速成为大数据领域的宠儿,在数据采集、传输、存储的过程中发挥着举足轻重的作用。

优点:

  • 性能卓越,单机写入 TPS 约在百万条/秒,最大的优点,就是吞吐量高。
  • 时效性 ms 级可用性非常高,kafka 是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用,
  • 消费者采用 Pull 方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;
  • 有优秀的第三方Kafka Web 管理界面 Kafka-Manager;在日志领域比较成熟。
  • 同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量

缺点

  • Kafka 单机超过 64 个队列/分区,Load 会发生明显的飙高现象,队列越多,load 越高,发送消息响应时间变长
  • 使用短轮询方式,实时性取决于轮询间隔时间,消费失败不支持重试;
  • 支持消息顺序,但是一台代理宕机后,就会产生消息乱序,社区更新较慢
  • 有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略。这个特性天然适合大数据实时计算以及日志收集

面试题:kafka、activemq、rabbitmq、rocketmq有什么优缺点

特性 ActiveMQ RabbitMQ RocketMQ Kafka
单机吞吐量 万级,吞吐量比RocketMQ和Kafka要低一个数量级 万级,吞吐量比RocketMQ和Kafka要低一个数量级 10万级,RocketMQ也是可以支撑高吞吐的一个MQ 10万级,这是kafka最大的优点就是吞吐量高。一般配合大数据类的系统来进行实时数据计算、日志采集等场景
topic数量对吞吐量的影响 topic可以达到几百,几千个的级别吞吐量会有较小幅度的下降这是RocketMQ的一大优势可以支撑大量的topic topic从几十个到几百个的时候吞吐量会大幅度的下降所以在同等机器下,Kafka尽量保证topic的数量不要过多。如果要支撑大规模的topic,需要增加更多的机器资源
时效性 ms级 微秒级,这是rabbitMQ的一大特点,延迟是最低的 ms级 延迟在ms级以内
可用性 高,基于主从架构实现高可用性 高,基于主从架构实现高 可用性非常高,分布式架构 非常高,Kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
消息的可靠性 有较低的概率丢失数据 一般不丢消息 经过参数优化配置,可以做到0丢失 经过参数优化配置,可以做到0丢失
功能支持 MQ领域的功能极其完备 基于erlang开发,所以并发能力很强,性能极其好,扩展性好 MQ功能比较完善,还是分布式的扩展性好 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准

RabbitMQ的组成部分

在这里插入图片描述

Broker

  • 接收和分发消息的应用,消息队列服务进程,此进程包括两个部分:Exchange和Queue。
  • RabbitMQ Server就是Message Broker。

Virtual Host

  • 虚拟主机,用于逻辑隔离。
  • 一个虚拟主机里面可以有若干个Exchange和Queue,同一个虚拟主机里面不能有相同名称的Exchange或Queue。

Exchange

  • 消息交换机,作用是接收来自生产者的消息,并根据路由键转发消息到所绑定的队列。

Queue

  • 即队列,RabbitMQ内部用于存储消息的对象,是真正用存储消息的结构,在生产端,生产者的消息最终发送到指定队列,而消费者也是通过订阅某个队列,达到获取消息的目的。

Binding

  • Binding是一种操作,其作用是建立消息从Exchange转发到Queue的规则
  • 在进行Exchange与Queue的绑定时,需要指定一个BindingKey
  • Binding操作一般用于RabbitMQ的路由工作模式和主题工作模式。

Connection

  • Connection就是一个TCP的连接,Producer和Consumer都是通过TCP连接到RabbitMQ Server的。

Channel

  • 信道,多路复用连接中的一条独立的双向数据流通道。
  • 是建立在上述的TCP连接中,因为建立TCP Connection的开销将是巨大的,所以其是为了节省Rabbitmq开销。

Producer

  • 消息生产者,即生产方客户端,生产方客户端将消息发送

Consumer

  • 消息消费者,即消费方客户端,接收MQ转发的消息

相关推荐

  1. 消息队列&中间

    2024-05-12 01:26:05       46 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-12 01:26:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-12 01:26:05       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-12 01:26:05       87 阅读
  4. Python语言-面向对象

    2024-05-12 01:26:05       96 阅读

热门阅读

  1. 设计模式——命令模式(Command)

    2024-05-12 01:26:05       37 阅读
  2. 软件测试概述

    2024-05-12 01:26:05       37 阅读
  3. Spring aop切面编程

    2024-05-12 01:26:05       32 阅读
  4. Spring中的DigestUtils:数据摘要的艺术与实用

    2024-05-12 01:26:05       35 阅读
  5. 简站WordPress主题

    2024-05-12 01:26:05       39 阅读
  6. QT 设置窗口不透明度

    2024-05-12 01:26:05       35 阅读