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

  • 早期的消息队列,就是按照“队列”的数据结构来设计的
  • 发布 - 订阅模型
    • 在发布 - 订阅模型中,消息的发送方称为发布者(Publisher),消息的接收方称为订阅者(Subscriber),服务端存放消息的容器称为主题(Topic)
    • 发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”
  • RabbitMQ 的消息模型
    • 它是少数依然坚持使用队列模型的产品
    • 在 RabbitMQ 中,Exchange 位于生产者和队列之间,生产者并不关心将消息发送给哪个队列,而是将消息发送给 Exchange,由 Exchange 上配置的策略来决定将消息投递到哪些队列中
  • RocketMQ 的消息模型
    • RocketMQ 使用的消息模型是标准的发布 - 订阅模型;在 RocketMQ 也有队列(Queue)这个概念
    • 消息队列的消费机制
      • 几乎所有的消息队列产品都使用一种非常朴素的“请求 - 确认”机制,确保消息不会在传递过程中由于网络或服务器故障丢失
      • 在生产端,生产者先将消息发送给服务端,也就是 Broker,服务端在收到消息并将消息写入主题或者队列中后,会给生产者发送确认的响应
      • 如果生产者没有收到服务端的确认或者收到失败的响应,则会重新发送消息
    • 这个确认机制很好地保证了消息传递过程中的可靠性,但是,引入这个机制在消费端带来了一个不小的问题
      • 为了确保消息的有序性,在某一条消息被成功消费之前,下一条消息是不能被消费的,否则就会出现消息空洞,违背了有序性这个原则
      • 每个主题在任意时刻,至多只能有一个消费者实例在进行消费,那就没法通过水平扩展消费者的数量来提升消费端总体的消费性能
    • 每个主题包含多个队列,通过多个队列来实现多实例并行生产和消费
      • RocketMQ 只在队列上保证消息的有序性,主题层面是无法保证消息的严格顺序的
      • RocketMQ 中,订阅者的概念是通过消费组(Consumer Group)来体现的。每个消费组都消费主题中一份完整的消息,不同消费组之间消费进度彼此不受影响
      • 一条消息被 Consumer Group1 消费过,也会再给 Consumer Group2 消费
      • 消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组内的一部分消息
    • 在 Topic 的消费过程中,由于消息需要被不同的组进行多次消费
      • 消费完的消息并不会立即被删除,这就需要 RocketMQ 为每个消费组在每个队列上维护一个消费位置(Consumer Offset)
      • 我们在使用消息队列的时候,丢消息的原因大多是由于消费位置处理不当导致的
  • Kafka 的消息模型——消费者组,通过水平扩展消费者的数量来提升消费端总体的消费性能
    • Kafka 的消息模型和 RocketMQ 是完全一样的
    • 唯一的区别是,在 Kafka 中,队列这个概念的名称不一样,Kafka 中对应的名称是“分区(Partition)”,含义和功能是没有任何区别的
  • 小结
    • 业务模型不等于就是实现层面的模型,没有哪个数据库是以二维表的方式去存储数据的,MySQL 使用 B+ 树来存储数据,而 HBase 使用的是 KV 的结构来存储
    • 同样,像 Kafka 和 RocketMQ 的业务模型基本是一样的,并不是说他们的实现就是一样的,实际上这两个消息队列的实现是完全不同的
posted @ 2020-06-10 11:21  怡情养性长智  阅读(230)  评论(0编辑  收藏  举报