消息队列内部机制 可视化实验室

用交互式 SVG 呈现 Kafka 分区/副本、消费者组、RabbitMQ 交换器、消息确认等消息中间件核心机制。八个模块,纯原生实现。

zero-deps HTML / CSS / JS + SVG requestAnimationFrame prefers-reduced-motion
MODULE 01

Kafka 分区与副本

Topic 被切分为多个 Partition,每个 Partition 有一个 Leader 与若干 Follower 副本。ISR(In-Sync Replicas)是当前与 Leader 保持同步的副本集合。生产消息先写 Leader,再复制到 Followers。

partition-replica.svg
Leader Follower (ISR) 失联 Follower 消息

分区与副本

点击“生产消息”观察消息写入 Leader 并复制到 ISR 副本;切换某副本失联可观察 ISR 收缩与 under-replicated 状态。acks=all 时需所有 ISR 副本确认才视为提交。

分区数
3
副本因子
3
ISR 副本
—
消息数
0
MODULE 02

消费者组与 Offset

同一消费者组内每个 Partition 只被一个消费者消费,实现并行扩展。消费者维护 Offset 进度并提交。增减消费者触发 Rebalance,分区重新分配。点击观察消费推进与 Rebalance。

consumer-offset.svg
消费者 A 消费者 B 消费者 C 已提交 Offset

消费进度

每个分区当前消费 Offset 与已提交 Offset。Rebalance 后分区在消费者间重新分配,可能造成短暂重复消费(at-least-once)或需要 seek 恢复。auto.offset.commit=enable 时周期性提交。

消费者数
2
分区数
4
已消费
0
Lag
0
MODULE 03

RabbitMQ 交换器四种路由

Direct 按 routing key 精确匹配;Fanout 广播到所有绑定队列;Topic 按模式匹配(* 一词,# 零词或多词);Header 按消息头属性匹配。切换类型并发送消息观察路由差异。

exchange-routing.svg
Exchange 绑定 命中队列 消息

Direct 交换器

routing key 与 binding key 完全相等才路由。输入 routing key 后发送,只有绑定了相同 key 的队列会收到消息。

交换器类型
direct
绑定队列
4
命中数
0
MODULE 04

消息确认 ACK / NACK 与幂等

消费者处理完成后 ACK 确认;失败则 NACK 并 requeue 重投,可能造成重复消费。通过去重表(幂等消费)实现 at-least-once 语义下业务 Exactly-Once。模拟消费者故障观察重投。

ack-nack.svg
ACK 成功 NACK 失败 重投 幂等去重

投递语义

auto-ack 关闭后,broker 在收到 ACK 前不会删除消息;消费者崩溃则消息 requeue 重投,导致 at-least-once。幂等消费用唯一 msg_id 在去重表标记,重复消息被跳过。

投递总数
0
ACK
0
NACK 重投
0
去重命中
0
MODULE 05

消息顺序性:分区有序 vs 全局有序

Kafka 仅保证单 Partition 内消息有序;多 Partition 并行消费会打破全局顺序。需要全局有序时只能用单 Partition(牺牲并行度)或顺序锁按 key 路由。切换模式对比。

ordering.svg
分区 1 分区 2 分区 3 乱序

顺序保证

分区有序:同一 key 路由到同一分区,分区内严格有序。全局有序:仅 1 个分区,所有消息串行,吞吐受限。顺序消费端用单线程 per-partition 消费保证处理顺序。

模式
分区有序
分区数
3
乱序消息
0
吞吐
高
MODULE 06

死信队列与重试退避

消费失败的消息经重试退避(指数退避)后仍失败,进入死信队列(DLQ)隔离处理。持续失败无法处理的消息称为毒丸(Poison Pill),需人工介入。模拟消费失败观察 DLQ 流转。

dlq-retry.svg
正常消费 重试中 DLQ 毒丸

重试与死信

最大重试次数(如 3)内每次失败按指数退避(1s/2s/4s)延迟重投;超过阈值则转入 DLQ。毒丸消息永远失败,应设置最大重试避免无限重投阻塞队列。

成功
0
重试
0
DLQ
0
毒丸
0
MODULE 07

消息积压与背压 Backpressure

生产速率大于消费速率时形成积压(Lag)。背压机制通过反馈调节生产速率或扩容消费者,防止系统过载。拖动滑块调节两侧速率观察积压与背压效果。

backpressure.svg
生产速率 消费速率 积压 背压触发

背压策略

背压实现:①拒绝/限流生产者(Reject / 429)②有界队列阻塞生产者线程③扩容消费者分区。当积压超过阈值(如 10000)触发背压,生产速率被压低至消费速率附近。

生产速率
—
消费速率
—
积压
0
背压状态
正常
MODULE 08

Exactly-Once 语义

Exactly-Once 通过事务消息(两阶段提交:Init→Begin→Produce→Commit)与幂等生产者(PID + 序列号去重)共同实现。对比 At-Least-Once 可能重复,Exactly-Once 保证消息不重不漏。

exactly-once.svg
提交 中止 幂等去重 事务

Exactly-Once 实现

幂等生产者:每个 producer 分配 PID,每条消息带递增 seq,broker 按 (PID, partition, seq) 去重,网络重试不会产生重复。事务:跨分区多消息原子写入,消费者 read_committed 只读已提交消息。

语义
exactly-once
提交事务
0
中止事务
0
去重消息
0