一文搞懂消息队列与选型(VIP典藏版)

一文搞懂消息队列与选型(VIP典藏版)Producer:消息生产者,负责产生和发送消息到Broker;Broker:消息处理中心,负责消息存储、确认、重试等,一般其中会包含多个Queue;Consumer:消息消费者,负责从Broker中获取消息,并进行相应处理。………

大家好,欢迎来到IT知识分享网。

目录

消息队列基础

什么是消息队列?

消息队列模式

点对点模式

发布/订阅模式

消息队列应用场景

异步处理

应用耦合

限流削峰

消息驱动的系统

常用消息队列

Kafka

重要概念

Kafka 架构

Kafka 工作原理

RocketMQ

重要概念

RocketMQ 工作原理

RocketMQ 架构

RabbitMQ

重要概念

RabbitMQ 工作原理

​编辑

常用交换器

消息队列对比

Kafka

优点

缺点

RocketMQ

优点

缺点

RabbitMQ

优点

缺点

消息队列选型

Kafka

RocketMQ

RabbitMQ

ActiveMQ

面试8连环

为什么要使用消息队列呢?(★★★★★)

为什么要选择RocketMQ?(★★★★)

如何保证消息的可用性/可靠性/不丢失呢?(★★★★★)

如何处理消息重复的问题呢?(★★★★★)

怎么处理消息积压?

怎么实现分布式消息事务的?半消息?(★★★)

如何保证RocketMQ的高可用?(★★★)

说一下RocketMQ的整体工作流程?(★★★)

参考资料

消息队列:

RabbitMQ

ActiveMQ

RocketMQ

Kafka

RabbitMQ/ActiveMQ/RocketMQ/Kafka对比


今天来聊下消息队列,消息队列中间件重要吗?当然重要了,我们不仅要知其然,更要知其所以然,本篇文章参考众多文章,加入面试常问问题,希望给大家带来帮助。

常用的消息队列主要这 4 种,分别为 Kafka、RocketMQ、RabbitMQ 和 ActiveMQ,这里主要介绍前三种,上思维导图!

一文搞懂消息队列与选型(VIP典藏版)

消息队列基础

什么是消息队列?

        消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以简单地描述为:

    当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。

消息队列主要解决了应用耦合、异步处理、流量削锋等问题

当前使用较多的消息队列有RabbitMQ、RocketMQKafka、ActiveMQ、ZeroMQ、MetaMq等,而部分数据库如Redis、Mysql以及phxsql也可实现消息队列的功能。

        是在消息的传输过程中保存消息的容器,用于接收消息并以文件的方式存储,一个消息队列可以被一个也可以被多个消费者消费,包含以下 3 元素:

  •     Producer:消息生产者,负责产生和发送消息到 Broker;
  •     Broker:消息处理中心,负责消息存储、确认、重试等,一般其中会包含多个 Queue;
  •     Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理。

一文搞懂消息队列与选型(VIP典藏版)

消息队列模式

点对点模式

多个生产者可以向同一个消息队列发送消息,一个具体的消息只能由一个消费者消费。

一文搞懂消息队列与选型(VIP典藏版)

发布/订阅模式

单个消息可以被多个订阅者并发的获取和处理。

一文搞懂消息队列与选型(VIP典藏版)

消息队列应用场景

    应用解耦:消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节。

    异步处理:消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息,多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间。

    限流削峰:当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的”载体”,在下游有能力处理的时候,再进行分发与处理。

    消息驱动的系统:系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理;

    日志处理:日志处理是指将消息队列用在日志处理中,比如 Kafka 的应用,解决大量日志传输的问题。

    消息通讯:消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯,比如实现点对点消息队列,或者聊天室等。

    消息广播:如果没有消息队列,每当一个新的业务方接入,我们都要接入一次新接口。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。

异步处理

具体场景:用户为了使用某个应用,进行注册,系统需要发送注册邮件并验证短信。对这两个操作的处理方式有两种:串行及并行。

(1)串行方式:新注册信息生成后,先发送注册邮件,再发送验证短信;

一文搞懂消息队列与选型(VIP典藏版)

在这种方式下,需要最终发送验证短信后再返回给客户端。

(2)并行处理:新注册信息写入后,由发短信和发邮件并行处理;

一文搞懂消息队列与选型(VIP典藏版)

在这种方式下,发短信和发邮件 需处理完成后再返回给客户端。

假设以上三个子系统处理的时间均为50ms,且不考虑网络延迟,则总的处理时间:

串行:50+50+50=150ms
并行:50+50 = 100ms

若使用消息队列:

一文搞懂消息队列与选型(VIP典藏版)

并在写入消息队列后立即返回成功给客户端,则总的响应时间依赖于写入消息队列的时间,而写入消息队列的时间本身是可以很快的,基本可以忽略不计,因此总的处理时间相比串行提高了2倍,相比并行提高了一倍;

应用耦合

具体场景:用户使用QQ相册上传一张图片,人脸识别系统会对该图片进行人脸识别,一般的做法是,服务器接收到图片后,图片上传系统立即调用人脸识别系统,调用完成后再返回成功,如下图所示:

一文搞懂消息队列与选型(VIP典藏版)

该方法有如下缺点:

  • 人脸识别系统被调失败,导致图片上传失败;
  • 延迟高,需要人脸识别系统处理完成后,再返回给客户端,即使用户并不需要立即知道结果;
  • 图片上传系统与人脸识别系统之间互相调用,需要做耦合;

若使用消息队列:

一文搞懂消息队列与选型(VIP典藏版)

客户端上传图片后,图片上传系统将图片信息如uin、批次写入消息队列,直接返回成功;而人脸识别系统则定时从消息队列中取数据,完成对新增图片的识别。
此时图片上传系统并不需要关心人脸识别系统是否对这些图片信息的处理、以及何时对这些图片信息进行处理。事实上,由于用户并不需要立即知道人脸识别结果,人脸识别系统可以选择不同的调度策略,按照闲时、忙时、正常时间,对队列中的图片信息进行处理。

限流削峰

具体场景:购物网站开展秒杀活动,一般由于瞬时访问量过大,服务器接收过大,会导致流量暴增,相关系统无法处理请求甚至崩溃。而加入消息队列后,系统可以从消息队列中取数据,相当于消息队列做了一次缓冲。

一文搞懂消息队列与选型(VIP典藏版)

该方法有如下优点:

  1. 请求先入消息队列,而不是由业务处理系统直接处理,做了一次缓冲,极大地减少了业务处理系统的压力;
  2. 队列长度可以做限制,事实上,秒杀时,后入队列的用户无法秒杀到商品,这些请求可以直接被抛弃,返回活动已结束或商品已售完信息;

消息驱动的系统

具体场景:用户新上传了一批照片, 人脸识别系统需要对这个用户的所有照片进行聚类,聚类完成后由对账系统重新生成用户的人脸索引(加快查询)。这三个子系统间由消息队列连接起来,前一个阶段的处理结果放入队列中,后一个阶段从队列中获取消息继续处理。

一文搞懂消息队列与选型(VIP典藏版)

该方法有如下优点:

  • 避免了直接调用下一个系统导致当前系统失败;
  • 每个子系统对于消息的处理方式可以更为灵活,可以选择收到消息时就处理,可以选择定时处理,也可以划分时间段按不同处理速度处理;

常用消息队列

由于官方社区现在对 ActiveMQ 5.x 维护越来越少,较少在大规模吞吐的场景中使用,所以我们主要讲解 Kafka、RabbitMQ 和 RocketMQ。

Kafka

Apache Kafka 最初由 LinkedIn 公司基于独特的设计实现为一个分布式的提交日志系统,之后成为 Apache 项目的一部分,号称大数据的杀手锏,在数据采集、传输、存储的过程中发挥着举足轻重的作用。

它是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。

重要概念

    主题(Topic):消息的种类称为主题,可以说一个主题代表了一类消息,相当于是对消息进行分类,主题就像是数据库中的表。

    分区(partition):主题可以被分为若干个分区,同一个主题中的分区可以不在一个机器上,有可能会部署在多个机器上,由此来实现 kafka 的伸缩性。

    批次:为了提高效率, 消息会分批次写入 Kafka,批次就代指的是一组消息。

    消费者群组(Consumer Group):消费者群组指的就是由一个或多个消费者组成的群体。

    Broker: 一个独立的 Kafka 服务器就被称为 broker,broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。

    Broker 集群:broker 集群由一个或多个 broker 组成。

    重平衡(Rebalance):消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。

Kafka 架构

一个典型的 Kafka 集群中包含 Producer、broker、Consumer Group、Zookeeper 集群。

Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 Consumer Group 发生变化时进行 rebalance。Producer 使用 push 模式将消息发布到 broker,Consumer 使用 pull 模式从 broker 订阅并消费消息。

一文搞懂消息队列与选型(VIP典藏版)

Kafka 工作原理

消息经过序列化后,通过不同的分区策略,找到对应的分区。

相同主题和分区的消息,会被存放在同一个批次里,然后由一个独立的线程负责把它们发到 Kafka Broker 上。

一文搞懂消息队列与选型(VIP典藏版)

分区的策略包括顺序轮询、随机轮询和 key hash 这 3 种方式,那什么是分区呢?

分区是 Kafka 读写数据的最小粒度,比如主题 A 有 15 条消息,有 5 个分区,如果采用顺序轮询的方式,15 条消息会顺序分配给这 5 个分区,后续消费的时候,也是按照分区粒度消费。

一文搞懂消息队列与选型(VIP典藏版)

由于分区可以部署在多个不同的机器上,所以可以通过分区实现 Kafka 的伸缩性,比如主题 A 的 5 个分区,分别部署在 5 台机器上,如果下线一台,分区就变为 4。

Kafka 消费是通过消费群组完成,同一个消费者群组,一个消费者可以消费多个分区,但是一个分区,只能被一个消费者消费。

一文搞懂消息队列与选型(VIP典藏版)

如果消费者增加,会触发 Rebalance,也就是分区和消费者需要重新配对。

不同的消费群组互不干涉,比如下图的 2 个消费群组,可以分别消费这 4 个分区的消息,互不影响。

一文搞懂消息队列与选型(VIP典藏版)

RocketMQ

RocketMQ 是阿里开源的消息中间件,它是纯 Java 开发,具有高性能、高可靠、高实时、适合大规模分布式系统应用的特点。

RocketMQ 思路起源于 Kafka,但并不是 Kafka 的一个 Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog 分发等场景。

重要概念

    Name 服务器(NameServer):充当注册中心,类似 Kafka 中的 Zookeeper。

    Broker: 一个独立的 RocketMQ 服务器就被称为 broker,broker 接收来自生产者的消息,为消息设置偏移量。

    主题(Topic):消息的第一级类型,一条消息必须有一个 Topic。

    子主题(Tag):消息的第二级类型,同一业务模块不同目的的消息就可以用相同 Topic 和不同的 Tag 来标识。

    分组(Group):一个组可以订阅多个 Topic,包括生产者组(Producer Group)和消费者组(Consumer Group)。

    队列(Queue):可以类比 Kafka 的分区 Partition。

RocketMQ 工作原理

RockerMQ 中的消息模型就是按照主题模型所实现的,包括 Producer Group、Topic、Consumer Group 三个角色。

为了提高并发能力,一个 Topic 包含多个 Queue,生产者组根据主题将消息放入对应的 Topic,下图是采用轮询的方式找到里面的 Queue。

RockerMQ 中的消费群组和 Queue,可以类比 Kafka 中的消费群组和 Partition:不同的消费者组互不干扰,一个 Queue 只能被一个消费者消费,一个消费者可以消费多个 Queue。

消费 Queue 的过程中,通过偏移量记录消费的位置。

一文搞懂消息队列与选型(VIP典藏版)

RocketMQ 架构

RocketMQ 技术架构中有四大角色 NameServer、Broker、Producer 和 Consumer,下面主要介绍 Broker。

Broker 用于存放 Queue,一个 Broker 可以配置多个 Topic,一个 Topic 中存在多个 Queue。

如果某个 Topic 消息量很大,应该给它多配置几个 Queue,并且尽量多分布在不同 broker 上,以减轻某个 broker 的压力。Topic 消息量都比较均匀的情况下,如果某个 broker 上的队列越多,则该 broker 压力越大。

一文搞懂消息队列与选型(VIP典藏版)

简单提一下,Broker 通过集群部署,并且提供了 master/slave 的结构,salve 定时从 master 同步数据(同步刷盘或者异步刷盘),如果 master 宕机,则 slave 提供消费服务,但是不能写入消息。

看到这里,大家应该可以发现,RocketMQ 的设计和 Kafka 真的很像!

RabbitMQ

RabbitMQ 2007 年发布,是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。

AMQP 的主要特征是面向消息、队列、路由、可靠性、安全。AMQP 协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

重要概念

    信道(Channel):消息读写等操作在信道中进行,客户端可以建立多个信道,每个信道代表一个会话任务。

    交换器(Exchange):接收消息,按照路由规则将消息路由到一个或者多个队列;如果路由不到,或者返回给生产者,或者直接丢弃。

    路由键(RoutingKey):生产者将消息发送给交换器的时候,会发送一个 RoutingKey,用来指定路由规则,这样交换器就知道把消息发送到哪个队列。

    绑定(Binding):交换器和消息队列之间的虚拟连接,绑定中可以包含一个或者多个 RoutingKey。

RabbitMQ 工作原理

AMQP 协议模型由三部分组成:生产者、消费者和服务端,执行流程如下:

  1.     生产者是连接到 Server,建立一个连接,开启一个信道。
  2.     生产者声明交换器和队列,设置相关属性,并通过路由键将交换器和队列进行绑定。
  3.     消费者也需要进行建立连接,开启信道等操作,便于接收消息。
  4.     生产者发送消息,发送到服务端中的虚拟主机。
  5.     虚拟主机中的交换器根据路由键选择路由规则,发送到不同的消息队列中。
  6.     订阅了消息队列的消费者就可以获取到消息,进行消费。

一文搞懂消息队列与选型(VIP典藏版)

常用交换器

RabbitMQ 常用的交换器类型有 direct、topic、fanout、headers 四种,具体的使用方法,可以参考官网:

https://www.rabbitmq.com/getstarted.html

一文搞懂消息队列与选型(VIP典藏版)

消息队列对比

一文搞懂消息队列与选型(VIP典藏版)

Kafka

优点

    高吞吐、低延迟:Kafka 最大的特点就是收发消息非常快,Kafka 每秒可以处理几十万条消息,它的最低延迟只有几毫秒;

    高伸缩性:每个主题(topic)包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中;

    高稳定性:Kafka 是分布式的,一个数据多个副本,某个节点宕机,Kafka 集群能够正常工作;

    持久性、可靠性、可回溯:Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,支持消息回溯;

    消息有序:通过控制能够保证所有消息被消费且仅被消费一次;

    有优秀的第三方 Kafka Web 管理界面 Kafka-Manager,在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点

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

    不支持消息路由,不支持延迟发送,不支持消息重试;

    社区更新较慢。

RocketMQ

优点

    高吞吐:借鉴 Kafka 的设计,单一队列百万消息的堆积能力;

    高伸缩性:灵活的分布式横向扩展部署架构,整体架构其实和 kafka 很像;

    高容错性:通过ACK机制,保证消息一定能正常消费;

    持久化、可回溯:消息可以持久化到磁盘中,支持消息回溯;

    消息有序:在一个队列中可靠的先进先出(FIFO)和严格的顺序传递;

    支持发布/订阅和点对点消息模型,支持拉、推两种消息模式;

    提供 docker 镜像用于隔离测试和云集群部署,提供配置、指标和监控等功能丰富的 Dashboard。

缺点

    不支持消息路由,支持的客户端语言不多,目前是 java 及 c++,其中 c++ 不成熟;

    部分支持消息有序:需要将同一类的消息 hash 到同一个队列 Queue 中,才能支持消息的顺序,如果同一类消息散落到不同的 Queue中,就不能支持消息的顺序。

    社区活跃度一般。

RabbitMQ

优点

    支持几乎所有最受欢迎的编程语言:Java,C,C ++,C#,Ruby,Perl,Python,PHP等等;

    支持消息路由:RabbitMQ 可以通过不同的交换器支持不同种类的消息路由;

    消息时序:通过延时队列,可以指定消息的延时时间,过期时间TTL等;

    支持容错处理:通过交付重试和死信交换器(DLX)来处理消息处理故障;

    提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker;

    社区活跃度高。

缺点

    Erlang 开发,很难去看懂源码,不利于做二次开发和维护,基本职能依赖于开源社区的快速维护和修复 bug;

    RabbitMQ 吞吐量会低一些,这是因为他做的实现机制比较重;

    不支持消息有序、持久化不好、不支持消息回溯、伸缩性一般。

消息队列选型

Kafka

        追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务,大型公司建议可以选用,如果有日志采集功能,肯定是首选 kafka。

RocketMQ

        天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RoketMQ 在稳定性上可能更值得信赖,这些业务场景在阿里双 11 已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择 RocketMQ。

RabbitMQ

        结合 erlang 语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护,不过 RabbitMQ 的社区十分活跃,可以解决开发过程中遇到的 bug。如果你的数据量没有那么大,小公司优先选择功能比较完备的 RabbitMQ。

ActiveMQ

        官方社区现在对 ActiveMQ 5.x 维护越来越少,较少在大规模吞吐的场景中使用。

面试8连环

为什么要使用消息队列呢?(★★★★★)

消息队列主要有三大用途,我们拿一个电商系统的下单举例:

    解耦:引入消息队列之前,下单完成之后,需要订单服务去调用库存服务减库存,调用营销服务加营销数据……引入消息队列之后,可以把订单完成的消息丢进队列里,下游服务自己去调用就行了,这样就完成了订单服务和其它服务的解耦合。

一文搞懂消息队列与选型(VIP典藏版)

    异步:订单支付之后,我们要扣减库存、增加积分、发送消息等等,这样一来这个链路就长了,链路一长,响应时间就变长了。引入消息队列,除了更新订单状态,其它的都可以异步去做,这样一来就来,就能降低响应时间。

    一文搞懂消息队列与选型(VIP典藏版)

    削峰:消息队列合一用来削峰,例如秒杀系统,平时流量很低,但是要做秒杀活动,秒杀的时候流量疯狂怼进来,我们的服务器,Redis,MySQL各自的承受能力都不一样,直接全部流量照单全收肯定有问题啊,严重点可能直接打挂了。

    我们可以把请求扔到队列里面,只放出我们服务能处理的流量,这样就能抗住短时间的大流量了。

    一文搞懂消息队列与选型(VIP典藏版)

    解耦、异步、削峰,是消息队列最主要的三大作用。

为什么要选择RocketMQ?(★★★★)

市场上几大消息队列对比如下:

一文搞懂消息队列与选型(VIP典藏版)

四大消息队列对比

总结一下:

选择中间件的可以从这些维度来考虑:可靠性,性能,功能,可运维行,可拓展性,社区活跃度。目前常用的几个中间件,ActiveMQ作为“老古董”,市面上用的已经不多,其它几种:

    RabbitMQ:

    优点:轻量,迅捷,容易部署和使用,拥有灵活的路由配置

    缺点:性能和吞吐量不太理想,不易进行二次开发

    RocketMQ:

        优点:性能好,高吞吐量,稳定可靠,有活跃的中文社区

        缺点:兼容性上不是太好

    Kafka:
        优点:拥有强大的性能及吞吐量,兼容性很好
        缺点:由于“攒一波再处理”导致延迟比较高

我们的系统是面向用户的C端系统,具有一定的并发量,对性能也有比较高的要求,所以选择了低延迟、吞吐量比较高,可用性比较好的RocketMQ。

如何保证消息的可用性/可靠性/不丢失呢?(★★★★★)

消息可能在哪些阶段丢失呢?可能会在这三个阶段发生丢失:生产阶段、存储阶段、消费阶段。

所以要从这三个阶段考虑:

一文搞懂消息队列与选型(VIP典藏版)
生产

在生产阶段,主要通过请求确认机制,来保证消息的可靠传递。

    1、同步发送的时候,要注意处理响应结果和异常。如果返回响应OK,表示消息成功发送到了Broker,如果响应失败,或者发生其它异常,都应该重试。
    2、异步发送的时候,应该在回调方法里检查,如果发送失败或者异常,都应该进行重试。
    3、如果发生超时的情况,也可以通过查询日志的API,来检查是否在Broker存储成功。

存储

存储阶段,可以通过配置可靠性优先的 Broker 参数来避免因为宕机丢消息,简单说就是可靠性优先的场景都应该使用同步。

    1、消息只要持久化到CommitLog(日志文件)中,即使Broker宕机,未消费的消息也能重新恢复再消费。
    2、Broker的刷盘机制:同步刷盘和异步刷盘,不管哪种刷盘都可以保证消息一定存储在pagecache中(内存中),但是同步刷盘更可靠,它是Producer发送消息后等数据持久化到磁盘之后再返回响应给Producer。

一文搞懂消息队列与选型(VIP典藏版)

    3、Broker通过主从模式来保证高可用,Broker支持Master和Slave同步复制、Master和Slave异步复制模式,生产者的消息都是发送给Master,但是消费既可以从Master消费,也可以从Slave消费。同步复制模式可以保证即使Master宕机,消息肯定在Slave中有备份,保证了消息不会丢失。

消费

从Consumer角度分析,如何保证消息被成功消费?

    Consumer保证消息成功消费的关键在于确认的时机,不要在收到消息后就立即发送消费确认,而是应该在执行完所有消费业务逻辑之后,再发送消费确认。因为消息队列维护了消费的位置,逻辑执行失败了,没有确认,再去队列拉取消息,就还是之前的一条。

如何处理消息重复的问题呢?(★★★★★)

对分布式消息队列来说,同时做到确保一定投递和不重复投递是很难的,就是所谓的“有且仅有一次” 。 RocketMQ择了确保一定投递,保证消息不丢失,但有可能造成消息重复。

处理消息重复问题,主要有业务端自己保证,主要的方式有两种:业务幂等和消息去重。

消息重复处理

业务幂等:第一种是保证消费逻辑的幂等性,也就是多次调用和一次调用的效果是一样的。这样一来,不管消息消费多少次,对业务都没有影响。

消息去重:第二种是业务端,对重复的消息就不再消费了。这种方法,需要保证每条消息都有一个惟一的编号,通常是业务相关的,比如订单号,消费的记录需要落库,而且需要保证和消息确认这一步的原子性。

具体做法是可以建立一个消费记录表,拿到这个消息做数据库的insert操作。给这个消息做一个唯一主键(primary key)或者唯一约束,那么就算出现重复消费的情况,就会导致主键冲突,那么就不再处理这条消息。

怎么处理消息积压?

发生了消息积压,这时候就得想办法赶紧把积压的消息消费完,就得考虑提高消费能力,一般有两种办法:

一文搞懂消息队列与选型(VIP典藏版)

    消费者扩容:如果当前Topic的Message Queue的数量大于消费者数量,就可以对消费者进行扩容,增加消费者,来提高消费能力,尽快把积压的消息消费玩。
    消息迁移Queue扩容:如果当前Topic的Message Queue的数量小于或者等于消费者数量,这种情况,再扩容消费者就没什么用,就得考虑扩容Message Queue。可以新建一个临时的Topic,临时的Topic多设置一些Message Queue,然后先用一些消费者把消费的数据丢到临时的Topic,因为不用业务处理,只是转发一下消息,还是很快的。接下来用扩容的消费者去消费新的Topic里的数据,消费完了之后,恢复原状。

一文搞懂消息队列与选型(VIP典藏版)

怎么实现分布式消息事务的?半消息?★★★

半消息:是指暂时还不能被 Consumer 消费的消息,Producer 成功发送到 Broker 端的消息,但是此消息被标记为 “暂不可投递” 状态,只有等 Producer 端执行完本地事务后经过二次确认了之后,Consumer 才能消费此条消息。

依赖半消息,可以实现分布式消息事务,其中的关键在于二次确认以及消息回查:

一文搞懂消息队列与选型(VIP典藏版)

    1、Producer 向 broker 发送半消息

    2、Producer 端收到响应,消息发送成功,此时消息是半消息,标记为 “不可投递” 状态,Consumer 消费不了。

    3、Producer 端执行本地事务。

    4、正常情况本地事务执行完成,Producer 向 Broker 发送 Commit/Rollback,如果是 Commit,Broker 端将半消息标记为正常消息,Consumer 可以消费,如果是 Rollback,Broker 丢弃此消息。

    5、异常情况,Broker 端迟迟等不到二次确认。在一定时间后,会查询所有的半消息,然后到 Producer 端查询半消息的执行情况。

    6、Producer 端查询本地事务的状态

    7、根据事务的状态提交 commit/rollback 到 broker 端。(5,6,7 是消息回查)

    8、消费者段消费到消息之后,执行本地事务,执行本地事务。

如何保证RocketMQ的高可用?★★★

NameServer因为是无状态,且不相互通信的,所以只要集群部署就可以保证高可用。

一文搞懂消息队列与选型(VIP典藏版)

RocketMQ的高可用主要是在体现在Broker的读和写的高可用,Broker的高可用是通过集群和主从实现的。

一文搞懂消息队列与选型(VIP典藏版)

Broker可以配置两种角色:Master和Slave,Master角色的Broker支持读和写,Slave角色的Broker只支持读,Master会向Slave同步消息。

也就是说Producer只能向Master角色的Broker写入消息,Cosumer可以从Master和Slave角色的Broker读取消息。

Consumer 的配置文件中,并不需要设置是从 Master 读还是从 Slave读,当 Master 不可用或者繁忙的时候, Consumer 的读请求会被自动切换到从 Slave。有了自动切换 Consumer 这种机制,当一个 Master 角色的机器出现故障后,Consumer 仍然可以从 Slave 读取消息,不影响 Consumer 读取消息,这就实现了读的高可用。

如何达到发送端写的高可用性呢?在创建 Topic 的时候,把 Topic 的多个Message Queue 创建在多个 Broker 组上(相同 Broker 名称,不同 brokerId机器组成 Broker 组),这样当 Broker 组的 Master 不可用后,其他组Master 仍然可用, Producer 仍然可以发送消息 RocketMQ 目前还不支持把Slave自动转成 Master ,如果机器资源不足,需要把 Slave 转成 Master ,则要手动停止 Slave 色的 Broker ,更改配置文件,用新的配置文件启动 Broker。

原理

说一下RocketMQ的整体工作流程?★★★

简单来说,RocketMQ是一个分布式消息队列,也就是消息队列+分布式系统。

作为消息队列,它是发-存-收的一个模型,对应的就是Producer、Broker、Cosumer;作为分布式系统,它要有服务端、客户端、注册中心,对应的就是Broker、Producer/Consumer、NameServer

所以我们看一下它主要的工作流程:RocketMQ由NameServer注册中心集群、Producer生产者集群、Consumer消费者集群和若干Broker(RocketMQ进程)组成:

    Broker在启动的时候去向所有的NameServer注册,并保持长连接,每30s发送一次心跳

    Producer在发送消息的时候从NameServer获取Broker服务器地址,根据负载均衡算法选择一台服务器来发送消息

    Conusmer消费消息的时候同样从NameServer获取Broker地址,然后主动拉取消息来消费

一文搞懂消息队列与选型(VIP典藏版)

参考资料

消息队列:

  1. 大型网站架构之分布式消息队列 大型网站架构之分布式消息队列_bing.shao的博客-CSDN博客
  2. 消息队列的使用场景 消息队列的使用场景是怎样的? – 知乎
  3. 浅谈异步消息队列模型 浅谈异步消息队列模型 – Sunkey – 博客园
  4. 消息队列的两种模式 消息队列的两种模式_和大黄的博客-CSDN博客_消息队列

RabbitMQ

  1. RabbitMQ主页 Messaging that just works — RabbitMQ
  2. RabbitMQ学习教程 RabbitMQ Tutorials — RabbitMQ
  3. 专栏:RabbitMQ从入门到精通 http://blog.csdn.net/column/details/rabbitmq.html
  4. RabbitMQ能为你做些什么 RabbitMQ能为你做些什么? · RabbitMQ in Chinese
  5. RabbitMQ指南(1)-特性及功能 RabbitMQ指南(1)-特性及功能 – 子暃之路

ActiveMQ

  1. ActiveMQ主页 ActiveMQ
  2. Apache ActiveMQ介绍 http://jfires.iteye.com/blog/1187688
  3. ActiveMQ的简介与安装 ActiveMQ的简介与安装_LifeIsForSharing的博客-CSDN博客
  4. ActiveMQ 和消息简介 ActiveMQ 和消息简介 – clearbug – 博客园

RocketMQ

  1. 主页 https://github.com/alibaba/RocketMQ
  2. RocketMQ 原理简介 http://alibaba.github.io/RocketMQ-docs/document/design/RocketMQ_design.pdf
  3. RocketMQ与kafka对比(18项差异) http://jm.taobao.org/2016/03/24/rmq-vs-kafka/

Kafka

1.Kafka主页: Apache Kafka

  1. Kafka特性 Kafka特性 – Uncle_Nucky – 博客园
  2. Kafka客户端支持语言 Clients – Apache Kafka – Apache Software Foundation

RabbitMQ/ActiveMQ/RocketMQ/Kafka对比

  1. RocketMQ,队列选型 http://www.zmannotes.com/index.php/2016/01/17/rocketmq/
  2. RabbitMQ和Kafka http://www.dongcoder.com/detail-416804.html
  3. 即时通信RabbitMQ二-性能测试 http://www.jianshu.com/p/d31ae9e3bfb6
  4. RabbitMq、ActiveMq、ZeroMq、kafka之间的比较,资料汇总 RabbitMq、ActiveMq、ZeroMq、kafka之间的比较,资料汇总_Sam_Deep_Thinking的博客-CSDN博客
  5. 消息队列软件产品大比拼 消息队列软件产品大比拼 – amityat – 博客园
  6. 面渣逆袭:RocketMQ二十三问

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/21762.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信