【消息队列高手课】- 基础篇

【消息队列高手课】- 基础篇

消息队列都有哪些选择:

  1. RabbitMQ - 特色:Exchange模块,开箱即用
  2. RocketMQ - 特色:低延迟和金融级的稳定性
  3. Kafka - 特色:海量,异步批量,“先攒一波再一起处理”
  4. ActiveMQ:队列模型和发布-订阅模型都支持
  5. ZeroMQ
  6. Pulsar - 特色:存储与计算分离

消息模型的种类?

1.队列模型

队列:先进先出的线性表。因为这个特性故而消息必须严格有序。按照什么顺序写到队列中就按照什么顺序读出去。

2.发布 - 订阅模型(Publish-Subscribe Pattern)

如果有多个消息者怎么办?使用发布-订阅模型解决这个问题

在发布-订阅模型中,消息的发送方称为发布者,消息的接收方称为订阅者,服务端存放消息的容器称为主题。发布者将消息发布到主题中,订阅者在接收消息之前需要先“订阅主题”,“订阅”在这里既是一个动作,同时,也可以认为是主题在消费的时的一个逻辑副本,每份订阅中,订阅者都能接收主题的所有消息。

队列模型和发布-订阅模型的最大区别是:一份消息数据能不能被消费多次。

RabbitMQ 的消息模型

RabbitMQ还是在坚持使用队列模型,Exchange模块放置在生产者和队列之间,生产者不关系发给哪个队列,而是把消息发送给Exchange模块,由Exchange上配置的策略决定将消息投递到哪些队列中。

同一份消息如果要被多个消费者消费,就需要配置Exchange将消息放入对个队列,每个队列中都会有一份完整的数据,为消费者提供服务

RocketMQ 的消息模型

RocketMQ使用的是标准的发布-订阅模型,但是,在 RocketMQ 也有队列(Queue)这个概念,队列的作用是什么呢?这里先说下消息队列的消费机制

消息队列的消费机制:

“请求 - 确认”机制,确保消息不会在传递过程中由于网络或者服务器故障丢失。

做法:在生产端,生产者先将消息发送给服务端,也就是Broker,服务端在收到消息并将消息写入主题或者队列后,会给生产者发送确认的响应。如果生产者没有收到服务端的确认或者收到失败额响应,则会重新发送消息;在消费端,消费者在收到消息并完成自己的业务逻辑后也会给服务端发送消费成功的确认,服务端只有收到消息确认后,才认为一条消息被成功消费,否则他就给消费者重新发送消息,直到对应的消费成功确认。这个机制保证了消息传递过程中的可靠性。

如何通过水平扩展消费者数量来提升消费端总体的消费性能?

每个主题包含多个队列,通过队列来实现多实例并行生产和消费。RocketMQ只保证队列上消息的有序性,主题层面是无法保证消息的严格顺序的。

RocketMQ中订阅者的概念是通过消费组(Consumer Group) 来体现的。每个消费组消费主题中的一份完整消息,不同消费组之前消费进度彼此不受影响。消费组中包含多个消费者,一条消息只被一个消费者消费。

消费完的消息并不会立即删除,RocketMQ在队列中维护了一个消费位置(Consumer Offset)

Kafka的消息模型

Kafka的消息模型跟Rocket是完全一样的,也是发布订阅模型,只是Kafka中的队列的名字为分区

另:消费者组和队列数没有关系。队列数量可以根据数据量和消费速度配置。

RocketMQ的分布式事务处理流程:

 对于第4步中,如果commit失败,kafka的解决方案为直接抛出异常。

事务:4 个属性(ACID):原子性、一致性、隔离性、持久性

MQTT协议-三种传递消息时能够提供的服务质量标准:

  • At most once: 至多一次 

  • At least once: 至少一次。

  • Exactly once:恰好一次。

预防消息积压如何处理:

  1. 发送端:增加每次发送消息的批量大小,增加并发
  2. 消费端:优化消费业务逻辑;水平扩容;增加消费端的并发数

特别需要注意的一点是,在扩容 Consumer 的实例数量的同时,必须同步扩容主题中的分区(也叫队列)数量,确保 Consumer 的实例数和分区数量是相等的。

课后题:

消费组和消息位置有关系,消费者和消费位置是没有关系的

如何实现单个队列的并行消费:

  JMQ的实现思路:

    当队列中有10条消息,对应的编号是0-9,当前的消费位置是5。同事来了3个请求来拉取消息,把编号为5、6、7的消息分别为3个消费者,每人一条。过了一段时间,3个消费成功的响应回来了,消费位置更为8.

    若是6、7回来了,5响应一直回不来,5就是一个消息空洞。为了避免5把这个队列卡住,先把5这个消息,复制到一个特殊重试队列中,然后依然把消费位置更新为8,继续消费。再有消费者来拉消息,优先把重试队列中的消息给消费者。 

并行消费原理:

开启并行消费后,队列是否上锁,由单队列最大并行数来控制

当客户端拉取消息时,服务端计算此队列上没有ack的消息总数,如果总数没有超过单队列的最大并行数,可以从后续位置积蓄拉取消息。

 

一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
原文地址:https://www.cnblogs.com/fengtingxin/p/14243268.html