目录 概述 Kafka RocketMQ 常见问题 一、概述 使用场景 解耦:生产者 / 消费者只负责发送 / 消费消息,而不关心对方状态;消费者挂掉后,消息只会积压在队列中,不影响整体业务。 削峰:高并发场景下,把大量请求写入 MQ,消费者按自己的处理能力拉取,避免直接冲垮数据库或服务。 异步:将无需同步完成的步骤放到 MQ 异步处理,提升接口响应速度。 各 MQ 对比 Kafka:性能高,分区有序,采用 sendfile。 RocketMQ:有序,采用 mmap(需要读取消息内容实现死信队列等)。 消息模型 队列模型:一个消息只能被一个消费者消费,未被消费的消息保持在队列中,直到被消费或超时。 发布-订阅模型:消息发送到 Topic,会被所有订阅 Topic 的消费者消费。 二、Kafka 核心概念 Broker:Kafka 集群中的每一个实例。 Partition:每个 Topic 有多个逻辑分区,分布在多个 Broker 上实现并发能力。 Replica:每个分区有 Leader 和 Follower 两种副本,分布在不同 Broker 上。 Leader:生产者和消费者只与这个唯一的 Leader 副本交互。 Follower:Leader 故障时,会从 Follower 中选举出一个 Leader。 Consumer Group:消费者组,共同消费同一个 topic,每个分区同一时间只能由一个消费者读取,故消费者数量与分区数相同时,吞吐量最大。 消息参数 topic、partition、key(相同 key 的消息进入同一 partition)、data 持久化 先写到内存的 PageCache 中,再由操作系统决定什么时候刷盘(默认),可以设置 log.flush.interval.messages 和log.flush.interval.ms 参数,控制日志达多少条、或保留时间超过多少时强制刷盘。 死信队列 Kafka 原生不支持死信队列,因为设计理念专注于消息存储和传递,把消费失败的处理交给上层应用来实现,但是可以通过一些框架实现。 Spring Kafka:在 @KafkaListener 同类下创建 @DltHandler 注解的方法,自动将消息内容、topic、partition、offset 以及异常信息等写入 .DLT 的 topic 中。注意,死信队列本身依赖 Kafka 的可用性,只能作为一道保险,最好增加持久化兜底。 三、RocketMQ 核心概念 Broker:并非 Kafka 中的独立服务实例,而是有主从之分;与 Topic 多对多。 NameServer:注册 Broker 信息,实现 Broker 管理和路由。 Queue:每个 Topic 拆分成多个 Queue 供读写,消息在 Queue 内有序。 持久化 设置 Broker 的 FlushDiskType 参数: 同步刷盘(SYNC_FLUSH):需等待刷盘 ack,安全性高,但性能较低。 异步刷盘(ASYNC_FLUSH):后台异步线程提交,Broker 宕机时会丢失数据。 主从同步 同步复制:只有消息同步双写到主从节点上时才返回写入成功。 异步复制:消息写入主节点之后就直接返回写入成功。 异步复制不影响可靠性,仅作为高可用手段,而可靠性依赖刷盘策略。RocketMQ 不支持自动主从切换,但消费者可以自动切换到从节点进行消费。 单主从架构下,主节点挂掉后整个系统无法生产,可用性差,因此生产环境一般采用多主多从部署。 功能特性 延时消息:将消息放入延时 Topic 队列,通过定时任务检查实现。 顺序消息:保证严格有序,需设置消息组,把消息映射到同一个 Queue。 分布式事务(最终一致性) (1)服务 A 发送 Half Message(消费者不可见)。 (2)服务 A 收到 MQ 响应后,执行本地事务。 (3)执行成功则发送 commit 到 MQ,消息变为可消费。 (4)执行失败则发送 rollback 到 MQ,删除半消息。 (5)如果 MQ 一直未收到服务 A 返回,回调服务 A 回查。 (6)根据回查结果再次 commit 或 rollback。 回溯消费:按照时间维度来回退消费进度。 四、常见问题 重复消费 生产者端:MQ 自身接口保证不会加入重复消息(如缓存已处理的 message_id)。 消费者端:需消费者做幂等,或拉取到消息就响应(会消息丢失,可配合对账)。 消息丢失 生产者端:生产者在 MQ 返回异常时,设置合理的消息重发逻辑。 Kafka:send() 方法返回 ListenableFuture,为异步操作,除了用 get() 使其变成同步操作外,还可以 addCallback() 为其添加回调。 消息队列:持久化 + 集群副本防止单点故障。 Kafka:可配置如下参数。 - acks:默认为 1,L