zoukankan      html  css  js  c++  java
  • 消息队列介绍

    什么是消息队列?

      Queue(队列),这个词在《数据结构》的课程中出现过,即先进先出的一中数据结构,形象例子就是简单的铁路隧道和排队机;和Queue对应的就是stack(栈),Stack是一种先进后出的数据结构;如果看中文书,还有一个名词用于混,就是heap(堆),这个也很形象,进出是没有顺序的,就像煤堆。

    在计算机科学中,Message Queue(MQ)消息队列,就是按顺序传递消息的一种技术

    MQ一般都做为企业级IT应用的中间件存在,有很多企业是作为标准IT基础结构存在的。在市面上常见的MQ中间件有IBM websphere message queue service,Oracle Advanced Queuing,Microsoft Message Queue(MSMQ),Apache ActiveMQ等,其中apache ActiveMQ是基于apache协议的,和tomcat一样,你可以在项目中免费使用,MSMQ是Windows的组件,默认是不被安装的,可以在“添加/删除组件”中安装MSMQ(不同版本的Windows对应的MSMQ版本是不同的,XP/2003是3.0,Vista是4.0)。

    队列允许你存储元数据在稍后的日期处理作业。 他们可以在SOA(面向服务架构)的发展,通过提供灵活的任务交由独立的进程帮助。 如果应用得当,队列可以通过减少加载时间大大提高网站的用户体验。

    消息队列的优点:

    • 异步:即接收和发送方可以在不同的线程、进程或机器上,发送成功的同时,也不需要接收方立即接收;
    • 去耦:将应用程序的逻辑。
    • 韧性:如果它的一部分失败不会记下你的整个应用程序。
    • 冗余:如果他们失败可以重试作业。
    • 担保:当消息发送成功时,你就可以确定接收方一定能接收到;MQ会使用某种技术(文件系统、数据库)将消息保存起来;
    • 可扩展性:许多工人可以在队列中处理个别工作。
    • 剖析:可帮助确定性能问题。

    消息队列的缺点:

    • 异步:你必须等待,直到作业完成。
    • 负载:每个队列中的作业必须等待轮到它,然后才能进行处理。 如果一个作业超支,它影响每个后续的工作。
    • 架构:应用程序需要进行设计时考虑到队列中。

    使用消息队列的情况:

    任何耗时的过程可以被放置在队列中,主要场景就是异步处理:

    • 发送/来自第三方的API接收数据
    • 发送电子邮件
    • 生成报告
    • 运行劳工密集的工序

    消息队列的应用场景:

    1. 异步处理:例如短信通知、邮件发送、终端状态推送、App推送、用户注册等
    2. 数据同步:业务数据推送同步(支付系统收款之后业务系统更新金额等)
    3. 重试补偿:记账失败重试
    4. 系统解耦:通讯上下行、终端异常监控、分布式事件中心
    5. 流量消峰:秒杀场景下的下单处理
    6. 发布订阅:HSF的服务状态变化通知、分布式事件中心
    7. 高并发缓冲:日志服务、监控上报

    消息队列的一些基本概念和简单原理

    1. Broker

    Broker的概念来自与Apache ActiveMQ,通俗的讲就是MQ的服务器。

    2. 消息的生产者、消费者

    消息生产者Producer:发送消息到消息队列。

    消息消费者Consumer:从消息队列接收消息。

    3. 点对点消息队列模型

    消息生产者向一个特定的队列发送消息,消息消费者从该队列中接收消息;消息的生产者和消费者可以不同时处于运行状态。

    每一个成功处理的消息都由消息消费者签收确认(Acknowledge)。如图:

    4. 发布订阅消息模型-Topic

    发布订阅消息模型中,支持向一个特定的主题Topic发布消息,0个或多个订阅者接收来自这个消息主题的消息。在这种模型下,发布者和订阅者彼此不知道对方。实际操作过程中,

    必须先订阅,再发送消息,而后接收订阅的消息,这个顺序必须保证。

    5. 消息的顺序性保证

    基于Queue消息模型,利用FIFO先进先出的特性,可以保证消息的顺序性。

    6. 消息的ACK确认机制

    即消息的Ackownledge确认机制,为了保证消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。如果Consumer宕机/关闭,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的Consumer重新消费处理。

    7. 消息的持久化

    消息的持久化,对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。

    8. 消息的同步和异步收发

    同步:消息的收发支持同步收发的方式。

    同时还有另一种同步方式:同步收发场景下,消息生产者和消费者双向应答模式,例如:张三写封信送到邮局中转站,然后李四从中转站获得信,然后在写一份回执信,放到中转站,然后张三去取,当然张三写信的时候就得写明回信地址

    消息的接收如果以同步的方式(Pull)进行接收,如果队列中为空,此时接收将处于同步阻塞状态,会一直等待,直到消息的到达。

    异步:消息的收发同样支持异步方式:异步发送消息,不需要等待消息队列的接收确认;异步接收消息,以Push的方式触发消息消费者接收消息。

    9. 消息的事务支持

    消息的收发处理支持事务,例如:在任务中心场景中,一次处理可能涉及多个消息的接收、处理,这处于同一个事务范围内,如果一个消息处理失败,事务回滚,消息重新回到队列中。

    使用消息队列的10个理由

      过去几年中,我们一直在使用、构建和宣传消息队列,我们认为它们是很令人敬畏的,这也不是什么秘密。我们相信对任何架构或应用来说,消息队列都是一个至关重要的组件,下面是十个理由:

    1. 解耦

      消息队列在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

    2. 冗余

      有时在处理数据的时候处理过程会失败。除非数据被持久化,否则将永远丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。在被许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。

    3. 扩展性

      因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的;只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。

    4. 灵活性 & 峰值处理能力

      当你的应用上了Hacker News的首页,你将发现访问流量攀升到一个不同寻常的水平。在访问量剧增的情况下,你的应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃。请查看我们关于峰值处理能力的博客文章了解更多此方面的信息。

    5. 可恢复性

      当体系的一部分组件失效,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。而这种允许重试或者延后处理请求的能力通常是造就一个略感不便的用户和一个沮丧透顶的用户之间的区别。

    6. 送达保证

      消息队列提供的冗余机制保证了消息能被实际的处理,只要一个进程读取了该队列即可。在此基础上,IronMQ提供了一个"只送达一次"保证。无论有多少进程在从队列中领取数据,每一个消息只能被处理一次。这之所以成为可能,是因为获取一个消息只是"预定"了这个消息,暂时把它移出了队列。除非客户端明确的表示已经处理完了这个消息,否则这个消息会被放回队列中去,在一段可配置的时间之后可再次被处理。

    7.排序保证

      在许多情况下,数据处理的顺序都很重要。消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。IronMO保证消息浆糊通过FIFO(先进先出)的顺序来处理,因此消息在队列中的位置就是从队列中检索他们的位置。

    8.缓冲

      在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行--写入队列的处理会尽可能的快速,而不受从队列读的预备处理的约束。该缓冲有助于控制和优化数据流经过系统的速度。

    9. 理解数据流

      在一个分布式系统里,要得到一个关于用户操作会用多长时间及其原因的总体印象,是个巨大的挑战。消息系列通过消息被处理的频率,来方便的辅助确定那些表现不佳的处理过程或领域,这些地方的数据流都不够优化。

    10. 异步通信

      很多时候,你不想也不需要立即处理消息。消息队列提供了异步处理机制,允许你把一个消息放入队列,但并不立即处理它。你想向队列中放入多少消息就放多少,然后在你乐意的时候再去处理它们。

    我们相信上述十个原因,使得消息队列成为在进程或应用之间进行通信的最好形式。我们已经花费了一年时间来创建和学习IronMQ,我们的客户也通过消息队列完成了许多不可思议的事情。队列是创建强大的分布式应用的关键,它可以利用云技术所提供的所有强大能量。

  • 相关阅读:
    leetcode 122. Best Time to Buy and Sell Stock II
    leetcode 121. Best Time to Buy and Sell Stock
    python 集合(set)和字典(dictionary)的用法解析
    leetcode 53. Maximum Subarray
    leetcode 202. Happy Number
    leetcode 136.Single Number
    leetcode 703. Kth Largest Element in a Stream & c++ priority_queue & minHeap/maxHeap
    [leetcode]1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree
    正则表达式
    十种排序算法
  • 原文地址:https://www.cnblogs.com/peterYong/p/11142749.html
Copyright © 2011-2022 走看看