功能特性:
应用场景:
消息队列 MQ 可应用于如下几个场景:
分布式事务
在传统的事务处理中,多个系统之间的交互耦合到一个事务中,响应时间长,影响系统可用性。引入分布式事务消息,交易系统和消息队列之间,组成一个事务处理,能保证分布式系统之间数据的最终一致。;下游业务系统(购物车、积分、其他)相互隔离,并行处理。
实时计算
通过消息队列(MQ),将源端不停产生的数据实时流入到计算引擎,实现实时计算。可采用如下计算引擎:Spark / Storm / EMR / ARMS / BeamRunner。
物联网应用
物联网设备通过微消息队列(LMQ)连接云端,双向通信,数据传输;设备数据通过消息队列(MQ)连接计算引擎,分析数据或者源数据实时高效写入到 HiTSDB / HiStore / ODPS 等。
大规模缓存同步
在商业大促活动中,如“双11”大促,各个分会场会有琳琅满目的商品,每件商品的价格都会实时变化;同时,大量并发访问商品数据库,会场页面响应时间长。集中式缓存,带宽成瓶颈,无法满足对商品价格的访问需求。
消息队列(MQ)能够通过大规模缓存同步,减少页面响应时间;针对分会场的多缓存设计,满足客户对商品价格的访问需求。
名词解释
本文主要对 MQ 涉及的专有名词及术语进行定义和解析,方便您更好地理解相关概念并使用 MQ。
Message Queue
消息队列,阿里云商用的专业消息中间件,是企业级互联网架构的核心产品,提供基于高可用分布式集群技术搭建的消息发布订阅、轨迹查询、资源统计、定时(延时)、监控报警等一系列消息云服务。
Message
消息,消息队列中信息传递的载体。
Message ID
消息的全局唯一标识,由 MQ 系统自动生成,唯一标识某条消息。
Message Key
消息的业务标识,由消息生产者(Producer)设置,唯一标识某个业务逻辑。
Topic
消息主题,一级消息类型,通过 Topic 对消息进行分类。
Tag
消息标签,二级消息类型,用来进一步区分某个 Topic 下的消息分类。
Producer
消息生产者,也称为消息发布者,负责生产并发送消息。
Producer ID
一类 Producer 的标识,这类 Producer 通常生产并发送一类消息,且发送逻辑一致。
Producer 实例
Producer 的一个对象实例,不同的 Producer 实例可以运行在不同进程内或者不同机器上。Producer 实例线程安全,可在同一进程内多线程之间共享。
Consumer
消息消费者,也称为消息订阅者,负责接收并消费消息。
Consumer ID
一类 Consumer 的标识,这类 Consumer 通常接收并消费一类消息,且消费逻辑一致。
Consumer 实例
Consumer 的一个对象实例,不同的 Consumer 实例可以运行在不同进程内或者不同机器上。一个 Consumer 实例内配置线程池消费消息。
集群消费
一个 Consumer ID 所标识的所有 Consumer 平均分摊消费消息。例如某个 Topic 有 9 条消息,一个 Consumer ID 有 3 个 Consumer 实例,那么在集群消费模式下每个实例平均分摊,只消费其中的 3 条消息。
广播消费
一个 Consumer ID 所标识的所有 Consumer 都会各自消费某条消息一次。例如某个 Topic 有 9 条消息,一个 Consumer ID 有 3 个 Consumer 实例,那么在广播消费模式下每个实例都会各自消费 9 条消息。
定时消息
Producer 将消息发送到 MQ 服务端,但并不期望这条消息立马投递,而是推迟到在当前时间点之后的某一个时间投递到 Consumer 进行消费,该消息即定时消息。
延时消息
Producer 将消息发送到 MQ 服务端,但并不期望这条消息立马投递,而是延迟一定时间后才投递到 Consumer 进行消费,该消息即延时消息。
事务消息
MQ 提供类似 X/Open XA 的分布事务功能,通过 MQ 事务消息能达到分布式事务的最终一致。
顺序消息
MQ 提供的一种按照顺序进行发布和消费的消息类型, 分为全局顺序消息和分区顺序消息。
顺序发布
对于指定的一个 Topic,客户端将按照一定的先后顺序进行发送消息。
顺序消费
对于指定的一个 Topic,按照一定的先后顺序进行接收消息,即先发送的消息一定会先被客户端接收到。
全局顺序消息
对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。
分区顺序消息
对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 key 是完全不同的概念。
消息堆积
Producer 已经将消息发送到 MQ 服务端,但由于 Consumer 消费能力有限,未能在短时间内将所有消息正确消费掉,此时在 MQ 服务端保存着未被消费的消息,该状态即消息堆积。
消息过滤
订阅者可以根据消息标签(Tag)对消息进行过滤,确保订阅者最终只接收被过滤后的消息类型。消息过滤在 MQ 服务端完成。
消息轨迹
在一条消息从发布者发出到订阅者消费处理过程中,由各个相关节点的时间、地点等数据汇聚而成的完整链路信息。通过消息轨迹,用户能清晰定位消息从发布者发出,经由 MQ 服务端,投递给消息订阅者的完整链路,方便定位排查问题。
重置消费位点
以时间轴为坐标,在消息持久化存储的时间范围内(默认3天),重新设置消息订阅者对其订阅 Topic 的消费进度,设置完成后订阅者将接收设定时间点之后由消息发布者发送到 MQ 服务端的消息。
 
集群消费和广播消费:
本文档主要介绍 MQ 集群消费和广播消费的基本概念,适用场景以及注意事项。
基本概念
MQ 是基于发布订阅模型的消息系统。在 MQ 消息系统中消息的订阅方订阅关注的 Topic,以获取并消费消息。由于订阅方应用一般是分布式系统,以集群方式部署有多台机器。因此 MQ 约定以下概念。
集群:MQ 约定使用相同 Consumer ID 的订阅者属于同一个集群,同一个集群下的订阅者消费逻辑必须完全一致(包括 Tag 的使用),这些订阅者在逻辑上可以认为是一个消费节点。
集群消费:当使用集群消费模式时,MQ 认为任意一条消息只需要被集群内的任意一个消费者处理即可。
广播消费:当使用广播消费模式时,MQ 会将每条消息推送给集群内所有注册过的客户端,保证消息至少被每台机器消费一次。
场景对比
集群消费模式:
适用场景&注意事项
  • 消费端集群化部署,每条消息只需要被处理一次。
  • 由于消费进度在服务端维护,可靠性更高。
  • 集群消费模式下,每一条消息都只会被分发到一台机器上处理,如果需要被集群下的每一台机器都处理,请使用广播模式。
  • 集群消费模式下,不保证消息的每一次失败重投等逻辑都能路由到同一台机器上,因此处理消息时不应该做任何确定性假设。
 
广播消费模式:
适用场景&注意事项
  • 顺序消息暂不支持广播消费模式。
  • 每条消息都需要被相同逻辑的多台机器处理。
  • 消费进度在客户端维护,出现重复的概率稍大于集群模式。
  • 广播模式下,MQ 保证每条消息至少被每台客户端消费一次,但是并不会对消费失败的消息进行失败重投,因此业务方需要关注消费失败的情况。
  • 广播模式下,第一次启动时默认从最新消息消费,客户端的消费进度是被持久化在客户端本地的隐藏文件中,因此不建议删除该隐藏文件,否则会丢失部分消息。
  • 广播模式下,每条消息都会被大量的客户端重复处理,因此推荐尽可能使用集群模式。
  • 目前仅 Java 客户端支持广播模式。
  • 广播模式下服务端不维护消费进度,所以 MQ 控制台不支持消息堆积查询和堆积报警功能。
使用集群模式模拟广播:
如果业务需要使用广播模式,也可以创建多个 Consumer ID,用于订阅同一个 Topic。
适用场景&注意事项
  • 每条消息都需要被多台机器处理,每台机器的逻辑可以相同也可以不一样。
  • 消费进度在服务端维护,可靠性高于广播模式。
  • 一个云账户所能创建的 Consumer ID 数量是有限制的,具体可以咨询售后技术支持。
  • 对于一个 Consumer ID 来说,可以部署一个消费端实例,也可以部署多个消费端实例。当部署多个消费端实例时,实例之间又组成了集群模式(共同分担消费消息)。假设 Consumer ID1 部署了三个消费者实例 C1,C2,C3,那么这三个实例将共同分担服务器发送给 Consumer ID1 的消息。同时,实例之间订阅关系必须保持一致。
 
消息过滤:
本文描述 MQ 消费者如何根据 Tag 在 MQ 服务端完成消息过滤。
Tag,即消息标签、消息类型,用来区分某个 MQ 的 Topic 下的消息分类。MQ 允许消费者按照 Tag 对消息进行过滤,确保消费者最终只消费到他关心的消息类型。
以下图电商交易场景为例,从客户下单到收到商品这一过程会生产一系列消息,比如订单创建消息(order)、支付消息(pay)、物流消息(logistics)。这些消息会发送到 Topic 为 Trade_Topic 的队列中,被各个不同的系统所接收,比如支付系统、物流系统、交易成功率分析系统、实时计算系统等。其中,物流系统只需接收物流类型的消息(logistics),而实时计算系统需要接收所有和交易相关(order、pay、logistics)的消息。
说明:针对消息归类,您可以选择创建多个 Topic, 或者在同一个 Topic 下创建多个 Tag。但通常情况下,不同的 Topic 之间的消息没有必然的联系,而 Tag 则用来区分同一个 Topic 下相互关联的消息,比如全集和子集的关系,流程先后的关系。
参考示例
发送消息
发送消息时,每条消息必须指明消息类型 Tag:
Message msg = new Message("MQ_TOPIC","TagA","Hello MQ".getBytes());
消费方式-1
消费者如需订阅某 Topic 下所有类型的消息,Tag 用符号 * 表示:
consumer.subscribe("MQ_TOPIC", "*", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
消费方式-2
消费者如需订阅某 Topic 下某一种类型的消息,请明确标明 Tag:
consumer.subscribe("MQ_TOPIC", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
消费方式-3
消费者如需订阅某 Topic 下多种类型的消息,请在多个 Tag 之间用 || 分隔:
consumer.subscribe("MQ_TOPIC", "TagA||TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
消费方式-4(错误示例)
同一个消费者多次订阅某 Topic 下的不同 Tag,后者会覆盖前者:
//如下错误代码中,consumer 只能接收到 MQ_TOPIC 下 TagB 的消息,而不能接收 TagA 的消息。
consumer.subscribe("MQ_TOPIC", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
consumer.subscribe("MQ_TOPIC", "TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
订阅关系一致:
MQ 里的一个 Consumer ID 代表一个 Consumer 实例群组。对于大多数分布式应用来说,一个 Consumer ID 下通常会挂载多个 Consumer 实例。订阅关系一致指的是同一个 Consumer ID 下所有 Consumer 实例的处理逻辑必须完全一致。一旦订阅关系不一致,消息消费的逻辑就会混乱,甚至导致消息丢失。
由于 MQ 的订阅关系主要由 Topic+Tag 共同组成,因此,保持订阅关系一致意味着同一个 Consumer ID 下所有的实例需在以下两方面均保持一致:
  1. 订阅的 Topic 必须一致;
  2. 订阅的 Topic 中的 Tag 必须一致。
如上图所示,一个 Consumer ID 也可以订阅多个 Topic,但是这个 Consumer ID 里的多个消费者实例的订阅关系一定要保持一致。
下文给出了订阅关系不一致的错误代码示例。
【例一】以下例子中,同一个 Consumer ID 下的两个实例订阅的 Topic 不一致。
Consumer 实例 1-1:
Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, "CID_jodie_test_1");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_A", "*", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});

Consumer 实例1-2:

Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, " CID_jodie_test_1");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_B ", "*", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
【例二】以下例子中,同一个 Consumer ID 下订阅 Topic 的 Tag 不一致。Consumer 实例2-1 订阅了 TagA,而 Consumer 实例2-2 未指定 Tag。
Consumer 实例2-1:
Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, "CID_jodie_test_2");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_A", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});

Consumer 实例2-2:

Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, " CID_jodie_test_2");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_A ", "*", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
【例三】此例中,错误的原因有俩个:
  1. 同一个 Consumer ID 下订阅 Topic 个数不一致。
  2. 同一个 Consumer ID 下订阅 Topic 的 Tag 不一致。
Consumer 实例3-1:
Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, "CID_jodie_test_3");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_A", "TagA", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});
consumer.subscribe("jodie_test_B", "TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});

Consumer 实例3-2:

Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, " CID_jodie_test_3");
Consumer consumer = ONSFactory.createConsumer(properties);
consumer.subscribe("jodie_test_A ", "TagB", new MessageListener() {
public Action consume(Message message, ConsumeContext context) {
System.out.println(message.getMsgID());
return Action.CommitMessage;
}
});

消息队列 MQ 入门理解的更多相关文章

  1. 详解RPC远程调用和消息队列MQ的区别

    PC(Remote Procedure Call)远程过程调用,主要解决远程通信间的问题,不需要了解底层网络的通信机制. RPC框架 知名度较高的有Thrift(FB的).dubbo(阿里的). RP ...

  2. ActiveMQ消息队列从入门到实践(4)—使用Spring JMS收发消息

    Java消息服务(Java Message Service ,JMS)是一个Java标准,定义了使用消息代理的通用API .在JMS出现之前,每个消息代理都有私有的API,这就使得不同代理之间的消息代 ...

  3. 高可用服务 AHAS 在消息队列 MQ 削峰填谷场景下的应用

    在消息队列中,当消费者去消费消息的时候,无论是通过 pull 的方式还是 push 的方式,都可能会出现大批量的消息突刺.如果此时要处理所有消息,很可能会导致系统负载过高,影响稳定性.但其实可能后面几 ...

  4. 高并发系统:消息队列MQ

    注:前提是知道什么是消息队列.不懂的去搜索各种消息队列入门(activeMQ.rabbitMQ.rocketMQ.kafka) 1.为什么要使用MQ?(MQ的好处:解耦.异步.削峰) (1)解耦:主要 ...

  5. 为什么会需要消息队列(MQ)?

    为什么会需要消息队列(MQ)? #################################################################################### ...

  6. 消息队列一:为什么需要消息队列(MQ)?

    为什么会需要消息队列(MQ)? #################################################################################### ...

  7. 消息队列MQ简介

    项目中要用到RabbitMQ,领导让我先了解一下.在之前的公司中,用到过消息队列MQ,阿里的那款RocketMQ,当时公司也做了简单的技术分享,自己也看了一些博客.自己在有道云笔记上,做了一些整理,但 ...

  8. 消息队列MQ集合

    消息队列MQ集合 消息队列简介 kafka简介 Centos7部署zookeeper和Kafka集群 .

  9. java面试记录三:hashmap、hashtable、concurrentHashmap、ArrayList、linkedList、linkedHashmap、Object类的12个成员方法、消息队列MQ的种类

    口述题 1.HashMap的原理?(数组+单向链表.put.get.size方法) 非线程安全:(1)hash冲突:多线程某一时刻同时操作hashmap并执行put操作时,可能会产两个key的hash ...

随机推荐

  1. Java NIO系列教程(四) Scatter 和 Gather

    Java NIO系列教程(四) Scatter 和 Gather Java NIO 开始支持 scatter/gather,scatter/gather 用于描述从 Channel(译者注:Chann ...

  2. 如何删除win8自带输入法

    如何删除 win8 自带输入法 win8 自带的那个中文输入法太坑了,想删又删不了.试了半个小时才试出一个方法.方法如下: 第一步:在更改语言道选项下面点击[添加语言] [控制面板] -> [时 ...

  3. 【原型实战】分分钟搞定Unsplash网站原型设计

    网站原型设计是我们在设计网页过程中必不可少的一步,激烈的市场竞争让我们不得不对产品进行快速迭代,如何高速有效的进行原型设计成为了设计师头疼的问题.本文将以unsplash网站为实例,教大家快速搞定we ...

  4. 这样的UI UX设计师描述你满意吗?

    UI/UX 设计师是我们耳熟能详的名称,但是这些红遍大江南北的设计师到底是什么鬼? 今天小编跟大家好好分享一些关于UI UX 设计师的描述,让大家搞清楚两者的含义和职责.全文主要分成UI设计师描述和U ...

  5. webapp的优化总结

    1. 最先加载本地数据,下拉刷新再取最新数据. 2. 图片延后加载.一种方法先<div data-url="xx.png"></div>,先加载一个div, ...

  6. 2018.10.15 NOIP训练 hyc的等比数列(数论+枚举)

    传送门 一道不错的枚举题. 显然桶排序之后瞎枚举一波. 考虑枚举首项和末项,假设首项除去一个最大的平方因子得到的结果为xxx. 那么末项一定等于xxx乘上一个平方数. 于是我们枚举首项,算出xxx然后 ...

  7. 2018.09.16 bzoj1086: [SCOI2005]王室联邦(贪心)

    传送门 就是给树分块. 对于一个节点. 如果它的几棵子树加起来超过了下限,就把它们分成一块. 这样每次可能会剩下几个节点. 把它们都加入栈中最顶上那一块就行了. 代码: #include<bit ...

  8. HDU 2561 第二小整数 (排序)

    题意:中文题. 析:输入后,排一下序就好. 代码如下: #include <iostream> #include <cstdio> #include <algorithm ...

  9. java基础-day5

    第05天 java基础知识 今日内容介绍 u 方法的概述及基本使用 u 方法的练习及注意事项 u 方法的重载及参数传递 u 方法的操作数组的练习 第1章   方法的概述及基本使用 1.1  方法定义格 ...

  10. DUBBO配置规则详解

    研究DUBBO也已经大半年了,对它的大部分源码进行了分析,以及对它的内部机制有了比较深入的了解,以及各个模块的实现.DUBBO包含很多内容,如果想了解DUBBO第一步就是启动它,从而可以很好的使用它, ...