Kafka 深度解析:从架构原理到生产实践
摘要:Apache Kafka 作为当今最流行的分布式流处理平台之一,已经成为现代数据架构的核心组件。本文将从 Kafka 的核心概念出发,深入剖析其底层架构、存储机制、高可用设计以及生产环境中的最佳实践,帮助你构建对 Kafka 的系统性认知。
目录
- [Kafka 是什么](#Kafka 是什么)
- 核心概念全景图
- [Kafka 架构深度解析](#Kafka 架构深度解析)
- 消息存储机制:日志与索引
- [高可用设计:副本与 ISR](#高可用设计:副本与 ISR)
- 生产者原理与优化
- [消费者组与 Rebalance](#消费者组与 Rebalance)
- 性能优化与调优实践
- 典型应用场景
- 总结
1. Kafka 是什么
Apache Kafka 最初由 LinkedIn 开发,后捐赠给 Apache 基金会。它不仅仅是一个消息队列,更是一个分布式流处理平台,具备以下三大核心能力:
- 发布与订阅:类似于传统消息队列,支持高吞吐量的消息流
- 持久化存储:以容错持久化方式存储消息流
- 流处理:实时处理发生的消息流
Kafka vs 传统 MQ
| 特性 | Kafka | RabbitMQ/ActiveMQ |
|---|---|---|
| 设计目标 | 高吞吐量流处理 | 通用消息队列 |
| 消息持久化 | 核心特性,长时间保留 | 消费后即删除或短期保留 |
| 消费模式 | Pull 模式,支持回溯 | Push 模式为主 |
| 吞吐量 | 百万级 TPS | 万级 TPS |
| 顺序性 | Partition 级别严格有序 | Queue 级别有序 |
2. 核心概念全景图
在深入架构之前,我们先梳理 Kafka 的核心概念及其关系:
#mermaid-svg-7kHkSv48PWKK4Ds3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7kHkSv48PWKK4Ds3 .error-icon{fill:#552222;}#mermaid-svg-7kHkSv48PWKK4Ds3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7kHkSv48PWKK4Ds3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .marker.cross{stroke:#333333;}#mermaid-svg-7kHkSv48PWKK4Ds3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7kHkSv48PWKK4Ds3 p{margin:0;}#mermaid-svg-7kHkSv48PWKK4Ds3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster-label text{fill:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster-label span{color:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster-label span p{background-color:transparent;}#mermaid-svg-7kHkSv48PWKK4Ds3 .label text,#mermaid-svg-7kHkSv48PWKK4Ds3 span{fill:#333;color:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .node rect,#mermaid-svg-7kHkSv48PWKK4Ds3 .node circle,#mermaid-svg-7kHkSv48PWKK4Ds3 .node ellipse,#mermaid-svg-7kHkSv48PWKK4Ds3 .node polygon,#mermaid-svg-7kHkSv48PWKK4Ds3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .rough-node .label text,#mermaid-svg-7kHkSv48PWKK4Ds3 .node .label text,#mermaid-svg-7kHkSv48PWKK4Ds3 .image-shape .label,#mermaid-svg-7kHkSv48PWKK4Ds3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-7kHkSv48PWKK4Ds3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .rough-node .label,#mermaid-svg-7kHkSv48PWKK4Ds3 .node .label,#mermaid-svg-7kHkSv48PWKK4Ds3 .image-shape .label,#mermaid-svg-7kHkSv48PWKK4Ds3 .icon-shape .label{text-align:center;}#mermaid-svg-7kHkSv48PWKK4Ds3 .node.clickable{cursor:pointer;}#mermaid-svg-7kHkSv48PWKK4Ds3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .arrowheadPath{fill:#333333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7kHkSv48PWKK4Ds3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7kHkSv48PWKK4Ds3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7kHkSv48PWKK4Ds3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster text{fill:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 .cluster span{color:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7kHkSv48PWKK4Ds3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7kHkSv48PWKK4Ds3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-7kHkSv48PWKK4Ds3 .icon-shape,#mermaid-svg-7kHkSv48PWKK4Ds3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7kHkSv48PWKK4Ds3 .icon-shape p,#mermaid-svg-7kHkSv48PWKK4Ds3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7kHkSv48PWKK4Ds3 .icon-shape .label rect,#mermaid-svg-7kHkSv48PWKK4Ds3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7kHkSv48PWKK4Ds3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7kHkSv48PWKK4Ds3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7kHkSv48PWKK4Ds3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Topic-A
Kafka Cluster
Broker 1
Broker 2
Broker 3
Partition 0 Leader B1 Replica B2
Partition 1 Leader B2 Replica B3
Partition 2 Leader B3 Replica B1
Producer
Consumer Group A
Consumer 1
Consumer 2
关键术语
| 概念 | 说明 |
|---|---|
| Broker | Kafka 服务器节点,负责存储和转发消息 |
| Topic | 消息的逻辑分类,类似数据库的表 |
| Partition | Topic 的物理分片,实现水平扩展 |
| Offset | 消息在 Partition 中的唯一标识(位移) |
| Producer | 消息生产者,向 Topic 发送消息 |
| Consumer | 消息消费者,从 Topic 读取消息 |
| Consumer Group | 消费者组,组内消费者共同消费一个 Topic |
| Replication | 副本机制,保证数据高可用 |
3. Kafka 架构深度解析
3.1 整体架构图
#mermaid-svg-mJk8Ok1i48Wkkjk1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .error-icon{fill:#552222;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .marker.cross{stroke:#333333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 p{margin:0;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster-label text{fill:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster-label span{color:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster-label span p{background-color:transparent;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .label text,#mermaid-svg-mJk8Ok1i48Wkkjk1 span{fill:#333;color:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .node rect,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node circle,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node ellipse,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node polygon,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .rough-node .label text,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node .label text,#mermaid-svg-mJk8Ok1i48Wkkjk1 .image-shape .label,#mermaid-svg-mJk8Ok1i48Wkkjk1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .rough-node .label,#mermaid-svg-mJk8Ok1i48Wkkjk1 .node .label,#mermaid-svg-mJk8Ok1i48Wkkjk1 .image-shape .label,#mermaid-svg-mJk8Ok1i48Wkkjk1 .icon-shape .label{text-align:center;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .node.clickable{cursor:pointer;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .arrowheadPath{fill:#333333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mJk8Ok1i48Wkkjk1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mJk8Ok1i48Wkkjk1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster text{fill:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .cluster span{color:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mJk8Ok1i48Wkkjk1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .icon-shape,#mermaid-svg-mJk8Ok1i48Wkkjk1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .icon-shape p,#mermaid-svg-mJk8Ok1i48Wkkjk1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .icon-shape .label rect,#mermaid-svg-mJk8Ok1i48Wkkjk1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mJk8Ok1i48Wkkjk1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mJk8Ok1i48Wkkjk1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mJk8Ok1i48Wkkjk1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Consumers
Kafka Cluster
Producers
Producer A
Producer B
Producer C
ZooKeeper KRaft Mode
Broker 1 Controller
Broker 2
Broker 3
Consumer Group 1
Consumer Group 2
Consumer 1
Consumer 2
Consumer 3
Consumer 4
3.2 Controller 机制
每个 Kafka 集群中只有一个 Controller Broker,负责:
- 管理 Partition 的 Leader 选举
- 监控 Broker 的存活状态
- 维护集群元数据
当 Controller 宕机时,其他 Broker 会通过 ZooKeeper(或 KRaft)选举新的 Controller。
3.3 KRaft 模式(Kafka 3.0+)
Kafka 逐步去除对 ZooKeeper 的依赖,引入 KRaft(Kafka Raft) 模式:
- 使用内置的 Raft 共识算法管理元数据
- 减少外部依赖,简化部署
- 提升元数据操作的性能和可扩展性
4. 消息存储机制:日志与索引
Kafka 的高性能很大程度上源于其顺序写磁盘的日志存储设计。
4.1 存储结构图解
#mermaid-svg-4fS3sAcEmY3VPjZo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4fS3sAcEmY3VPjZo .error-icon{fill:#552222;}#mermaid-svg-4fS3sAcEmY3VPjZo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4fS3sAcEmY3VPjZo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4fS3sAcEmY3VPjZo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4fS3sAcEmY3VPjZo .marker.cross{stroke:#333333;}#mermaid-svg-4fS3sAcEmY3VPjZo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4fS3sAcEmY3VPjZo p{margin:0;}#mermaid-svg-4fS3sAcEmY3VPjZo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster-label text{fill:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster-label span{color:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster-label span p{background-color:transparent;}#mermaid-svg-4fS3sAcEmY3VPjZo .label text,#mermaid-svg-4fS3sAcEmY3VPjZo span{fill:#333;color:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo .node rect,#mermaid-svg-4fS3sAcEmY3VPjZo .node circle,#mermaid-svg-4fS3sAcEmY3VPjZo .node ellipse,#mermaid-svg-4fS3sAcEmY3VPjZo .node polygon,#mermaid-svg-4fS3sAcEmY3VPjZo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4fS3sAcEmY3VPjZo .rough-node .label text,#mermaid-svg-4fS3sAcEmY3VPjZo .node .label text,#mermaid-svg-4fS3sAcEmY3VPjZo .image-shape .label,#mermaid-svg-4fS3sAcEmY3VPjZo .icon-shape .label{text-anchor:middle;}#mermaid-svg-4fS3sAcEmY3VPjZo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4fS3sAcEmY3VPjZo .rough-node .label,#mermaid-svg-4fS3sAcEmY3VPjZo .node .label,#mermaid-svg-4fS3sAcEmY3VPjZo .image-shape .label,#mermaid-svg-4fS3sAcEmY3VPjZo .icon-shape .label{text-align:center;}#mermaid-svg-4fS3sAcEmY3VPjZo .node.clickable{cursor:pointer;}#mermaid-svg-4fS3sAcEmY3VPjZo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4fS3sAcEmY3VPjZo .arrowheadPath{fill:#333333;}#mermaid-svg-4fS3sAcEmY3VPjZo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4fS3sAcEmY3VPjZo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4fS3sAcEmY3VPjZo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4fS3sAcEmY3VPjZo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4fS3sAcEmY3VPjZo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4fS3sAcEmY3VPjZo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster text{fill:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo .cluster span{color:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4fS3sAcEmY3VPjZo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4fS3sAcEmY3VPjZo rect.text{fill:none;stroke-width:0;}#mermaid-svg-4fS3sAcEmY3VPjZo .icon-shape,#mermaid-svg-4fS3sAcEmY3VPjZo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4fS3sAcEmY3VPjZo .icon-shape p,#mermaid-svg-4fS3sAcEmY3VPjZo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4fS3sAcEmY3VPjZo .icon-shape .label rect,#mermaid-svg-4fS3sAcEmY3VPjZo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4fS3sAcEmY3VPjZo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4fS3sAcEmY3VPjZo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4fS3sAcEmY3VPjZo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Broker-1-Storage
Topic-Orders
Partition 0
Partition 1
Partition 2
Segment 00000000000000000000.log 1GB
Segment 00000000000003657291.log 1GB
Segment 00000000000007314582.log Active
Index File .index
TimeIndex File .timeindex
Transaction Index .txnindex
4.2 Log Segment 详解
每个 Partition 在物理上被划分为多个 Segment(默认 1GB):
/orders-0/
├── 00000000000000000000.log # 消息数据文件
├── 00000000000000000000.index # 偏移量索引(稀疏索引)
├── 00000000000000000000.timeindex # 时间戳索引
├── 00000000000003657291.log # 下一个 Segment
├── 00000000000003657291.index
└── 00000000000003657291.timeindex
关键设计点:
- 顺序追加写:只有最后一个 Segment(Active Segment)可写,避免随机磁盘寻址
- 稀疏索引:每隔一定字节(默认 4KB)建立一条索引记录,平衡内存占用与查询效率
- 零拷贝(Zero-Copy) :通过
sendfile系统调用直接将数据从 Page Cache 发送到网卡
4.3 消息查找流程
Log File Index File Broker Consumer Log File Index File Broker Consumer #mermaid-svg-g4uOpk6gtuGnIoUX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-g4uOpk6gtuGnIoUX .error-icon{fill:#552222;}#mermaid-svg-g4uOpk6gtuGnIoUX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-g4uOpk6gtuGnIoUX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-g4uOpk6gtuGnIoUX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-g4uOpk6gtuGnIoUX .marker.cross{stroke:#333333;}#mermaid-svg-g4uOpk6gtuGnIoUX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-g4uOpk6gtuGnIoUX p{margin:0;}#mermaid-svg-g4uOpk6gtuGnIoUX .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-g4uOpk6gtuGnIoUX text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-g4uOpk6gtuGnIoUX .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-g4uOpk6gtuGnIoUX .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-g4uOpk6gtuGnIoUX #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-g4uOpk6gtuGnIoUX .sequenceNumber{fill:white;}#mermaid-svg-g4uOpk6gtuGnIoUX #sequencenumber{fill:#333;}#mermaid-svg-g4uOpk6gtuGnIoUX #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-g4uOpk6gtuGnIoUX .messageText{fill:#333;stroke:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-g4uOpk6gtuGnIoUX .labelText,#mermaid-svg-g4uOpk6gtuGnIoUX .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .loopText,#mermaid-svg-g4uOpk6gtuGnIoUX .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-g4uOpk6gtuGnIoUX .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-g4uOpk6gtuGnIoUX .noteText,#mermaid-svg-g4uOpk6gtuGnIoUX .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-g4uOpk6gtuGnIoUX .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-g4uOpk6gtuGnIoUX .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-g4uOpk6gtuGnIoUX .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-g4uOpk6gtuGnIoUX .actorPopupMenu{position:absolute;}#mermaid-svg-g4uOpk6gtuGnIoUX .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-g4uOpk6gtuGnIoUX .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-g4uOpk6gtuGnIoUX .actor-man circle,#mermaid-svg-g4uOpk6gtuGnIoUX line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-g4uOpk6gtuGnIoUX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Fetch Offset 3658000 定位 Segment 3657291 二分查找 Index Offset 3658000 返回物理位置 Position 892341 从 Position 顺序扫描 找到目标消息 返回消息数据
5. 高可用设计:副本与 ISR
5.1 Replication 架构
#mermaid-svg-5IqLv39M8tOh9Cyy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5IqLv39M8tOh9Cyy .error-icon{fill:#552222;}#mermaid-svg-5IqLv39M8tOh9Cyy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5IqLv39M8tOh9Cyy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5IqLv39M8tOh9Cyy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5IqLv39M8tOh9Cyy .marker.cross{stroke:#333333;}#mermaid-svg-5IqLv39M8tOh9Cyy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5IqLv39M8tOh9Cyy p{margin:0;}#mermaid-svg-5IqLv39M8tOh9Cyy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster-label text{fill:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster-label span{color:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster-label span p{background-color:transparent;}#mermaid-svg-5IqLv39M8tOh9Cyy .label text,#mermaid-svg-5IqLv39M8tOh9Cyy span{fill:#333;color:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy .node rect,#mermaid-svg-5IqLv39M8tOh9Cyy .node circle,#mermaid-svg-5IqLv39M8tOh9Cyy .node ellipse,#mermaid-svg-5IqLv39M8tOh9Cyy .node polygon,#mermaid-svg-5IqLv39M8tOh9Cyy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5IqLv39M8tOh9Cyy .rough-node .label text,#mermaid-svg-5IqLv39M8tOh9Cyy .node .label text,#mermaid-svg-5IqLv39M8tOh9Cyy .image-shape .label,#mermaid-svg-5IqLv39M8tOh9Cyy .icon-shape .label{text-anchor:middle;}#mermaid-svg-5IqLv39M8tOh9Cyy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5IqLv39M8tOh9Cyy .rough-node .label,#mermaid-svg-5IqLv39M8tOh9Cyy .node .label,#mermaid-svg-5IqLv39M8tOh9Cyy .image-shape .label,#mermaid-svg-5IqLv39M8tOh9Cyy .icon-shape .label{text-align:center;}#mermaid-svg-5IqLv39M8tOh9Cyy .node.clickable{cursor:pointer;}#mermaid-svg-5IqLv39M8tOh9Cyy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5IqLv39M8tOh9Cyy .arrowheadPath{fill:#333333;}#mermaid-svg-5IqLv39M8tOh9Cyy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5IqLv39M8tOh9Cyy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5IqLv39M8tOh9Cyy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5IqLv39M8tOh9Cyy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5IqLv39M8tOh9Cyy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5IqLv39M8tOh9Cyy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster text{fill:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy .cluster span{color:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5IqLv39M8tOh9Cyy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5IqLv39M8tOh9Cyy rect.text{fill:none;stroke-width:0;}#mermaid-svg-5IqLv39M8tOh9Cyy .icon-shape,#mermaid-svg-5IqLv39M8tOh9Cyy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5IqLv39M8tOh9Cyy .icon-shape p,#mermaid-svg-5IqLv39M8tOh9Cyy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5IqLv39M8tOh9Cyy .icon-shape .label rect,#mermaid-svg-5IqLv39M8tOh9Cyy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5IqLv39M8tOh9Cyy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5IqLv39M8tOh9Cyy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5IqLv39M8tOh9Cyy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Partition-0-Replication
Leader Broker 1 处理读写请求
Follower 1 Broker 2 同步数据
Follower 2 Broker 3 同步数据
Producer
Consumer
5.2 ISR(In-Sync Replicas)机制
- AR(Assigned Replicas):分配给 Partition 的所有副本
- ISR :与 Leader 保持同步的副本集合(同步滞后不超过
replica.lag.time.max.ms) - OSR:超出同步阈值的副本(Out-of-Sync Replicas)
关键公式:
AR = ISR + OSR
Leader 选举策略:
- unclean.leader.election.enable=false(默认):仅从 ISR 中选举 Leader,保证数据不丢失但可用性降低
- unclean.leader.election.enable=true:允许从 OSR 中选举 Leader,提升可用性但可能丢失数据
5.3 HW 与 LEO
#mermaid-svg-5J8VPCvrmEn6Iu1E{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5J8VPCvrmEn6Iu1E .error-icon{fill:#552222;}#mermaid-svg-5J8VPCvrmEn6Iu1E .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5J8VPCvrmEn6Iu1E .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .marker.cross{stroke:#333333;}#mermaid-svg-5J8VPCvrmEn6Iu1E svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5J8VPCvrmEn6Iu1E p{margin:0;}#mermaid-svg-5J8VPCvrmEn6Iu1E .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster-label text{fill:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster-label span{color:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster-label span p{background-color:transparent;}#mermaid-svg-5J8VPCvrmEn6Iu1E .label text,#mermaid-svg-5J8VPCvrmEn6Iu1E span{fill:#333;color:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .node rect,#mermaid-svg-5J8VPCvrmEn6Iu1E .node circle,#mermaid-svg-5J8VPCvrmEn6Iu1E .node ellipse,#mermaid-svg-5J8VPCvrmEn6Iu1E .node polygon,#mermaid-svg-5J8VPCvrmEn6Iu1E .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .rough-node .label text,#mermaid-svg-5J8VPCvrmEn6Iu1E .node .label text,#mermaid-svg-5J8VPCvrmEn6Iu1E .image-shape .label,#mermaid-svg-5J8VPCvrmEn6Iu1E .icon-shape .label{text-anchor:middle;}#mermaid-svg-5J8VPCvrmEn6Iu1E .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .rough-node .label,#mermaid-svg-5J8VPCvrmEn6Iu1E .node .label,#mermaid-svg-5J8VPCvrmEn6Iu1E .image-shape .label,#mermaid-svg-5J8VPCvrmEn6Iu1E .icon-shape .label{text-align:center;}#mermaid-svg-5J8VPCvrmEn6Iu1E .node.clickable{cursor:pointer;}#mermaid-svg-5J8VPCvrmEn6Iu1E .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .arrowheadPath{fill:#333333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5J8VPCvrmEn6Iu1E .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5J8VPCvrmEn6Iu1E .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5J8VPCvrmEn6Iu1E .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster text{fill:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E .cluster span{color:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5J8VPCvrmEn6Iu1E .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5J8VPCvrmEn6Iu1E rect.text{fill:none;stroke-width:0;}#mermaid-svg-5J8VPCvrmEn6Iu1E .icon-shape,#mermaid-svg-5J8VPCvrmEn6Iu1E .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5J8VPCvrmEn6Iu1E .icon-shape p,#mermaid-svg-5J8VPCvrmEn6Iu1E .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5J8VPCvrmEn6Iu1E .icon-shape .label rect,#mermaid-svg-5J8VPCvrmEn6Iu1E .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5J8VPCvrmEn6Iu1E .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5J8VPCvrmEn6Iu1E .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5J8VPCvrmEn6Iu1E :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Follower-2
Follower-1
Leader
HW 10
LEO 12
Messages 1 to 12
HW 10
LEO 11
HW 10
LEO 10
- LEO(Log End Offset):副本最后一条消息的 Offset + 1
- HW(High Watermark):ISR 中所有副本的最小 LEO,消费者只能读取 HW 之前的消息
6. 生产者原理与优化
6.1 生产者发送流程
#mermaid-svg-ww5DuyoihgHHsAR0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ww5DuyoihgHHsAR0 .error-icon{fill:#552222;}#mermaid-svg-ww5DuyoihgHHsAR0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ww5DuyoihgHHsAR0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ww5DuyoihgHHsAR0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ww5DuyoihgHHsAR0 .marker.cross{stroke:#333333;}#mermaid-svg-ww5DuyoihgHHsAR0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ww5DuyoihgHHsAR0 p{margin:0;}#mermaid-svg-ww5DuyoihgHHsAR0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster-label text{fill:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster-label span{color:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster-label span p{background-color:transparent;}#mermaid-svg-ww5DuyoihgHHsAR0 .label text,#mermaid-svg-ww5DuyoihgHHsAR0 span{fill:#333;color:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 .node rect,#mermaid-svg-ww5DuyoihgHHsAR0 .node circle,#mermaid-svg-ww5DuyoihgHHsAR0 .node ellipse,#mermaid-svg-ww5DuyoihgHHsAR0 .node polygon,#mermaid-svg-ww5DuyoihgHHsAR0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ww5DuyoihgHHsAR0 .rough-node .label text,#mermaid-svg-ww5DuyoihgHHsAR0 .node .label text,#mermaid-svg-ww5DuyoihgHHsAR0 .image-shape .label,#mermaid-svg-ww5DuyoihgHHsAR0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ww5DuyoihgHHsAR0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ww5DuyoihgHHsAR0 .rough-node .label,#mermaid-svg-ww5DuyoihgHHsAR0 .node .label,#mermaid-svg-ww5DuyoihgHHsAR0 .image-shape .label,#mermaid-svg-ww5DuyoihgHHsAR0 .icon-shape .label{text-align:center;}#mermaid-svg-ww5DuyoihgHHsAR0 .node.clickable{cursor:pointer;}#mermaid-svg-ww5DuyoihgHHsAR0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ww5DuyoihgHHsAR0 .arrowheadPath{fill:#333333;}#mermaid-svg-ww5DuyoihgHHsAR0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ww5DuyoihgHHsAR0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ww5DuyoihgHHsAR0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ww5DuyoihgHHsAR0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ww5DuyoihgHHsAR0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ww5DuyoihgHHsAR0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster text{fill:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 .cluster span{color:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ww5DuyoihgHHsAR0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ww5DuyoihgHHsAR0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ww5DuyoihgHHsAR0 .icon-shape,#mermaid-svg-ww5DuyoihgHHsAR0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ww5DuyoihgHHsAR0 .icon-shape p,#mermaid-svg-ww5DuyoihgHHsAR0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ww5DuyoihgHHsAR0 .icon-shape .label rect,#mermaid-svg-ww5DuyoihgHHsAR0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ww5DuyoihgHHsAR0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ww5DuyoihgHHsAR0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ww5DuyoihgHHsAR0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Producer Client
ProducerRecord
序列化器 Serializer
分区器 Partitioner
消息累加器 RecordAccumulator
Sender线程
Broker 1
Broker 2
Broker 3
6.2 分区策略
生产者发送消息时,通过 Partitioner 决定目标 Partition:
- 指定 Partition:直接发送到指定分区
- 指定 Key :
hash(key) % partitionNum,保证相同 Key 的消息顺序性 - 未指定 Key (Sticky Partitioner 2.4+):
- 先粘在一个分区发送一批数据
- 批次满或超时后切换到下一个分区
- 避免数据倾斜,提升批处理效率
6.3 ACK 机制与可靠性
| acks 配置 | 说明 | 可靠性 | 吞吐量 |
|---|---|---|---|
acks=0 |
发完即忘,不等待确认 | 最低 | 最高 |
acks=1 |
等待 Leader 确认 | 中等 | 中等 |
acks=all |
等待 ISR 中所有副本确认 | 最高 | 最低 |
最小副本数配置:
properties
min.insync.replicas=2 # ISR 中至少要有 2 个副本才能写入
配合 acks=all 使用,可防止写入到只有一个 Leader 的危险状态。
6.4 幂等性与事务
幂等性 Producer (enable.idempotence=true):
- 通过 PID(Producer ID)和 Sequence Number 去重
- 保证单分区、单会话的 Exactly-Once 语义
事务 Producer:
- 支持跨 Partition 的原子写入
- 配合 Consumer 的
isolation.level=read_committed,实现端到端 Exactly-Once
Broker Transaction Coordinator Producer Broker Transaction Coordinator Producer #mermaid-svg-rdgfW3c5davhfjCu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rdgfW3c5davhfjCu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rdgfW3c5davhfjCu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rdgfW3c5davhfjCu .error-icon{fill:#552222;}#mermaid-svg-rdgfW3c5davhfjCu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rdgfW3c5davhfjCu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rdgfW3c5davhfjCu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rdgfW3c5davhfjCu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rdgfW3c5davhfjCu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rdgfW3c5davhfjCu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rdgfW3c5davhfjCu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rdgfW3c5davhfjCu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rdgfW3c5davhfjCu .marker.cross{stroke:#333333;}#mermaid-svg-rdgfW3c5davhfjCu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rdgfW3c5davhfjCu p{margin:0;}#mermaid-svg-rdgfW3c5davhfjCu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rdgfW3c5davhfjCu text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-rdgfW3c5davhfjCu .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rdgfW3c5davhfjCu .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-rdgfW3c5davhfjCu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-rdgfW3c5davhfjCu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-rdgfW3c5davhfjCu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-rdgfW3c5davhfjCu .sequenceNumber{fill:white;}#mermaid-svg-rdgfW3c5davhfjCu #sequencenumber{fill:#333;}#mermaid-svg-rdgfW3c5davhfjCu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-rdgfW3c5davhfjCu .messageText{fill:#333;stroke:none;}#mermaid-svg-rdgfW3c5davhfjCu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rdgfW3c5davhfjCu .labelText,#mermaid-svg-rdgfW3c5davhfjCu .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-rdgfW3c5davhfjCu .loopText,#mermaid-svg-rdgfW3c5davhfjCu .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-rdgfW3c5davhfjCu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rdgfW3c5davhfjCu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-rdgfW3c5davhfjCu .noteText,#mermaid-svg-rdgfW3c5davhfjCu .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-rdgfW3c5davhfjCu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rdgfW3c5davhfjCu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rdgfW3c5davhfjCu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rdgfW3c5davhfjCu .actorPopupMenu{position:absolute;}#mermaid-svg-rdgfW3c5davhfjCu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-rdgfW3c5davhfjCu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rdgfW3c5davhfjCu .actor-man circle,#mermaid-svg-rdgfW3c5davhfjCu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-rdgfW3c5davhfjCu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} InitTransactions PID 分配 beginTransaction 发送消息批次 1 发送消息批次 2 sendOffsetsToTransaction commitTransaction 标记事务提交 确认
7. 消费者组与 Rebalance
7.1 消费者组模型
#mermaid-svg-suKvusbGTQovQBtZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-suKvusbGTQovQBtZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-suKvusbGTQovQBtZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-suKvusbGTQovQBtZ .error-icon{fill:#552222;}#mermaid-svg-suKvusbGTQovQBtZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-suKvusbGTQovQBtZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-suKvusbGTQovQBtZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-suKvusbGTQovQBtZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-suKvusbGTQovQBtZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-suKvusbGTQovQBtZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-suKvusbGTQovQBtZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-suKvusbGTQovQBtZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-suKvusbGTQovQBtZ .marker.cross{stroke:#333333;}#mermaid-svg-suKvusbGTQovQBtZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-suKvusbGTQovQBtZ p{margin:0;}#mermaid-svg-suKvusbGTQovQBtZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-suKvusbGTQovQBtZ .cluster-label text{fill:#333;}#mermaid-svg-suKvusbGTQovQBtZ .cluster-label span{color:#333;}#mermaid-svg-suKvusbGTQovQBtZ .cluster-label span p{background-color:transparent;}#mermaid-svg-suKvusbGTQovQBtZ .label text,#mermaid-svg-suKvusbGTQovQBtZ span{fill:#333;color:#333;}#mermaid-svg-suKvusbGTQovQBtZ .node rect,#mermaid-svg-suKvusbGTQovQBtZ .node circle,#mermaid-svg-suKvusbGTQovQBtZ .node ellipse,#mermaid-svg-suKvusbGTQovQBtZ .node polygon,#mermaid-svg-suKvusbGTQovQBtZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-suKvusbGTQovQBtZ .rough-node .label text,#mermaid-svg-suKvusbGTQovQBtZ .node .label text,#mermaid-svg-suKvusbGTQovQBtZ .image-shape .label,#mermaid-svg-suKvusbGTQovQBtZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-suKvusbGTQovQBtZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-suKvusbGTQovQBtZ .rough-node .label,#mermaid-svg-suKvusbGTQovQBtZ .node .label,#mermaid-svg-suKvusbGTQovQBtZ .image-shape .label,#mermaid-svg-suKvusbGTQovQBtZ .icon-shape .label{text-align:center;}#mermaid-svg-suKvusbGTQovQBtZ .node.clickable{cursor:pointer;}#mermaid-svg-suKvusbGTQovQBtZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-suKvusbGTQovQBtZ .arrowheadPath{fill:#333333;}#mermaid-svg-suKvusbGTQovQBtZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-suKvusbGTQovQBtZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-suKvusbGTQovQBtZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-suKvusbGTQovQBtZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-suKvusbGTQovQBtZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-suKvusbGTQovQBtZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-suKvusbGTQovQBtZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-suKvusbGTQovQBtZ .cluster text{fill:#333;}#mermaid-svg-suKvusbGTQovQBtZ .cluster span{color:#333;}#mermaid-svg-suKvusbGTQovQBtZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-suKvusbGTQovQBtZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-suKvusbGTQovQBtZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-suKvusbGTQovQBtZ .icon-shape,#mermaid-svg-suKvusbGTQovQBtZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-suKvusbGTQovQBtZ .icon-shape p,#mermaid-svg-suKvusbGTQovQBtZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-suKvusbGTQovQBtZ .icon-shape .label rect,#mermaid-svg-suKvusbGTQovQBtZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-suKvusbGTQovQBtZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-suKvusbGTQovQBtZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-suKvusbGTQovQBtZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Topic Orders 6 Partitions
Consumer Group Order-Processors
Consumer 1 分配 P0 P1
Consumer 2 分配 P2 P3
Consumer 3 分配 P4 P5
Partition 0
Partition 1
Partition 2
Partition 3
Partition 4
Partition 5
核心规则:
- 一个 Partition 只能被同一个 Consumer Group 内的一个 Consumer 消费
- 一个 Consumer 可以消费多个 Partition
- Consumer 数量建议不超过 Partition 数量,否则多余的 Consumer 将空闲
7.2 Rebalance 触发与协议
触发条件:
- Consumer Group 成员发生变化(加入/离开/崩溃)
- Topic 的 Partition 数量发生变化
- 消费者主动调用
unsubscribe()
分区分配策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Range(默认) | 按 Topic 范围分配,可能不均匀 | Partition 数能整除 Consumer 数 |
| RoundRobin | 轮询分配,较为均匀 | 订阅相同 Topic 时 |
| Sticky | 尽量保持现有分配,减少迁移 | 频繁 Rebalance 场景 |
| CooperativeSticky | 增量 Rebalance,2.4+ 推荐 | 大消费组,减少停顿 |
7.3 Rebalance 过程图解
Group Coordinator Consumer 3 Consumer 2 Consumer 1 Group Coordinator Consumer 3 Consumer 2 Consumer 1 #mermaid-svg-bvH4vYrayawovdiT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bvH4vYrayawovdiT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bvH4vYrayawovdiT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bvH4vYrayawovdiT .error-icon{fill:#552222;}#mermaid-svg-bvH4vYrayawovdiT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bvH4vYrayawovdiT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bvH4vYrayawovdiT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bvH4vYrayawovdiT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bvH4vYrayawovdiT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bvH4vYrayawovdiT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bvH4vYrayawovdiT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bvH4vYrayawovdiT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bvH4vYrayawovdiT .marker.cross{stroke:#333333;}#mermaid-svg-bvH4vYrayawovdiT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bvH4vYrayawovdiT p{margin:0;}#mermaid-svg-bvH4vYrayawovdiT .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bvH4vYrayawovdiT text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-bvH4vYrayawovdiT .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bvH4vYrayawovdiT .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-bvH4vYrayawovdiT .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-bvH4vYrayawovdiT .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-bvH4vYrayawovdiT #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-bvH4vYrayawovdiT .sequenceNumber{fill:white;}#mermaid-svg-bvH4vYrayawovdiT #sequencenumber{fill:#333;}#mermaid-svg-bvH4vYrayawovdiT #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-bvH4vYrayawovdiT .messageText{fill:#333;stroke:none;}#mermaid-svg-bvH4vYrayawovdiT .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bvH4vYrayawovdiT .labelText,#mermaid-svg-bvH4vYrayawovdiT .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-bvH4vYrayawovdiT .loopText,#mermaid-svg-bvH4vYrayawovdiT .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-bvH4vYrayawovdiT .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bvH4vYrayawovdiT .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-bvH4vYrayawovdiT .noteText,#mermaid-svg-bvH4vYrayawovdiT .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-bvH4vYrayawovdiT .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bvH4vYrayawovdiT .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bvH4vYrayawovdiT .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bvH4vYrayawovdiT .actorPopupMenu{position:absolute;}#mermaid-svg-bvH4vYrayawovdiT .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-bvH4vYrayawovdiT .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bvH4vYrayawovdiT .actor-man circle,#mermaid-svg-bvH4vYrayawovdiT line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-bvH4vYrayawovdiT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 初始状态 C1消费P0P1 C2消费P2P3 新状态 C1消费P0P1 C2消费P2P3 C3消费P4P5 JoinGroup请求 发现组成员变化触发Rebalance 通知Rebalance 通知Rebalance JoinGroup JoinGroup 选举Leader Consumer 返回成员列表 执行分区分配算法 SyncGroup分配方案 分配结果 P0 P1 分配结果 P2 P3 分配结果 P4 P5
7.4 Offset 管理
消费者通过 __consumer_offsets 内部 Topic 存储消费位移:
#mermaid-svg-gF1fk0bwT1ESFlEN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gF1fk0bwT1ESFlEN .error-icon{fill:#552222;}#mermaid-svg-gF1fk0bwT1ESFlEN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gF1fk0bwT1ESFlEN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gF1fk0bwT1ESFlEN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gF1fk0bwT1ESFlEN .marker.cross{stroke:#333333;}#mermaid-svg-gF1fk0bwT1ESFlEN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gF1fk0bwT1ESFlEN p{margin:0;}#mermaid-svg-gF1fk0bwT1ESFlEN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster-label text{fill:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster-label span{color:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster-label span p{background-color:transparent;}#mermaid-svg-gF1fk0bwT1ESFlEN .label text,#mermaid-svg-gF1fk0bwT1ESFlEN span{fill:#333;color:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN .node rect,#mermaid-svg-gF1fk0bwT1ESFlEN .node circle,#mermaid-svg-gF1fk0bwT1ESFlEN .node ellipse,#mermaid-svg-gF1fk0bwT1ESFlEN .node polygon,#mermaid-svg-gF1fk0bwT1ESFlEN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gF1fk0bwT1ESFlEN .rough-node .label text,#mermaid-svg-gF1fk0bwT1ESFlEN .node .label text,#mermaid-svg-gF1fk0bwT1ESFlEN .image-shape .label,#mermaid-svg-gF1fk0bwT1ESFlEN .icon-shape .label{text-anchor:middle;}#mermaid-svg-gF1fk0bwT1ESFlEN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gF1fk0bwT1ESFlEN .rough-node .label,#mermaid-svg-gF1fk0bwT1ESFlEN .node .label,#mermaid-svg-gF1fk0bwT1ESFlEN .image-shape .label,#mermaid-svg-gF1fk0bwT1ESFlEN .icon-shape .label{text-align:center;}#mermaid-svg-gF1fk0bwT1ESFlEN .node.clickable{cursor:pointer;}#mermaid-svg-gF1fk0bwT1ESFlEN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gF1fk0bwT1ESFlEN .arrowheadPath{fill:#333333;}#mermaid-svg-gF1fk0bwT1ESFlEN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gF1fk0bwT1ESFlEN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gF1fk0bwT1ESFlEN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gF1fk0bwT1ESFlEN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gF1fk0bwT1ESFlEN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gF1fk0bwT1ESFlEN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster text{fill:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN .cluster span{color:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gF1fk0bwT1ESFlEN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gF1fk0bwT1ESFlEN rect.text{fill:none;stroke-width:0;}#mermaid-svg-gF1fk0bwT1ESFlEN .icon-shape,#mermaid-svg-gF1fk0bwT1ESFlEN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gF1fk0bwT1ESFlEN .icon-shape p,#mermaid-svg-gF1fk0bwT1ESFlEN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gF1fk0bwT1ESFlEN .icon-shape .label rect,#mermaid-svg-gF1fk0bwT1ESFlEN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gF1fk0bwT1ESFlEN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gF1fk0bwT1ESFlEN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gF1fk0bwT1ESFlEN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Offset Storage Format
Offset Commit
Consumer
__consumer_offsets Topic
Key group topic partition
Value offset metadata timestamp
提交模式:
- 自动提交 (
enable.auto.commit=true):定期提交,可能重复消费或丢失消息 - 手动同步提交 (
commitSync()):可靠但阻塞 - 手动异步提交 (
commitAsync()):非阻塞,可能提交失败 - 带回调的异步提交:处理提交失败,实现重试
8. 性能优化与调优实践
8.1 生产者优化
properties
# 1. 批处理优化
batch.size=32768 # 批次大小 32KB,根据消息大小调整
linger.ms=10 # 等待 10ms 攒批,提升吞吐量
compression.type=lz4 # 启用压缩,降低网络带宽
# 2. 缓冲区优化
buffer.memory=67108864 # 缓冲区 64MB,防止发送阻塞
max.in.flight.requests.per.connection=5 # 允许 5 个未确认请求
# 3. 可靠性配置
acks=1 # 根据业务需求选择
retries=3 # 失败重试次数
enable.idempotence=true # 启用幂等性
8.2 消费者优化
properties
# 1. 拉取优化
fetch.min.bytes=50000 # 至少拉取 50KB 才返回
fetch.max.wait.ms=100 # 最多等待 100ms
max.poll.records=500 # 单次拉取最大消息数
# 2. 并行处理
max.poll.interval.ms=300000 # 处理超时时间,防止 Rebalance
session.timeout.ms=10000 # 会话超时
heartbeat.interval.ms=3000 # 心跳间隔(建议为 session.timeout.ms 的 1/3)
8.3 Broker 与 OS 层面优化
properties
# server.properties
num.network.threads=8 # 网络线程数
num.io.threads=16 # IO 线程数
log.segment.bytes=1073741824 # Segment 大小 1GB
log.retention.hours=168 # 保留 7 天
log.retention.bytes=-1 # 不限制总大小(或按磁盘容量设置)
操作系统调优:
bash
# 1. 文件描述符
ulimit -n 100000
# 2. 脏页刷新策略
vm.dirty_background_ratio=5
vm.dirty_ratio=10
# 3. 禁用交换分区或降低 Swappiness
vm.swappiness=1
# 4. 磁盘调度算法(SSD 使用 noop/deadline)
echo noop > /sys/block/sda/queue/scheduler
# 5. 开启 Transparent Huge Pages(谨慎使用)
8.4 监控关键指标
| 指标 | 说明 | 告警阈值建议 |
|---|---|---|
| UnderReplicatedPartitions | 副本不足的分区数 | 大于 0 立即告警 |
| OfflinePartitions | 离线分区数 | 大于 0 立即告警 |
| ActiveControllerCount | Active Controller 数量 | 不等于 1 立即告警 |
| RequestHandlerAvgIdlePercent | IO 线程空闲率 | 小于 20% 告警 |
| NetworkProcessorAvgIdlePercent | 网络线程空闲率 | 小于 20% 告警 |
| MessagesInPerSec | 每秒入站消息数 | 监控趋势 |
| ConsumerLag | 消费者延迟 | 根据业务 SLA 设定 |
9. 典型应用场景
9.1 场景对比图
#mermaid-svg-GbytWRCmigfOPLEN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GbytWRCmigfOPLEN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GbytWRCmigfOPLEN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GbytWRCmigfOPLEN .error-icon{fill:#552222;}#mermaid-svg-GbytWRCmigfOPLEN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GbytWRCmigfOPLEN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GbytWRCmigfOPLEN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GbytWRCmigfOPLEN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GbytWRCmigfOPLEN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GbytWRCmigfOPLEN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GbytWRCmigfOPLEN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GbytWRCmigfOPLEN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GbytWRCmigfOPLEN .marker.cross{stroke:#333333;}#mermaid-svg-GbytWRCmigfOPLEN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GbytWRCmigfOPLEN p{margin:0;}#mermaid-svg-GbytWRCmigfOPLEN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GbytWRCmigfOPLEN .cluster-label text{fill:#333;}#mermaid-svg-GbytWRCmigfOPLEN .cluster-label span{color:#333;}#mermaid-svg-GbytWRCmigfOPLEN .cluster-label span p{background-color:transparent;}#mermaid-svg-GbytWRCmigfOPLEN .label text,#mermaid-svg-GbytWRCmigfOPLEN span{fill:#333;color:#333;}#mermaid-svg-GbytWRCmigfOPLEN .node rect,#mermaid-svg-GbytWRCmigfOPLEN .node circle,#mermaid-svg-GbytWRCmigfOPLEN .node ellipse,#mermaid-svg-GbytWRCmigfOPLEN .node polygon,#mermaid-svg-GbytWRCmigfOPLEN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GbytWRCmigfOPLEN .rough-node .label text,#mermaid-svg-GbytWRCmigfOPLEN .node .label text,#mermaid-svg-GbytWRCmigfOPLEN .image-shape .label,#mermaid-svg-GbytWRCmigfOPLEN .icon-shape .label{text-anchor:middle;}#mermaid-svg-GbytWRCmigfOPLEN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GbytWRCmigfOPLEN .rough-node .label,#mermaid-svg-GbytWRCmigfOPLEN .node .label,#mermaid-svg-GbytWRCmigfOPLEN .image-shape .label,#mermaid-svg-GbytWRCmigfOPLEN .icon-shape .label{text-align:center;}#mermaid-svg-GbytWRCmigfOPLEN .node.clickable{cursor:pointer;}#mermaid-svg-GbytWRCmigfOPLEN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GbytWRCmigfOPLEN .arrowheadPath{fill:#333333;}#mermaid-svg-GbytWRCmigfOPLEN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GbytWRCmigfOPLEN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GbytWRCmigfOPLEN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GbytWRCmigfOPLEN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GbytWRCmigfOPLEN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GbytWRCmigfOPLEN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GbytWRCmigfOPLEN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GbytWRCmigfOPLEN .cluster text{fill:#333;}#mermaid-svg-GbytWRCmigfOPLEN .cluster span{color:#333;}#mermaid-svg-GbytWRCmigfOPLEN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GbytWRCmigfOPLEN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GbytWRCmigfOPLEN rect.text{fill:none;stroke-width:0;}#mermaid-svg-GbytWRCmigfOPLEN .icon-shape,#mermaid-svg-GbytWRCmigfOPLEN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GbytWRCmigfOPLEN .icon-shape p,#mermaid-svg-GbytWRCmigfOPLEN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GbytWRCmigfOPLEN .icon-shape .label rect,#mermaid-svg-GbytWRCmigfOPLEN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GbytWRCmigfOPLEN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GbytWRCmigfOPLEN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GbytWRCmigfOPLEN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Stream Processing
Kafka
Kafka Streams Flink
Database
Log Aggregation
App Server 1
Kafka
App Server 2
App Server 3
Elasticsearch
Grafana
Event-Driven Architecture
Order Service
Kafka
Payment Service
Inventory Service
Notification Service
9.2 场景详解
1. 异步解耦
- 订单系统下单后发送事件到 Kafka
- 库存、支付、物流系统独立消费处理
- 系统间解耦,提升可用性和扩展性
2. 日志聚合
- 应用服务将日志发送到 Kafka
- ELK(Elasticsearch + Logstash/Beat + Kibana)或 ClickHouse 消费
- 统一日志收集、检索和分析
3. 流式处理
- 实时数据管道:ETL 数据清洗与转换
- 实时监控:异常检测、风控规则引擎
- 实时推荐:基于用户行为的实时特征计算
4. 事件溯源(Event Sourcing)
- 将系统状态变更记录为不可变事件流
- 支持状态回放、审计追踪、系统重建
10. 总结
Kafka 的设计哲学可以概括为:以日志为中心、以分区为扩展单元、以副本为容错手段。理解以下核心要点,你就能在生产环境中游刃有余地使用 Kafka:
参考资料
- Apache Kafka 官方文档
- 《Kafka 权威指南》(Kafka: The Definitive Guide)
- 《深入理解 Kafka:核心设计与实践原理》
- Kafka Improvement Proposals (KIPs)