消息队列通识

为什么需要消息队列

  1. 解耦
  2. 削峰填谷
  3. 异步调用

消息队列如何保持幂等

  • 重复源泉
    • 生产端重发
      • 发送ACK没有回复继续发送
    • 消费端重复
  • 解决方案
    • 唯一消息ID,生产者发送时携带messageId
    • 幂等表
    • 状态机校验
    • 乐观锁 / 版本号
    • 分布式锁
  • 核心原则
    • 消费逻辑天然幂等

为什么需要消息队列

  • 解耦
  • 异步
  • 削峰

消息队列的模型有哪些

  • 点对点模型
  • 发布订阅模型

如何保证消息不丢失

  • 生产端
    • ack
    • broker 持久化
      • 生产环境副本因子 >= 3
  • 消费端
    • 手动提交 offset

如何保证消息有序

  • 让需要保持有序的消息落到同一个分区
  • 给唯一的key,且key以后不会重复
  • Kafka保证唯一分区内有序,跨分区无序

RabbitMQ

RabbitMQ 如何保证消息不丢失

  • 哪些情况会丢失
    • publisher -> exchange
      • 生产者确认机制
        • ack publish-confirm
        • nack publish-confirm
        • ack publish-return
        • 消息失败之后如何处理
          • 回调方法
          • 记录日志
          • 保存到数据库中然后定时重发
    • exchange -> queue
      • 消息持久化
        • 交换机持久化
        • 队列持久化
        • 消息持久化
    • queue
    • queue -> consumer
      • 消费者确认机制

RabbitMQ 消息的重复消费问题是如何解决的

重复消费的原因

  • 网络抖动
  • 消费者挂了

解决方案

  • 每条消息设置一个唯一的标识id
  • 幂等方案
    • 分布式锁
    • 数据库锁
      • 悲观锁
      • 乐观锁

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

延迟队列 = 死信交换机

消息堆积问题

  1. 增加消费者
  2. 消费者端开启线程池
  3. 扩大队列容积
    1. 惰性队列

RabbitMQ 的高可用机制

  1. 普通集群
  2. 镜像集群
  3. 仲裁队列

Kafka

Kafka 如何保证消息不丢失?

  • 丢失的三个情况
  • producer发送方式
    • 同步
      • get
    • 异步
  • 解决生产者丢失
    • 设置异步发送
    • 消息重试
  • 解决broker存储中丢失
    • 发送确认机制
      • acks
        • 0
        • 1
        • all
  • 解决消费者主从 broker 接收消息丢失
    • 禁止自动提交偏移量,改为手动提交偏移量
      • 同步提交
      • 异步提交
      • 同步+异步组合提交

如何解决Kafka的消息重复消费问题

  • 关闭自动提交
  • 同步+异步提交
  • 幂等方案

Kafka 如何保证消费的顺序性

  • 指定分区号
  • 发送消息时按照相同的业务设置相同的key

Kafka 高可用机制了解过吗

  • 集群
  • 分区备份机制
    • ISR副本(In-Sync Replica)
    • 普通副本

解释一下复制机制中的ISR?

分区副本的follwer分为两类 一类是ISR与leader副本同步保存数据 另一个是普通副本异步保存数据

Kafka 数据清理机制了解过吗?

  • Kafka 文件存储机制
    • 分段存储
      • .index
      • .log
      • .timeindex
    • 分段的好处
      • 减少单个文件内容大小,查找数据方便
      • 方便kafka进行日志清理
  • 数据清理机制
    • 日志的清理策略
      • 根据消息保留时间,如果消息超过指定时间,触发清理
      • 默认7天
      • 根据topic存储的数据大小,日志文件大小超过一定阈值进行清理(默认关闭)

Kafka 中实现高性能的设计有了解过吗?

  • 多性能是多方面协同的结果
  • 主要体现
    • 消息分区
    • 顺序读写
    • 页缓存
      • Linux系统的缓存。将磁盘数据缓存到内存,提高性能
    • 零拷贝
      • 减少上下文切换以及数据拷贝
    • 消息压缩
      • 提供多种消息压缩算法,减少磁盘和网络IO
      • 压缩耗费CPU
    • 分批发送
      • 将消息打包分批发送,减少网络开销

零拷贝的含义

用户空间 kafka 内核空间 页缓存 Socket缓冲区 硬件 磁盘文件 网卡

节省了页缓存到网卡的中间开销

页缓存直接到网卡

ZooKeeper 的作用,为什么抛弃?

  • 作用
    • broker 注册
    • topic / partition 元数据
    • controller 选举
    • ISR 变更
  • 抛弃原因
    • 运维两套系统麻烦
    • ZK 成为元数据规模的瓶颈
      • ZK 为了保证高性能,将整个数据树完全保存在内存中
      • Kafka能管理的分区总数,受限于 ZK 服务器的物理内存
    • 故障恢复慢
      • Leader 宕机或集群重启时,必须完成一套严格的恢复流程

Kafka 为什么这么快

  • 顺序IO写磁盘
  • 分区并行
  • 批量发送
  • 零拷贝
    • 数据在操作系统内核空间直接传递
    • 避免内核空间和用户空间之间多次拷贝和上下文切换
    • Kafka 的零拷贝是指利用 Linux 的 sendfile 系统调用,让数据从磁盘 PageCache 直接发送到网卡,绕过了用户态内存拷贝,从而极大降低了 CPU 开销并提升了消费吞吐量