跳到主要内容

MQ 常见的消费模式

面试问题 1:请解释生产者-消费者消息队列模式的工作原理

问题描述

生产者生产消息后,消息会持久化进入队列,分发给不同的消费者消费(同一个组的消费者均分消息,不同组的消费者都得到消息的一份拷贝),只要队列里的消息还没被消费群组确认完,会一直消费,每一个消费群组会记录消费到的消息 offset。

请用时序图描述这个过程,并解释 Consumer Group 的概念。

答案解析

Consumer Group 概念

Consumer Group:消费者组,由一到多个 Consumer 组成,每个 Consumer 都属于一个 Consumer Group。

  • 消费者组在逻辑上是同一个订阅者
  • 消费者组内每个消费者负责消费不同分区(Partition)的数据,一个分区只能由一个组内消费者消费
  • 消费者组之间互不影响。即每条消息只能被 Consumer Group 中的一个 Consumer 消费
  • 但是可以被多个 Consumer Group 组消费。这样就实现了单播和多播

时序图

解释说明

  1. 消息生产:生产者将消息发送到不同分区
  2. 消息持久化:MQ 将消息持久化存储
  3. 消息分发
    • 同一消费者组内的消费者按分区分工消费(负载均衡)
    • 不同消费者组都能收到完整的消息副本(广播)
  4. 消息确认:消费者处理完消息后发送 ACK
  5. Offset 管理:每个消费者组维护自己的消费位置

面试问题 2:在 Go 中如何实现 Redis 作为消息队列?

问题描述

不只是专业的 MQ 能做消息队列,很多公司也使用 Redis 来做消息队列。请描述 Redis 实现消息队列的方案,并介绍相关的 Go 工具。

答案解析

Redis 消息队列实现方案

Go 实现示例

使用 machinery 库

import "github.com/RichardKnop/machinery/v1"

// 配置
config := &config.Config{
Broker: "redis://localhost:6379",
DefaultQueue: "machinery_tasks",
ResultBackend: "redis://localhost:6379",
}

// 创建服务器
server, err := machinery.NewServer(config)

// 注册任务
server.RegisterTask("add", func(args ...int64) (int64, error) {
return args[0] + args[1], nil
})

时序图展示 Redis 队列工作流程


面试问题 3:发布-订阅模式与生产者-消费者模式的区别

问题描述

发布-订阅模式在订阅之前的消息收不到,只会收到订阅之后的消息,也就是非持久化的消息发布(退化的生产者-消费者消息队列模式)。请对比这两种模式的特点和适用场景。

答案解析

模式对比图

特点对比

特性生产者-消费者模式发布-订阅模式
消息持久化✅ 支持❌ 不支持
历史消息✅ 可消费❌ 无法获取
消费保证✅ 至少一次❌ 可能丢失
实时性较低很高
适用场景任务处理、数据同步实时通知、事件广播

发布-订阅时序图


面试问题 4:在大厂实际项目中,如何选择合适的消息队列方案?

问题描述

假设你在一个大厂工作,需要为不同的业务场景选择合适的消息队列方案。请描述你的选择依据和决策流程。

答案解析

决策流程图

技术选型对比


面试问题 5:如何保证消息队列的可靠性?

问题描述

在生产环境中,消息的可靠性至关重要。请描述如何从多个维度保证消息队列的可靠性。

答案解析

可靠性保证机制

消息可靠性时序图