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选型

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

8. 参考

讨论

使用 GitHub 账号参与讨论,评论会保存在 GitHub Issues 中。在 GitHub 查看