0%

MQ

MQ

MQ总览

作用

异步,削峰,解耦,大数据量分批

引入复杂度

重复消费,中间数据不一致,降低可用性,复杂度提高

防止重复消费

  1. 幂等
  2. redis分布式锁
  3. 分区顺序MQ
  4. mysql唯一键

消息积压

原因:生产速率大于消费速率

  • 用户流量突然增大
  • 广播消息,服务器扩容10倍以上
  • 消费者服务问题
    • bug
    • 数据库,下游服务网络问题

解决消息积压:

  1. 增加消费能力

    • 直接增加消费者数量;增加消费者服务器、多线程消费
    • 单个消费改为批量消费
    • 提前写消息积压时的特殊消费逻辑。
    • 将Topic分发到多个临时Topic,新的多台consumer消费临时Topic
  2. 降低生产速率

    1. 限流
  3. 进一步对MQ削峰填谷

    白天丢弃消息,晚上通过日志找到消息补发到MQ中

避免消息积压

  • 监控和告警,监控消息队列的消息数量、延迟等指标

示例

  • 问题:部分MQ消费速度为0,消息积压
  • 原因:修改饮品菜谱后,广播清除所有服务器的JVM本地缓存,节日扩容引起了单个MQ消费速率超高,占用了所有消费限制。生产+消费一共8万。
  • 解决
    临时:缩容
    后期:取消广播,本地缓存时间降低到2分钟,接受2分钟的数据延迟

数据一致性

定时任务比较成功消费MQ的数据是否正确

RocketMQ

功能

  1. 异步消息

  2. 同步消息

  3. 顺序消息

  4. 定时消息

  5. 事务消息

    修改状态原理:

    1. 记录消息offset(相当于地址)
    2. 第一阶段提交
    3. 第二阶段根据offset查询到消息
    4. 修改状态

    offset实现查询消息的问题:通过offset修改数据,会产生很多脏页

  6. 消息重放

    支持指定消息,指定时间段重放

  7. 消息堆积

    可堆积亿条消息

  8. 消息防丢失

  9. 消息可靠性

    • broker关闭、异常、操作系统异常后恢复,可保证消息不丢失。(刷盘方式是异步时丢失极少量数据)
    • 机器无法开机、磁盘损坏,通过异步复制,可保证99%的消息不丢失;同步双写可避免单点问题,但很影响性能。
    • 消息消费后,才会返回ACK,不返回ACK,消息会重新投递,消费一定次数后,会被投递到死信队列。

原理

物理结构

image-20240228075320819

逻辑结构

image-20240228075354953

消息数据结构

消费方式

  • push(推,长轮询pull)

    优点:实时性高,不用自己维护消费速率

    缺点:消息量大的时候,消费者压力大

    • 拉去消息步骤

      1. 消费者启动时创建一个后台线程,处理拉消息

      2. 判断有没有过多消息未消费,

        • 有的话,间隔一定时间再去执行拉消息步骤

        • 没有的话,直接向MQ发送拉去消息的请求。

          • 有消息,立刻返回
          • 没有消息,hold住请求,有消息时再放回
      3. 获取消息后,找用户自定义的消息处理逻辑,并执行;同时再次拉取消息。

    • 消费者控制消费压力

      • 基于未消费消息的数量
      • 基于未消费消息内存占用
  • pull

    优点:消费速率灵活可控

    缺点:实时性差,需要主动维护消费速率

各类MQ区别

RocketMQ RabbitMQ Kafaka
开发语言 Java Erlang Java
单机性能 10万 10万
延迟 ms us ms
可用性 普通集群(主从架构),镜像集群
功能性 功能完备,扩展性强 相比RocketMQ缺事务、顺序消息。基于Erlang开发,并发能力强,延时低,管理界面丰富