Rocket的概念和遇到的问题

https://rocketmq.apache.org/zh/docs/4.x/introduction/02whatis
强烈建议看官网文档 ,获取 “一手” 资源,而不是看视频和博客

这个是MQ的最佳实践,就是官网建议如何设置 Topic和Tag 和一个项目中最好怎么配置等内容
https://rocketmq.apache.org/zh/docs/4.x/bestPractice/01bestpractice

如果消费者订阅了topic中的一个tag 那么其他的tag信息怎么办?

在消息队列中,例如 Apache RocketMQ,Topic 是消息的逻辑集合,Tag 是用来进一步标识或过滤消息的标签。如果消费者订阅了一个 Topic 中的某个特定的 Tag,那么只有这个 Tag 对应的消息会被消费者接收,其他 Tag 的消息将不会被消费。
其他 Tag 的处理方式:

  1. 未订阅的 Tag 不会消费:消费者只会接收订阅的 Tag 对应的消息,其他 Tag 的消息会继续留在队列中,等待其他订阅相应 Tag 的消费者消费。
  2. 多个消费者:可以有多个消费者订阅同一个 Topic 中不同的 Tag。每个消费者只消费它订阅的 Tag 对应的消息。例如:
  • 消费者 A 订阅了 Tag1,它只会消费 Tag1 的消息。
  • 消费者 B 订阅了 Tag2,它只会消费 Tag2 的消息。
  1. 消息保留:未消费的 Tag 的消息会根据消息队列的配置继续保留一段时间(根据消息的存储策略或过期策略),直到有订阅该 Tag 的消费者来消费它们,或者它们过期被自动清理。
    如果你想让一个消费者订阅多个 Tag,可以在订阅时通过逗号分隔多个 Tag

Rocket的底层存储方式

  1. . RocketMQ 的队列(Queue)设计
    RocketMQ 将消息存储在磁盘上,这些消息被逻辑上划分为不同的 Topic 和 Queue。然而,消息在物理上是按照顺序存储的,RocketMQ 会根据消息的 Topic 和 Queue 对消息进行逻辑划分。具体来说:
  • Queue 是逻辑概念:每个 Topic 可以有多个 Queue,Queue 只是在逻辑上用于消息的分片,目的是为了提高并发和扩展性。
  • 消息物理存储在 CommitLog 中:所有消息(无论属于哪个 Topic 或 Queue)都会顺序写入到一个称为 CommitLog 的文件中。消息在 CommitLog 中是按照写入的顺序依次存储的。
  1. 消息索引机制(ConsumeQueue)
    RocketMQ 通过一个叫 ConsumeQueue 的结构来索引消息。每个 Topic 的每个 Queue 都有一个对应的 ConsumeQueue 文件,其中记录了该队列中消息在 CommitLog 文件中的物理位置(偏移量)。当消费者从 Queue 拉取消息时,RocketMQ 会从 ConsumeQueue 获取该队列中消息的偏移量,然后从 CommitLog 中读取实际消息。
    因此,RocketMQ 的实际存储并不是简单的队列,而是通过以下结构来组织:
  • CommitLog:顺序存储所有消息。
  • ConsumeQueue:每个 Queue 维护一个消息的索引,指向消息在 CommitLog 中的存储位置。
  1. Tag 过滤的原理
    RocketMQ 的 Tag 过滤是在消费者端进行的(默认情况下)。消费者从 ConsumeQueue 中获取消息的偏移量,再从 CommitLog 中读取消息,并在本地根据 Tag 过滤消息。如果消息的 Tag 与消费者的订阅不匹配,该消息会被跳过,RocketMQ 并不会阻塞后续消息的消费。
  2. 为什么不是简单的 Queue 或 Map?
  • Queue 是为了提高并发性能:逻辑上的 Queue 分片让多个消费者可以并发消费同一个 Topic 的消息,而不影响彼此的性能。
  • CommitLog 的顺序写入:顺序写入磁盘有利于性能优化,尤其是减少磁盘的随机写入。通过 CommitLog 和 ConsumeQueue 的结合,RocketMQ 实现了高效的消息存储和读取。
  • Tag 过滤是本地化的:消息体在 CommitLog 中是按顺序存储的,而 Tag 只是消息的一个属性。通过本地过滤,可以避免在服务端进行复杂的 Tag 匹配,从而提升系统的性能。
  1. 总结
    RocketMQ 的底层存储结构是 CommitLog + ConsumeQueue,并不是简单的 FIFO 队列,也不是映射(Map)。消息存储在 CommitLog 中,ConsumeQueue 提供对消息的索引。Tag 过滤在消费者端进行,未匹配的消息不会影响后续消息的消费。

从CommitLog读取消息,那么队列中的实际消息不会立即被删除

RocketMQ 的消息存储机制是基于 CommitLog 的顺序写入,并且消息在一段时间内不会被立即删除。消息不会因为被消费就从 CommitLog 中删除,而是按照一定的策略在后台进行清理。这种机制保证了消息的可靠性和高效性。具体来说,RocketMQ 的消息删除是基于过期策略和磁盘空间管理的,消息存储和清理机制如下:

  1. 消息的持久化与 CommitLog
  • CommitLog 是顺序写入的:所有的消息都会顺序写入到 CommitLog 文件中。无论消息属于哪个 Topic 或 Queue,CommitLog 都是全局的消息存储文件。消息写入之后不会被立即删除,甚至在被消费后仍然会存在。
  • ConsumeQueue 记录索引:每个 Topic 的每个逻辑 Queue 都有一个对应的 ConsumeQueue 文件,它是一个消息的索引文件,记录了消息在 CommitLog 中的物理偏移量。消费者通过 ConsumeQueue 获取消息的偏移量,随后从 CommitLog 中读取消息。
  1. 消息消费与清理
  • 消息不会立即删除:当一个消费者成功消费了某条消息后,RocketMQ 并不会立刻删除该消息。CommitLog 文件中的消息会保留一段时间。这是为了保证消费者在发生异常时(例如消息消费失败或重复消费)能够重新消费该消息。
  • 清理策略:基于时间或磁盘空间:
    • 时间策略:RocketMQ 提供了一个配置参数 fileReservedTime,用于定义 CommitLog 文件的保留时间(以小时为单位)。当消息在系统中存在的时间超过该时间后,系统会将其标记为可删除。
    • 磁盘空间管理:RocketMQ 还会根据磁盘的使用情况进行清理。通过 diskMaxUsedSpaceRatio 参数,RocketMQ 可以设置当磁盘使用率超过某个百分比时,启动文件清理机制,以防止磁盘空间被耗尽。
  • 后台删除机制(定期删除):RocketMQ 的后台清理线程会定期扫描 CommitLog 文件,并根据消息的保留时间或磁盘空间占用情况来删除过期或不需要的消息。
  1. 消息消费与重新消费
  • 消费位点管理:消费者的消费进度(消费位点)是由 RocketMQ 进行管理的。当消费者从一个 Queue 中消费消息时,RocketMQ 会记录它消费到的最后一个消息的偏移量(位点)。因此,即使消息还存在于 CommitLog 中,RocketMQ 会确保消费者不会重复消费已经处理过的消息。
  • 重新消费机制:由于消息没有被立即删除,消费者可以在某些情况下重新消费消息。例如,当消费失败时,RocketMQ 支持消息重试机制,消费者可以从上次失败的位点继续消费。
  1. 消息删除与不可恢复
    一旦消息被清理(从 CommitLog 文件中物理删除),它将不可恢复。这种清理是基于时间或磁盘空间的策略,RocketMQ 通过这种方式实现了消息存储的自动化管理。除非明确配置了持久化存储策略,否则被消费且过期的消息会被自动删除。
  2. 总结
  • 消息消费后不会立即从 CommitLog 中删除,而是保留一段时间。
  • 清理消息是通过时间或磁盘空间管理策略完成的。
  • 这种设计使得消息可以在需要时重新消费,并保证了系统的高效性和稳定性。

topic等都是逻辑上的分区

在 RocketMQ 中,Topic、Queue 都是逻辑上的分区,它们的主要作用是帮助消息系统进行消息分类和提高并发性能,但这些都是在逻辑层面实现的。消息的物理存储实际上是集中在 CommitLog 文件中,所有消息按顺序存储在一起。下面详细解释 RocketMQ 的逻辑分区和物理存储机制:

  1. Topic 是逻辑分区
  • Topic 是用于分类的逻辑标识符,它代表消息的类型或类别。在生产者发送消息时,消息会被打上 Topic 标签,消费者可以根据 Topic 订阅相应的消息。
  • 物理上,所有属于同一个 Topic 的消息并不会存储在一个单独的物理文件或队列中,而是存储在全局的 CommitLog 文件中。RocketMQ 通过 ConsumeQueue(类似于索引文件)来帮助消费者找到某个 Topic 的具体消息。
  1. Queue 是逻辑上的分片
  • Queue 是为了提高消息的并发处理能力,对同一个 Topic 进行的逻辑分片。一个 Topic 可以有多个 Queue,这使得消费者可以并行地从多个 Queue 中读取消息,从而提高消费效率。
  • 物理上,同一个 Topic 的不同 Queue 中的消息仍然存储在 CommitLog 文件中,RocketMQ 通过每个 Queue 对应的 ConsumeQueue 来维护这个 Queue 中的消息索引。
  1. 消息物理存储在 CommitLog
  • 所有的消息(无论它们属于哪个 Topic 或 Queue)都会物理上存储在 CommitLog 文件中。CommitLog 是一个顺序写入的文件,RocketMQ 使用这种设计来优化磁盘的写入性能。
  • ConsumeQueue 是一个索引文件,它记录了消息在 CommitLog 中的物理偏移量和大小。消费者通过 ConsumeQueue 找到消息的物理位置,并从 CommitLog 中读取消息。
  1. 逻辑分区的好处
  • 分类处理:Topic 让开发者可以对不同类型的消息进行分类处理。不同的消费者可以订阅不同的 Topic,专注于处理它们关心的消息。
  • 并行消费:Queue 是为了提高并发性能,RocketMQ 支持多个消费者组同时订阅同一个 Topic,并且可以从不同的 Queue 并发拉取消息。这种设计提高了系统的吞吐量。
  1. 逻辑上的分区与物理存储的关系
  • 虽然 Topic 和 Queue 是逻辑上的分区,它们只是用来帮助分类消息和实现并发消费。所有的消息最终都会写入一个物理存储文件——CommitLog 中,并通过索引机制(ConsumeQueue)来检索不同的 Topic 和 Queue 的消息。
  • 当消费者订阅某个 Topic 时,RocketMQ 会通过该 Topic 的 ConsumeQueue 文件找到相应的消息,然后从 CommitLog 中读取实际的消息数据。
    总结
  • Topic 和 Queue 都是逻辑分区,它们帮助实现消息分类和并发处理。
  • CommitLog 是消息的物理存储位置,所有的消息都会顺序存储在其中。
  • ConsumeQueue 是索引文件,用于找到特定 Topic 和 Queue 的消息在 CommitLog 中的位置。

实际消费者设置的订阅topic和tag只是告诉偏移量

可以这样理解,消费者订阅的 Topic 和 Tag 实际上只是帮助消费者过滤消息,并确定读取哪些消息的偏移量。RocketMQ 内部通过 ConsumeQueue 和 CommitLog 来管理和读取消息,而 Topic 和 Tag 则更多是逻辑上的标记,起到消息分类和过滤的作用。
具体解释:

  1. 订阅 Topic 的消费者:
  • 当消费者订阅了某个 Topic 时,它其实是在告诉 RocketMQ:“我要读取这个 Topic 中的消息。” RocketMQ 会从这个 Topic 对应的 ConsumeQueue 中获取消息的偏移量(即,消息在 CommitLog 中的物理位置),然后从 CommitLog 中读取这些消息。
  • ConsumeQueue 文件中记录了某个 Topic 的每个 Queue 中消息在 CommitLog 文件中的物理偏移量。因此,当消费者订阅一个 Topic 时,它会从 Topic 的不同 Queue 中拉取消息。
  1. 订阅 Tag 的消费者:
  • Tag 是消息的一个属性,用于进一步对 Topic 内的消息进行过滤。每条消息可能都有一个 Tag(或没有),Tag 主要用于帮助消费者更细粒度地过滤消息。
  • 当消费者订阅了一个特定的 Tag 时,RocketMQ 并不会在服务端直接过滤消息。消费者会根据 Topic 的 ConsumeQueue 获取消息的偏移量,然后从 CommitLog 中读取消息,在消费者端根据订阅的 Tag 进行过滤。
  • 也就是说,消费者会从 CommitLog 中读取所有消息,但只处理与订阅的 Tag 匹配的消息,其他消息会被忽略。
  1. 消息的偏移量:
  • 当消费者订阅某个 Topic 时,RocketMQ 通过 ConsumeQueue 提供该 Topic 的消息偏移量(即消息在 CommitLog 文件中的位置)。
  • Tag 只是在消费时的一个过滤条件,消息的偏移量是通过 Topic 和 Queue 来管理的,而不是通过 Tag 管理的。因此,消费者仍然会读取所有该 Topic 的消息,只是过滤掉与 Tag 不匹配的消息。
    订阅 Topic 和 Tag 的流程:
  1. 订阅 Topic:消费者向 RocketMQ 请求该 Topic 中的消息,RocketMQ 会通过 ConsumeQueue 找到对应的消息偏移量。
  2. 读取消息:RocketMQ 根据 ConsumeQueue 的偏移量从 CommitLog 中读取消息。
  3. Tag 过滤:消息到达消费者后,消费者端根据订阅的 Tag 进行过滤,只有匹配的消息会被处理,其他消息会被丢弃或忽略。
    订阅 Topic 和 Tag 的作用:
  • Topic 让消费者可以订阅消息的逻辑分区。
  • Tag 让消费者可以从 Topic 中进一步筛选出它们关心的消息。
    总结:
    消费者订阅的 Topic 确定了消费者从哪里获取消息偏移量,而 Tag 是在消费者端用于消息过滤的逻辑。RocketMQ 通过 ConsumeQueue 确定消息的物理位置(偏移量),而 Tag 只是在消费时的一个过滤条件,不影响消息的存储位置和偏移量。

生产者同步发送异步发送消息的区别

  1. 同步发送消息(Synchronous Sending)
    同步发送消息是指消息生产者在发送消息后,会等待消息服务器(Broker)的确认响应,只有当 Broker 成功接收并存储了消息之后,生产者才会继续执行后续逻辑。
    工作流程:
  2. 消息生产者发送消息到 RocketMQ 的 Broker。
  3. Broker 接收到消息后,持久化消息到磁盘或内存,并返回一个确认响应给生产者。
  4. 生产者收到 Broker 的确认响应后,认为消息发送成功,并继续执行下一步操作。
    特点:
  • 可靠性高:生产者会等待 Broker 的确认,确保消息已经成功存储。如果发送失败,生产者可以捕获异常并进行重试或其他处理逻辑。
  • 延迟较高:由于需要等待 Broker 的响应,整个过程会受到网络延迟和 Broker 处理能力的影响,响应时间相对较长。
  • 常用于重要场景:适合用于对数据一致性要求较高的场景,比如订单创建、支付处理等重要业务场景,因为消息的发送和确认过程都是可控的。
  1. 异步发送消息(Asynchronous Sending)
    异步发送消息是指消息生产者在发送消息后,不会等待 Broker 的确认,而是通过回调机制处理发送结果。生产者发送完消息后立即返回,Broker 的响应通过回调函数异步处理。
    工作流程:
  2. 消息生产者发送消息到 RocketMQ 的 Broker。
  3. 生产者无需等待 Broker 的响应,立即返回继续执行其他操作。
  4. 当 Broker 接收到消息并处理完后,会通过回调函数通知生产者消息发送的结果(成功或失败)。
    特点:
  • 响应速度快:因为生产者无需等待 Broker 的确认响应,可以快速返回并处理其他逻辑,适合对响应时间要求较高的场景。
  • 可靠性依赖回调处理:消息是否成功发送由回调函数处理。如果回调函数中未处理好失败的情况,可能会出现消息丢失的风险。
  • 适用于高并发场景:例如日志、监控数据等高并发且对可靠性要求不高的场景,因为异步发送能显著提高吞吐量。
  1. 同步发送与异步发送的区别
    暂时无法在飞书文档外展示此内容
  2. 异步发送的优势与挑战
  • 优势:异步发送可以极大地提高消息发送的吞吐量,因为生产者无需等待 Broker 的响应,可以同时发送大量消息,适合对实时性要求较高的场景。
  • 挑战:异步发送的难点在于错误处理。如果消息发送失败,生产者通过回调函数才能得知。如何设计合适的重试机制,确保消息不会丢失,是异步发送时需要重点考虑的。
  1. 选择哪种方式?
  • 同步发送:适合对消息发送的可靠性要求高、业务重要性高的场景,如支付系统、订单系统。
  • 异步发送:适合对响应时间要求高、并发量大的场景,如日志处理、监控系统等对消息可靠性要求较低的场景。
  1. 其他方式:单向发送
    除了同步和异步发送,RocketMQ 还提供了一种 单向发送(One-way Sending) 的方式。它不需要任何响应或回调,消息发出去后不关心结果,适合对可靠性要求最低的场景。
    总结:
  • 同步发送:生产者等待 Broker 的确认响应,适合高可靠性场景。
  • 异步发送:生产者不等待确认,依赖回调处理,适合高并发和低延迟场景。

发送方式和消费者无关

消息的同步发送和异步发送是生产者端的行为,和消费者无关。这两种发送方式的区别只体现在生产者如何处理消息的发送过程,而消费者的消费过程并不会受到影响。
详细解释:

  1. 生产者的同步/异步发送:
  • 同步发送:生产者等待消息发送成功的确认。
  • 异步发送:生产者发送消息后立即返回,结果通过回调函数处理。
  1. 无论是同步还是异步,消息一旦成功发送并存储在 Broker 上,都会进入到相应的 Topic 和 Queue 中,等待消费者来消费。
  2. 消费者的消费:
  • 消费者端的逻辑完全独立于生产者的发送方式。消费者只会从指定的 Topic 和 Queue 中拉取消息,而不会关心这些消息是通过同步方式还是异步方式发送的。
  • 消费者根据其订阅的 Topic 和 Tag 过滤并处理消息,与生产者端的发送方式无关。
    总结:
  • 生产者的同步/异步发送 只是影响消息发送的确认机制,与消费者的消费方式无关。
  • 消费者 只关注如何从 Broker 中拉取消息,处理逻辑与生产者的发送方式(同步或异步)没有直接联系。
    一个消费者组能消费几个topic 一个topic只能被一个消费者组消费吗?
    在 RocketMQ 中,一个消费者组可以消费多个Topic,而且一个 Topic 可以被多个消费者组消费。消费者组和 Topic 之间的关系是灵活的,它们的工作方式可以适应多种业务场景。
  1. 一个消费者组能消费多个 Topic
  • 消费者组是一个逻辑上的集合,通常用于一组消费者实例(通常是同一类业务)共同消费同一个或多个 Topic 中的消息。
  • 同一个消费者组中的多个消费者可以消费来自不同 Topic 的消息。这种方式允许多个 Topic 的消息同时被处理,提高了系统的灵活性。
  1. 一个 Topic 可以被多个消费者组消费
  • 一个 Topic 可以被多个消费者组订阅和消费,每个消费者组之间互不干扰,各自独立地消费该 Topic 中的消息。
  • 这种机制允许你为不同的业务场景设置不同的消费者组,分别消费相同 Topic 的消息。例如,一个 Topic 可能被多个系统使用,每个系统使用一个不同的消费者组来消费它感兴趣的消息。
  1. 消费者组内的消息分发:广播模式 vs 集群模式
  • 在同一个消费者组内部,RocketMQ 提供了两种消息分发模式:广播模式和集群模式。
    • 广播模式:每个消费者实例都能收到所有消息,每个消费者都处理一份完整的消息。
    • 集群模式:同一个消费者组内的不同实例会共同分摊消息,消息只会被其中一个消费者处理,这种模式通常用于负载均衡。
      示例:
  • 集群模式:如果 消费者组 A 有 3 个实例,那么 Topic1 的消息会被分摊到这 3 个实例进行消费,每条消息只会被其中一个实例处理。
  • 广播模式:如果 消费者组 A 有 3 个实例,那么每个实例都会收到 Topic1 中的所有消息。
  1. 消费者组与消费进度
  • 每个消费者组会维护独立的消费进度(Offset),即它在某个 Topic 中消费到哪个位置。如果多个消费者组订阅同一个 Topic,它们各自的消费进度是独立的,互不影响。
    示例:
  • 消费者组 A 和 消费者组 B 都订阅 Topic1,即使 消费者组 A 已经消费到最新的消息,消费者组 B 仍然可以从它自己的消费进度继续消费。
  1. 总结
  • 一个消费者组可以消费多个 Topic。你可以让同一个消费者组订阅并处理来自不同 Topic 的消息。
  • 一个 Topic 可以被多个消费者组消费。不同的消费者组可以同时订阅和消费相同的 Topic,且各自独立地管理消费进度。
  • 消费者组内的消费者在集群模式下会分摊消费消息,而在广播模式下每个消费者都会收到所有消息。
    这使得 RocketMQ 的消费模型非常灵活,可以适应各种消息消费的需求。

如果多个消费者组消费同一个topic那么一个消息是发给谁?是每组一份还是一共一份

当两个消费者组消费同一个 Topic 时,消息的分发方式是基于消费者组的。每个消费者组都有自己独立的消费进度和消费模式。因此,同一个 Topic 中的消息在不同的消费者组之间是独立消费的,
也就是说每个消费者组都会接收到完整的消息副本。
具体说明:

  1. 不同消费者组之间互不影响:
  • 如果你有两个消费者组,比如 消费者组 A 和 消费者组 B,并且它们都订阅了同一个 Topic,那么 RocketMQ 会将 Topic 中的消息发送给这两个消费者组。每个消费者组都会接收到该 Topic 的所有消息。
  • 换句话说,每个消费者组都会各自收到一份消息的副本,这两个组互不影响。
  1. 同一个消费者组内的消息分发:
  • 同一个消费者组中的消费者实例是通过分布式的方式进行消息消费的,具体消费模式有两种:
    • 集群模式(Clustering Mode):同一组内的消费者分摊消息处理,每条消息只会被消费者组中的一个消费者实例处理。例如,消费者组 A 内有 3 个实例,那么消息会被分配到不同的实例,形成负载均衡,消息不会被重复消费。
    • 广播模式(Broadcasting Mode):同一组内的每个消费者实例都会收到每条消息,也就是每个消费者实例都会处理一份完整的消息副本。广播模式通常用于对消息的全局通知场景。
      例子解释:
      场景 1:两个消费者组同时订阅一个 Topic
  • 消费者组 A 和 消费者组 B 都订阅了 Topic1。
  • RocketMQ 会确保 Topic1 中的每条消息都被分发给 消费者组 A 和 消费者组 B。
  • 消费者组 A 和 消费者组 B 各自有独立的消费进度,因此两组互不影响。消息 一共两份,每个消费者组都有一份消息副本。
    场景 2:同一个消费者组的消息分发
  • 假设 消费者组 A 有 3 个实例(A1、A2、A3),他们都订阅了 Topic1。
    • 在集群模式下,Topic1 的消息会被分配到 A1、A2、A3,每条消息只会被其中一个实例消费,不同实例分担消息处理。
    • 在广播模式下,A1、A2、A3 会同时收到同一条消息,即 每个实例都会处理一份完整的消息副本。
      总结:
  • 不同的消费者组:每个消费者组会独立消费消息,每个组都能接收到完整的消息副本。
  • 同一个消费者组:
    • 集群模式:消息在组内的不同消费者实例之间进行负载均衡,每条消息只会被组内一个实例消费。
    • 广播模式:组内的每个消费者实例都会收到所有的消息副本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值