1.1 消息队列基础篇(1-3)

前言:

此文章是在学习极客时间消息队列高手课程的时候整理而来,做了一点扩展,主要目的是方便复习扩展,还是建议去看原课程,讲的很好。


01 | 为什么需要消息队列?

主要功能:收发消息,解决应用之间的通信问题。

哪些问题适合使用消息队列来解决?

1、异步处理

例如秒杀处理中确定本次请求的秒杀结果后,就可以马上给用户返回响应,然后把请求的数据放入消息队列中,由消息队列异步地进行后续的操作。

优点:

  • 更快返回结果;
  • 减少等待,实现了步骤之间的并发,提升系统总体的性能。

2、流量控制

使用消息队列隔离网关和后端服务,以达到流量控制和保护后端服务的目的。

  1. 网关在收到请求后,将请求放入请求消息队列;
  2. 后端服务从请求消息队列中获取 APP 请求,完成后续秒杀处理过程,然后返回结果。在这里插入图片描述

优点:

  • 大量的秒杀请求到达网关时,不会直接冲击到后端的秒杀服务,而是先堆积在消息队列中,后端服务按照自己的最大处理能力,从消息队列中消费请求进行处理。
  • 根据下游的处理能力自动调节流量,达到**“削峰填谷”**的作用。
  • 可以随时增加秒杀服务的实例数量进行水平扩容,而不用对系统的其他部分做任何更改。

代价:

  • 增加了系统调用链环节,导致总体的响应时延变长。
  • 上下游系统都要将同步调用改为异步消息,增加了系统的复杂度
更简单的流量控制方法:令牌桶

​ 单位时间内只发放固定数量的令牌到令牌桶中,服务在处理请求之前必须先从令牌桶中拿出一个令牌,如果令牌桶中没有令牌,则拒绝请求。保证单位时间内,能处理的请求不超过发放令牌的数量,起到了流量控制的作用。

​ 不需要破坏原有的调用链,只要网关在处理 APP 请求时增加一个获取令牌的逻辑。在这里插入图片描述

实现:

​ 用固定容量的消息队列加一个“令牌发生器”来实现:令牌发生器按照预估的处理能力,匀速生产令牌并放入令牌队列(队列满了则丢弃令牌),网关在收到请求时去令牌队列消费一个令牌,获取到令牌则继续调用后端服务,获取不到令牌则返回失败。

3、服务解耦

​ 引入消息队列后,订单服务在订单变化时发送一条消息到消息队列的一个主题 Order 中,所有下游系统都订阅主题 Order,这样每个下游系统都可以获得一份实时完整的订单数据
​ 无论增加、减少下游系统或是下游系统需求如何变化,订单服务都无需做任何更改,实现了订单服务与下游服务的解耦。

4、其他应用场景

  • 作为发布 / 订阅系统实现一个微服务级系统间的观察者模式
  • 连接流计算任务和数据;
  • 用于将消息广播给大量接收者。

5、问题和局限性

  • 引入消息队列带来的延迟问题
  • 增加了系统的复杂度
  • 可能产生数据不一致的问题。

02 | 该如何选择消息队列?

及格的标准:开源、有一定社区活跃度、与周边生态系统有比较好的集成和兼容

  • 消息的可靠传递:确保不丢消息;
  • Cluster:支持集群,确保不会因为某个节点宕机导致服务不可用,当然也不能丢消息;
  • 性能:具备足够好的性能,能满足绝大多数场景的性能要求。

1、RabbitMQ

轻量级、迅捷、开箱即用、RabbitMQ 是一个相当轻量级的消息队列,易部署和使用。

特点:

  • 支持灵活的路由配置,它在生产者(Producer)和队列(Queue)之间增加了一个 Exchange 模块,你可以
    理解为交换机。可根据配置的路由规则将生产者发出的消息分发到不同的队列中。可以自定义路由规则。
  • 支持的编程语言大概是所有消息队列中最多的。

问题:

  • 它的设计理念里面,消息队列是一个管道,大量的消息积压是一种不正常的情况,应当尽量去避免。当大量消息积压的时候,会导致 RabbitMQ 的性能急剧下降。
  • 性能差,每秒钟可以处理几万到十几万条消息。
  • 编程语言 Erlang小众,难以扩展和开发。

2、RocketMQ

特点:

  • 有着不错的性能,稳定性和可靠性;
  • 有非常活跃的中文社区,易于维护;
  • 使用 Java 语言开发,易对 RocketMQ 进行扩展或者二次开发
  • 响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,很在意响应时延,那应该选择使用RocketMQ;
  • 性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息

问题:

  • 国际上还没有那么流行,与周边生态系统的集成和兼容程度要略逊一筹。

3、Kafka

Kafka 最初的设计目的是用于处理海量的日志。

特点:

  • 有不错的数据可靠性、稳定性和功能特性;
  • 与周边生态系统的兼容性最好,尤其在大数据和流计算领域,相关开源软件系统都会优先支持 Kafka。
  • 设计上大量使用了批量和异步的思想,这种设计使得Kafka 能做到超高的性能。
  • 异步收发的性能,是三者中最好的,每秒钟可以处理几十万条消息。

问题:

​ 同步收发消息的响应时延比较高,Kafka 不会立即发送出去,而是要“先攒一波再一起处理”,在它的 Broker 中,很多地方都会使用这种设计。因此当你的业务场景中,每秒钟消息数量没有那么多的时候,Kafka 的时延反而会比较高。所以,Kafka不太适合在线业务场景。

4、选择建议

  • RabbitMQ:消息队列不是系统的主角之一,对功能和性能都没有很高的要求,开箱即用易于维护;

  • RocketMQ:场景是处理在线业务,比如在交易系统中用消息队列传递订单,低延迟和金融级的稳定性

  • Kafka:海量的消息,收集日志、监控信息或是前端的埋点这类数据,或大量使用了大数据、流计算相关的开源产品。

03 | 消息模型:主题和队列有什么区别?

没有通用的标准

主题和队列有什么区别?

早期的消息模型:队列模型。在这里插入图片描述

弊端:

​ 多个消费者之间是竞争关系,每个消费者只能收到队列中的一部分消息,任何一条消息只能被其中的一个消费者收到。

发布 - 订阅模型(Publish-Subscribe Pattern)在这里插入图片描述

  • 发布者(Publisher):消息的发送方
  • 订阅者(Subscriber):消息的接收方
  • 主题(Topic):服务端存放消息的容器

​ 发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”。“订阅”在这里既是一个动作,同时还可以认为是主题在消费时的一个逻辑副本,每份订阅中,订阅者都可以接收到主题的所有消息。

两种模型的区别:一份消息数据能不能被消费多次的问题。

RabbitMQ 的消息模型

使用队列模型

针对队列模型问题的解决方案:

  • Exchange 位于生产者和队列之间,生产者将消息发送给 Exchange,由 Exchange 上配置的策略来决定将消息投递到哪些队列中。
  • 每个队列中都存放一份完整的消息数据

在这里插入图片描述

RocketMQ 的消息模型

标准的发布 - 订阅模型

消息队列的消费机制

“请求 - 确认”机制,确保消息不会丢失。

  1. 生产者先将消息发给服务端,服务端收到消息并将消息写入主题或者队列中后,会给生产者发送确认的响应。
  2. 生产者没收到确认或者收到失败的响应,则会重新发送消息
  3. 在消费端,消费者在收到消息并完成自己的消费业务逻辑(比如,将数据保存到数据库中)后,也会给服务端发送消费成功的确认
  4. 服务端只有收到消费确认后,才认为一条消息被成功消费,否则它会重新发送消息,直到收到对应的消费成功确认。

问题:

在某一条消息被成功消费之前,下一条消息是不能被消费的,否则会出现消息空洞,违背了有序性这个原则。

意味着每个主题在任意时刻,至多只能有一个消费者实例在进行消费,没法通过水平扩展消费者的数量来提升消费端总体的消费性能。

RocketMQ的解决方式:

主题下面增加了队列的概念。

每个主题包含多个队列,通过多个队列来实现多实例并行生产和消费。

注意:RocketMQ 只在队列上保证消息的有序性,主题层面是无法保证消息的严格顺序的。在这里插入图片描述

  • 订阅者:通过消费组来体现,一个消费组是一个订阅者
  • 消费组:每个消费组都消费主题中一份完整的消息,不同消费组之间消费进度彼此不受影响,一条消息被消费组1 消费过,也会再给 消费组2 消费。
  • 消费者:消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组内的一部分消息。如果一条消息被消费者 消费了,那同组的其他消费者就不会再收到这条消息
  • 主题(Topic):由于消息需要被不同的组进行多次消费,所以消费完的消息并不会立即被删除,这就需要 RocketMQ 为每个消费组在每个队列上维护一个消费位置(Consumer Offset),这个位置**之前的消息都被消费过,之后的消息都没有被消费过,**每成功消费一条消息,消费位置就加一
  • 注意:丢消息的原因大多是由于消费位置处理不当导致的

Kafka 的消息模型

Kafka 的消息模型和 RocketMQ 是完全一样的;

唯一的区别是,在 Kafka 中,队列对应的名称是“分区(Partition)”,含义和功能没有区别。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值