一、RabbitMQ

1.1 什么场景下会使用MQ

  • 异步发送
  • MySQL和Redis之间的数据同步
  • 分布式事务
  • 消峰填谷

解耦 异步 消峰

1.2 MQ如何保证消息不丢失

消息发送过程

~各个环节都有可能造成消息丢失~

  1. RabbitMQ提供了publisher confirm机制,即发送方确认机制,保证消息不丢失。消息发送到MQ之后,会返回一个确认结果给发送方。如果发送方没有收到确认结果,则认为消息丢失。
  2. 正常发送到队列之后会返回一个ack publish confirm
  3. 如果失败:
    1. 发送到交换机失败:nack publish confirm
    2. 发送到队列失败:ack publish return

处理方法

  1. 使用生产者确认机制

    • 回调方法即时重发
    • 记录日志
    • 保存到数据库然后定时重发 发送成功就删除表中的数据
  2. 消息持久化

    • 交换机持久化
    • 队列持久化
    • 消息持久化
  3. 消费者确认机制

    • manual 手动ack
    • auto 自动ack
    • none 关闭ack
  4. 开启消费者失败重试机制

    • 超过重试次数交给error交换机 交给人工处理

1.3 Rabbit重复消费问题怎么解决

解决方案

  1. 每条消息设置一个唯一的标识id,接收消息时校验业务id是否存在
  2. 幂等性处理(分布式锁,数据库锁)

1.4 RabbitMQ的死信交换机(延迟队列)

延迟队列:进入队列的消息会被延迟消费的队列 (死信队列+TTL)
比如订单支付成功后,延迟10分钟, 如果10分钟内没有支付,则发送给死信队列。

死信交换机:当一个队列信息满足以下情况之一时,可以成为死信

  • 消费者使用basic.rejectbasic.nack声明消费失败,并且消息requeue为false
  • 消息是过期队列
  • 要投递的队列消息队积满了,最早的消息可能成为死信

1.5 消息堆积怎么解决

解决思路

  1. 增加更多消费者
  2. 在消费者内开启线程池加快消息处理速度
  3. 扩大队列容积,提高堆积上限(设置惰性队列)
    1. 接收到消息后直接存入磁盘
    2. 消费者要消费消息才会从磁盘中读取并加载到内存
    3. 支持数百万条消息存储

1.6 高可用机制

  • 在生产环境下、使用集群来保证高可用性
  • 普通集群
    • 集群的各个节点间共享部分数据 包括交换机 队列元信息(不包括队列中的消息)
  • 镜像集群
    • 本质是主从模式 互为主从
    • 交换机 队列 队列中的消息会在各个mq镜像节点之间同步备份
  • 仲裁队列 (quorum)
    • 和镜像队列一样 都是主从模式
    • 主从同步基于Raft协议,强一致