NOTE

1.1 消息队列介绍

1. 什么是MQ - 消息队列,解耦生产者和消费者 - 生产者消费者其实也可以用数据库实现:生产者可以将事件写入数据库,消费者定时轮询数据库 - 但是这种方式对数据库的压力太大 2. MQ消息分发模型 - 有两种消息模型:队列模型和发布-订阅模型 2.1. 队列模型 - 一个生产者- Queue-

Message Queue更新于 约 3 分钟读完historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. 什么是MQ

  • 消息队列,解耦生产者和消费者
  • 生产者消费者其实也可以用数据库实现:生产者可以将事件写入数据库,消费者定时轮询数据库
  • 但是这种方式对数据库的压力太大

2. MQ消息分发模型

  • 有两种消息模型:队列模型和发布-订阅模型

2.1. 队列模型

  • 一个生产者->Queue->一个消费者
    • 一个生产者生产的消息由一个消费者独立消费;如果有多个消费者同时消费这个Queue,那么Queue的数据会分散给这几个消费者
    • 那我想多个消费者都独立的消费Queue的完整数据怎么办?只能建立多个Queue,每个Queue对应一个消费者
  • 消息分发模式-队列模式

2.2. 发布订阅模型

  • 一个生产者->Topic->多个消费者
    • 一个生产者产生的消息能够被多个消费者同时独立消费。
    • 如果只有一个消费者,那么就是队列模型
  • 消息分发模式-Topic模式

3. 消息推送模式

3.1. Push

  • 由服务器主动推送消息给客户端
  • 优点
    • 实时性好
  • 缺点
    • 客户端无法根据自己的能力决定消费速率
    • 需要服务器保持长连接以防消息丢失

3.2. Pull

  • 由客户端从服务器拉取消息
  • 优点
    • 客户端可以根据自己的能力决定消费速率
  • 缺点
    • 需要轮询对服务器压力大
    • 实时性差了点

4. 使用MQ的好处

4.1. 解耦

  • 没有解耦的时候,系统A需要直接调用其他系统的接口发送数据,每增加/删除一个消费方系统A都需要改代码。
  • 解耦后,系统A只需要发送数据到MQ中,其他系统可以从MQ中消费数据 消息队列优点-解耦

4.2. 异步

  • 同步调用的场景,系统A需要调用系统B、C、D,每个耗时200ms,那么总共耗时600ms
  • 使用了mq异步化可以更快速的响应用户请求,系统A只需要写入MQ,耗时100ms,其他系统自己消费进行处理

消息队列优点-异步

4.3. 削锋

  • 高峰时期5K个请求直接打在数据库上,崩溃
  • 使用mq抗住写请求,消费者根据能力进行处理

未命名绘图-削峰

5. 使用MQ的坏处

5.1. 可用性问题

5.2. 消息丢失问题

5.3. 幂等性问题

5.3.1. 生产者重复发送

生产者重复发送问题不大,主要是保证消费者不重复消费即可

5.3.2. 消费者重复消费

  • 消费者消费后没有commit offset(比如程序崩溃/强行kill/消费耗时/自动提交偏移情况下unscrible)
  • 如何解决
    • 这个属于消费者自己的问题不是MQ的问题,需要消费者自行解决
    • 编写幂等消息处理程序。写数据库的话可以先用主键查一下,有则不要插入
    • 跟踪消息并处理重复项。比如在数据库中记录message id 来去重,可以使用redis的set保存处理过的数据的key

5.4. 顺序性问题

5.5. 一致性问题

  • ABC写入成功才算成功,但是C失败了,那么就会造成数据不一致的现象
  • 如何解决
    • 手动确认+重试

6. 如何实现MQ

  • 可以使用日志系统实现消息的持久化
  • 生产者将消息追加到日志的末尾,而消费者通过依次读取日志来接收消息
  • 为了保证高性能可以对日志分区,每个分区放到不同的节点上
  • 为了保证高可用可以对日志复制,每个副本放到不同的节点上
  • 在每个分区之中,每个消息都会有一个单调递增的序列号,这样能够保证分区之中所有的消息是完全有序的,而不同分区之间的消息则没有顺序保证

7. 常见的MQ

7.1. RabbitMQ

7.2. Kafka

7.3. MQ选型

2026 注:下面的选型表是当时的粗略经验值;QPS、社区活跃度和可靠性能力都会随版本、配置与部署方式变化,不应作为固定基准。

ActiveMQ RabbitMQ RocketMQ Kafka
功能 不完备,可能丢失消息 完备(消息可以各种路由) 完备 不完备(普通的收发消息),可能丢失消息
QPS 万级并发 万级并发 十万级并发 十万级并发
社区活跃 不活跃 活跃 活跃 活跃
语言 Java erlang Java Java

8. 参考

正在加载有帮助数量