欢迎光临
我们一直在努力

Kafka 架构深度拆解:Broker、Partition、Replica 与 ISR 的协作机制

一、Kafka 基础架构概述

1.1 Kafka 的核心组件介绍

Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发并开源,现在是 Apache 软件基金会的一部分。Kafka 以其高吞吐量、可扩展性和持久性而闻名,被广泛用于日志聚合、实时数据流处理、事件溯源等多种场景。

Kafka 的核心组件包括 Broker、Topic、Partition、Replica 和 ISR(In-Sync Replicas)。这些组件相互协作,共同实现了 Kafka 的高可用性和高性能。

1.2 Broker 在 Kafka 中的作用与职责

Broker 是 Kafka 集群中的服务器节点,负责存储消息、处理客户端请求以及协调集群中的其他组件。每个 Broker 都有一个唯一的 ID,并维护着它所存储的分区和副本信息。

Broker 的主要职责包括:

  • 接收生产者发送的消息并存储到相应的分区中
  • 为消费者提供消息读取服务
  • 处理分区重分配和副本选举等集群管理任务
  • 监控集群状态并维护 ISR 列表
  • 在 Kafka 集群中,Broker 通过 ZooKeeper 或 KRaft 协调模式进行通信和状态管理。

    1.3 Partition 与 Replica 的关系

    Partition 是 Kafka 中 Topic 的物理分组,每个 Topic 可以被分为一个或多个 Partition。Partition 是 Kafka 实现并行处理和扩展的基本单位,每个 Partition 中的消息都是有序的,并且有一个唯一的偏移量(Offset)。

    Replica 是 Partition 的副本,用于实现数据冗余和高可用性。每个 Partition 可以有多个副本,分布在不同的 Broker 上。这些副本分为 Leader 和 Follower 两种角色,所有的读写请求都由 Leader 处理,Follower 只负责从 Leader 同步数据。

    Partition 和 Replica 的关系可以这样理解:Partition 是数据的基本单位,而 Replica 是 Partition 的冗余备份,两者共同构成了 Kafka 的数据存储与容错机制。

    #publish-mermaid-1788278620282-0{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;}}#publish-mermaid-1788278620282-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620282-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620282-0 .error-icon{fill:#552222;}#publish-mermaid-1788278620282-0 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278620282-0 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278620282-0 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278620282-0 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278620282-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278620282-0 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278620282-0 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278620282-0 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620282-0 .marker.cross{stroke:#333333;}#publish-mermaid-1788278620282-0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278620282-0 p{margin:0;}#publish-mermaid-1788278620282-0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1788278620282-0 .cluster-label text{fill:#333;}#publish-mermaid-1788278620282-0 .cluster-label span{color:#333;}#publish-mermaid-1788278620282-0 .cluster-label span p{background-color:transparent;}#publish-mermaid-1788278620282-0 .label text,#publish-mermaid-1788278620282-0 span{fill:#333;color:#333;}#publish-mermaid-1788278620282-0 .node rect,#publish-mermaid-1788278620282-0 .node circle,#publish-mermaid-1788278620282-0 .node ellipse,#publish-mermaid-1788278620282-0 .node polygon,#publish-mermaid-1788278620282-0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620282-0 .rough-node .label text,#publish-mermaid-1788278620282-0 .node .label text,#publish-mermaid-1788278620282-0 .image-shape .label,#publish-mermaid-1788278620282-0 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1788278620282-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1788278620282-0 .rough-node .label,#publish-mermaid-1788278620282-0 .node .label,#publish-mermaid-1788278620282-0 .image-shape .label,#publish-mermaid-1788278620282-0 .icon-shape .label{text-align:center;}#publish-mermaid-1788278620282-0 .node.clickable{cursor:pointer;}#publish-mermaid-1788278620282-0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1788278620282-0 .arrowheadPath{fill:#333333;}#publish-mermaid-1788278620282-0 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1788278620282-0 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1788278620282-0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278620282-0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620282-0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620282-0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1788278620282-0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1788278620282-0 .cluster text{fill:#333;}#publish-mermaid-1788278620282-0 .cluster span{color:#333;}#publish-mermaid-1788278620282-0 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;}#publish-mermaid-1788278620282-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1788278620282-0 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1788278620282-0 .icon-shape,#publish-mermaid-1788278620282-0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278620282-0 .icon-shape p,#publish-mermaid-1788278620282-0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1788278620282-0 .icon-shape .label rect,#publish-mermaid-1788278620282-0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620282-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1788278620282-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1788278620282-0 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node rect,#publish-mermaid-1788278620282-0 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620282-0 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620282-0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    生产者 Producer

    Broker 集群

    Topic 1

    Topic 2

    Partition 1.1

    Partition 1.2

    Partition 2.1

    Partition 2.2

    Leader Replica

    Follower Replica

    Leader Replica

    Follower Replica

    Leader Replica

    Follower Replica

    Leader Replica

    Follower Replica

    消费者 Consumer 1

    消费者 Consumer 2

    二、Partition 机制深度解析

    2.1 Partition 的基本概念

    Partition 是 Kafka 中 Topic 的基本组成单位,每个 Topic 可以分为多个 Partition,这种分区机制是 Kafka 实现高吞吐量和可扩展性的关键。每个 Partition 是一个有序的、不可变的消息序列,消息被追加到 Partition 的末尾。

    每个 Partition 中的每条消息都有一个唯一的序列号,称为偏移量(Offset),从 0 开始递增。Partition 的存在使得 Kafka 能够将数据分布到多个 Broker 上,从而实现水平扩展。

    2.2 Partition 的分布策略

    Kafka 提供了多种 Partition 分布策略,以确保数据在集群中均匀分布:

  • RoundRobin 分配策略:按照轮询方式将分区分配给 Broker,确保每个 Broker 分配到大致相同数量的分区。
  • Range 分配策略:将连续的分区范围分配给同一个 Broker,这种方式可能会导致数据分布不均衡。
  • 自定义分配策略:用户可以根据业务需求自定义分区分配策略,例如将相关性强的分区分配到同一个 Broker。
  • | 策略类型 | 实现原理 | 优点 | 缺点 | 适用场景 |

    |———|———|——|——|———|

    | RoundRobin | 按照轮询方式将分区分配给 Broker | 分区分布均匀,负载均衡效果好 | 可能导致相关分区分散 | 通用场景,特别是对数据 locality 要求不高的场景 |

    | Range | 将连续的分区范围分配给同一个 Broker | 相关分区集中在一起,便于查询 | 可能导致负载不均衡,某些 Broker 负载过高 | 对数据 locality 要求较高的场景 |

    | 自定义 | 根据业务需求自定义分区分配策略 | 灵活性高,可满足特定业务需求 | 实现复杂,需要深入了解业务 | 特定业务场景,如需要将相关数据分区在一起 |

    2.3 Partition 的读写机制

    Kafka 中 Partition 的读写机制是高吞吐量的关键:

    写入机制:

  • 生产者将消息发送给指定 Topic 的 Partition Leader
  • Leader 将消息写入本地日志并复制到所有 Follower 副本
  • 当所有 ISR(In-Sync Replicas)中的副本都成功复制消息后,Leader 才会向生产者确认写入成功
  • 消息被追加到 Partition 的末尾,并分配一个唯一的偏移量
  • 读取机制:

  • 消费者可以选择从一个或多个 Topic 的 Partition 读取消息
  • 消费者可以控制读取的起始位置(偏移量),可以重放历史消息或跳过某些消息
  • 消费者可以独立地维护每个 Partition 的消费位置
  • 多个消费者可以组成消费者组(Consumer Group),共同消费一个 Topic 的所有 Partition
  • 消费者Follower 副本Partition Leader生产者消费者Follower 副本Partition Leader生产者#publish-mermaid-1788278620392-1{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;}}#publish-mermaid-1788278620392-1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620392-1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620392-1 .error-icon{fill:#552222;}#publish-mermaid-1788278620392-1 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278620392-1 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278620392-1 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278620392-1 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278620392-1 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278620392-1 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278620392-1 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278620392-1 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620392-1 .marker.cross{stroke:#333333;}#publish-mermaid-1788278620392-1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278620392-1 p{margin:0;}#publish-mermaid-1788278620392-1 .actor{stroke:#9370DB;fill:#ECECFF;stroke-width:1;}#publish-mermaid-1788278620392-1 rect.actor.outer-path[data-look=\”neo\”]{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 rect.note[data-look=\”neo\”]{stroke:#aaaa33;fill:#fff5ad;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 text.actor>tspan{fill:black;stroke:none;}#publish-mermaid-1788278620392-1 .actor-line{stroke:#9370DB;}#publish-mermaid-1788278620392-1 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#publish-mermaid-1788278620392-1 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#publish-mermaid-1788278620392-1 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#publish-mermaid-1788278620392-1 [id$=\”-arrowhead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278620392-1 .sequenceNumber{fill:white;}#publish-mermaid-1788278620392-1 [id$=\”-sequencenumber\”]{fill:#333;}#publish-mermaid-1788278620392-1 [id$=\”-crosshead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278620392-1 .messageText{fill:#333;stroke:none;}#publish-mermaid-1788278620392-1 .labelBox{stroke:#9370DB;fill:#ECECFF;filter:none;}#publish-mermaid-1788278620392-1 .labelText,#publish-mermaid-1788278620392-1 .labelText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278620392-1 .loopText,#publish-mermaid-1788278620392-1 .loopText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278620392-1 .sectionTitle,#publish-mermaid-1788278620392-1 .sectionTitle>tspan{fill:black;stroke:none;}#publish-mermaid-1788278620392-1 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#9370DB;fill:#9370DB;}#publish-mermaid-1788278620392-1 .note{stroke:#aaaa33;fill:#fff5ad;}#publish-mermaid-1788278620392-1 .noteText,#publish-mermaid-1788278620392-1 .noteText>tspan{fill:black;stroke:none;font-weight:normal;}#publish-mermaid-1788278620392-1 .activation0{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278620392-1 .activation1{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278620392-1 .activation2{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278620392-1 .actorPopupMenu{position:absolute;}#publish-mermaid-1788278620392-1 .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));}#publish-mermaid-1788278620392-1 .actor-man circle,#publish-mermaid-1788278620392-1 line{fill:#ECECFF;stroke-width:2px;}#publish-mermaid-1788278620392-1 g rect.rect{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));stroke:#9370DB;}#publish-mermaid-1788278620392-1 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node rect,#publish-mermaid-1788278620392-1 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620392-1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}发送消息写入本地日志复制消息到 Follower确认复制成功等待所有 ISR 确认返回写入确认请求读取消息返回消息和偏移量

    三、Replica 机制详解

    3.1 Replica 的类型与角色

    Kafka 中的 Replica 主要分为以下几种类型和角色:

  • Leader Replica:每个 Partition 只有一个 Leader 副本,所有客户端的读写请求都由 Leader 处理。Leader 负责维护消息的顺序和一致性。
  • Follower Replica:Partition 可以有一个或多个 Follower 副本,它们负责从 Leader 同步数据,但不处理客户端请求。当 Leader 发生故障时,其中一个 Follower 会被选举为新的 Leader。
  • AR (Assigned Replicas):分配给一个 Partition 的所有 Replica 的集合,包括 Leader 和所有 Follower。
  • ISR (In-Sync Replicas):与 Leader 保持同步的 Follower 副本集合。只有 ISR 中的副本才有资格被选举为新的 Leader。
  • OSR (Out-of-Sync Replicas):与 Leader 不同步的副本集合。当副本落后 Leader 的时间超过 replica.lag.time.max.ms 参数设置的值时,它会被移出 ISR 并加入 OSR。
  • 3.2 Replication 的工作原理

    Kafka 的 Replication 机制是保证数据高可用和一致性的关键:

  • 数据同步:Follower 通过定期向 Leader 发送FetchRequest请求来获取最新的消息。Leader 收到请求后,将新的消息发送给 Follower。
  • 同步确认:Follower 收到消息后,会将其写入本地日志,并向 Leader 发送确认。Leader 会维护每个 Follower 的同步状态。
  • ISR 维护:Kafka 会定期检查每个 Follower 的同步状态。如果 Follower 在 replica.lag.time.max.ms 时间内没有向 Leader 发送请求,或者虽然发送了请求但消息落后 Leader 的数量超过 replica.lag.max.messages,它会被移出 ISR。
  • Leader 选举:当 Leader 发生故障时,Controller 会从 ISR 中选举一个新的 Leader。选举过程会考虑多个因素,包括副本的可用性、数据同步程度等。
  • #publish-mermaid-1788278620788-2{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;}}#publish-mermaid-1788278620788-2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620788-2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620788-2 .error-icon{fill:#552222;}#publish-mermaid-1788278620788-2 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278620788-2 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278620788-2 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278620788-2 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278620788-2 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278620788-2 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278620788-2 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278620788-2 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620788-2 .marker.cross{stroke:#333333;}#publish-mermaid-1788278620788-2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278620788-2 p{margin:0;}#publish-mermaid-1788278620788-2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1788278620788-2 .cluster-label text{fill:#333;}#publish-mermaid-1788278620788-2 .cluster-label span{color:#333;}#publish-mermaid-1788278620788-2 .cluster-label span p{background-color:transparent;}#publish-mermaid-1788278620788-2 .label text,#publish-mermaid-1788278620788-2 span{fill:#333;color:#333;}#publish-mermaid-1788278620788-2 .node rect,#publish-mermaid-1788278620788-2 .node circle,#publish-mermaid-1788278620788-2 .node ellipse,#publish-mermaid-1788278620788-2 .node polygon,#publish-mermaid-1788278620788-2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620788-2 .rough-node .label text,#publish-mermaid-1788278620788-2 .node .label text,#publish-mermaid-1788278620788-2 .image-shape .label,#publish-mermaid-1788278620788-2 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1788278620788-2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1788278620788-2 .rough-node .label,#publish-mermaid-1788278620788-2 .node .label,#publish-mermaid-1788278620788-2 .image-shape .label,#publish-mermaid-1788278620788-2 .icon-shape .label{text-align:center;}#publish-mermaid-1788278620788-2 .node.clickable{cursor:pointer;}#publish-mermaid-1788278620788-2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1788278620788-2 .arrowheadPath{fill:#333333;}#publish-mermaid-1788278620788-2 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1788278620788-2 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1788278620788-2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278620788-2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620788-2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620788-2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1788278620788-2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1788278620788-2 .cluster text{fill:#333;}#publish-mermaid-1788278620788-2 .cluster span{color:#333;}#publish-mermaid-1788278620788-2 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;}#publish-mermaid-1788278620788-2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1788278620788-2 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1788278620788-2 .icon-shape,#publish-mermaid-1788278620788-2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278620788-2 .icon-shape p,#publish-mermaid-1788278620788-2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1788278620788-2 .icon-shape .label rect,#publish-mermaid-1788278620788-2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620788-2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1788278620788-2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1788278620788-2 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node rect,#publish-mermaid-1788278620788-2 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620788-2 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620788-2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Leader Replica

    接收生产者消息

    写入本地日志

    将消息发送给 Follower

    Follower Replica 1

    Follower Replica 2

    Follower Replica 3

    写入本地日志

    写入本地日志

    写入本地日志

    向 Leader 确认

    Leader 收到确认

    更新 ISR 状态

    向生产者确认写入成功

    3.3 Replication 的配置优化

    为了优化 Kafka 的 Replication 机制,可以调整以下关键参数:

  • replication.factor:指定每个 Partition 的副本数量,通常设置为 3 或更高以提供高可用性。
  • min.insync.replicas:指定 ISR 中必须包含的最小副本数,以确保数据一致性。例如,如果设置为 2,则至少需要有 2 个副本(包括 Leader)同步成功,生产者才会收到写入确认。
  • replica.lag.time.max.ms:指定 Follower 可以落后 Leader 的最长时间,超过这个时间 Follower 会被移出 ISR。
  • replica.lag.max.messages:指定 Follower 可以落后 Leader 的最大消息数,超过这个数量 Follower 会被移出 ISR。
  • unclean.leader.election.enable:指定是否允许从非 ISR 副本中选举 Leader。如果设置为 false,则只有在 ISR 不为空时才能选举新的 Leader,这可以防止数据丢失,但可能导致分区在较长时间内不可用。
  • | 参数名 | 默认值 | 推荐值 | 说明 |

    |——-|——-|——-|——|

    | replication.factor | 1 | 3 | 每个 Partition 的副本数量 |

    | min.insync.replicas | 1 | 2 | ISR 中必须包含的最小副本数 |

    | replica.lag.time.max.ms | 30000 | 30000 | Follower 可以落后 Leader 的最长时间 |

    | replica.lag.max.messages | 400 | 10000 | Follower 可以落后 Leader 的最大消息数 |

    | unclean.leader.election.enable | false | false | 是否允许从非 ISR 副本中选举 Leader |

    四、ISR 机制深入分析

    4.1 ISR 的概念与重要性

    ISR(In-Sync Replicas)是 Kafka 中与 Leader 副本保持同步的副本集合,是 Kafka 高可用性和数据一致性的核心机制。ISR 中至少包含 Leader 副本,可以包含多个 Follower 副本。

    ISR 的重要性体现在以下几个方面:

  • 数据一致性保证:生产者写入消息时,只有当 ISR 中所有副本都成功复制消息后,才会向生产者确认写入成功,这确保了即使 Leader 故障,数据也不会丢失。
  • 故障恢复能力:当 Leader 故障时,可以从 ISR 中快速选举新的 Leader,因为 ISR 中的副本都是最新的,数据不会丢失。
  • 负载均衡:通过调整 ISR 的大小,可以在数据一致性和可用性之间取得平衡,避免因等待所有副本同步而导致性能下降。
  • 4.2 ISR 的动态维护机制

    Kafka 采用动态机制来维护 ISR,主要过程如下:

  • 心跳检测:每个 Follower 副本都会定期向 Leader 发送心跳请求,表明自己仍然存活并正在同步数据。
  • 滞后检测:Leader 会跟踪每个 Follower 副本的同步状态,包括接收消息的最大偏移量。Leader 会比较自己的日志末端偏移和 Follower 的日志末端偏移,计算 Follower 落后的消息数量。
  • 超时判断:如果 Follower 在 replica.lag.time.max.ms 时间内没有向 Leader 发送心跳请求,或者虽然发送了请求但落后的消息数量超过 replica.lag.max.messages,Leader 会将该 Follower 移出 ISR。
  • 重新加入 ISR:当 Follower 追上 Leader 的数据后,可以重新加入 ISR。这个过程通常由 Controller 定期检查并触发。
  • #publish-mermaid-1788278620893-3{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;}}#publish-mermaid-1788278620893-3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620893-3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278620893-3 .error-icon{fill:#552222;}#publish-mermaid-1788278620893-3 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278620893-3 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278620893-3 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278620893-3 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278620893-3 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278620893-3 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278620893-3 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278620893-3 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620893-3 .marker.cross{stroke:#333333;}#publish-mermaid-1788278620893-3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278620893-3 p{margin:0;}#publish-mermaid-1788278620893-3 defs [id$=\”-barbEnd\”]{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620893-3 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#publish-mermaid-1788278620893-3 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#publish-mermaid-1788278620893-3 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#publish-mermaid-1788278620893-3 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#publish-mermaid-1788278620893-3 g.stateGroup line{stroke:#333333;stroke-width:1;}#publish-mermaid-1788278620893-3 .transition{stroke:#333333;stroke-width:1;fill:none;}#publish-mermaid-1788278620893-3 .stateGroup .composit{fill:white;border-bottom:1px;}#publish-mermaid-1788278620893-3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#publish-mermaid-1788278620893-3 .state-note{stroke:#aaaa33;fill:#fff5ad;}#publish-mermaid-1788278620893-3 .state-note text{fill:black;stroke:none;font-size:10px;}#publish-mermaid-1788278620893-3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#publish-mermaid-1788278620893-3 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#publish-mermaid-1788278620893-3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278620893-3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620893-3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278620893-3 .edgeLabel .label text{fill:#333;}#publish-mermaid-1788278620893-3 .label div .edgeLabel{color:#333;}#publish-mermaid-1788278620893-3 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#publish-mermaid-1788278620893-3 .node circle.state-start{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620893-3 .node .fork-join{fill:#333333;stroke:#333333;}#publish-mermaid-1788278620893-3 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#publish-mermaid-1788278620893-3 .end-state-inner{fill:white;stroke-width:1.5;}#publish-mermaid-1788278620893-3 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620893-3 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620893-3 [id$=\”-barbEnd\”]{fill:#333333;}#publish-mermaid-1788278620893-3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620893-3 .cluster-label,#publish-mermaid-1788278620893-3 .nodeLabel{color:#131300;}#publish-mermaid-1788278620893-3 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#publish-mermaid-1788278620893-3 .statediagram-state .divider{stroke:#9370DB;}#publish-mermaid-1788278620893-3 .statediagram-state .title-state{rx:5px;ry:5px;}#publish-mermaid-1788278620893-3 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#publish-mermaid-1788278620893-3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#publish-mermaid-1788278620893-3 .statediagram-cluster .inner{rx:0;ry:0;}#publish-mermaid-1788278620893-3 .statediagram-state rect.basic{rx:5px;ry:5px;}#publish-mermaid-1788278620893-3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#publish-mermaid-1788278620893-3 .note-edge{stroke-dasharray:5;}#publish-mermaid-1788278620893-3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#publish-mermaid-1788278620893-3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#publish-mermaid-1788278620893-3 .statediagram-note text{fill:black;}#publish-mermaid-1788278620893-3 .statediagram-note .nodeLabel{color:black;}#publish-mermaid-1788278620893-3 .statediagram .edgeLabel{color:red;}#publish-mermaid-1788278620893-3 [id$=\”-dependencyStart\”],#publish-mermaid-1788278620893-3 [id$=\”-dependencyEnd\”]{fill:#333333;stroke:#333333;stroke-width:1;}#publish-mermaid-1788278620893-3 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].statediagram-cluster rect.outer{rx:5px;ry:5px;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node rect,#publish-mermaid-1788278620893-3 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278620893-3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}检测心跳和同步状态同步正常超时或落后消息过多追上数据重新加入 ISR成为新 Leader关闭或故障

    Leader

    Follower

    InSyncReplica

    OutOfSyncReplica

    4.3 ISR 的选举与故障转移

    当 Kafka 集群中的 Leader 副本发生故障时,需要从 ISR 中选举新的 Leader。这个过程通常由 Controller 协调完成:

  • 故障检测:Controller 会定期检测每个 Broker 和副本的状态。当检测到 Leader 副本故障时,会触发 Leader 选举过程。
  • 选举过程:Controller 会从 ISR 中选择一个副本作为新的 Leader。选举策略通常考虑以下因素:
    • 副本的可用性(Broker 是否存活)
    • 副本的数据同步程度(是否是最新的)
    • 负载均衡(选择负载较低的 Broker)
  • 状态更新:选举完成后,Controller 会更新集群的元数据,通知所有 Broker 和客户端新的 Leader 是谁。
  • 客户端重定向:生产者和消费者在连接到原来的 Leader 失败后,会从 ZooKeeper 或 Broker 获取最新的元数据,然后连接到新的 Leader。
  • 故障恢复:原来的 Leader 恢复后,会自动成为 Follower,并从新的 Leader 同步数据,最终重新加入 ISR。
  • #publish-mermaid-1788278621075-4{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;}}#publish-mermaid-1788278621075-4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621075-4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621075-4 .error-icon{fill:#552222;}#publish-mermaid-1788278621075-4 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278621075-4 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278621075-4 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278621075-4 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278621075-4 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278621075-4 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278621075-4 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278621075-4 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278621075-4 .marker.cross{stroke:#333333;}#publish-mermaid-1788278621075-4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278621075-4 p{margin:0;}#publish-mermaid-1788278621075-4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1788278621075-4 .cluster-label text{fill:#333;}#publish-mermaid-1788278621075-4 .cluster-label span{color:#333;}#publish-mermaid-1788278621075-4 .cluster-label span p{background-color:transparent;}#publish-mermaid-1788278621075-4 .label text,#publish-mermaid-1788278621075-4 span{fill:#333;color:#333;}#publish-mermaid-1788278621075-4 .node rect,#publish-mermaid-1788278621075-4 .node circle,#publish-mermaid-1788278621075-4 .node ellipse,#publish-mermaid-1788278621075-4 .node polygon,#publish-mermaid-1788278621075-4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621075-4 .rough-node .label text,#publish-mermaid-1788278621075-4 .node .label text,#publish-mermaid-1788278621075-4 .image-shape .label,#publish-mermaid-1788278621075-4 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1788278621075-4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1788278621075-4 .rough-node .label,#publish-mermaid-1788278621075-4 .node .label,#publish-mermaid-1788278621075-4 .image-shape .label,#publish-mermaid-1788278621075-4 .icon-shape .label{text-align:center;}#publish-mermaid-1788278621075-4 .node.clickable{cursor:pointer;}#publish-mermaid-1788278621075-4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1788278621075-4 .arrowheadPath{fill:#333333;}#publish-mermaid-1788278621075-4 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1788278621075-4 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1788278621075-4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278621075-4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621075-4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621075-4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1788278621075-4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1788278621075-4 .cluster text{fill:#333;}#publish-mermaid-1788278621075-4 .cluster span{color:#333;}#publish-mermaid-1788278621075-4 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;}#publish-mermaid-1788278621075-4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1788278621075-4 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1788278621075-4 .icon-shape,#publish-mermaid-1788278621075-4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278621075-4 .icon-shape p,#publish-mermaid-1788278621075-4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1788278621075-4 .icon-shape .label rect,#publish-mermaid-1788278621075-4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621075-4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1788278621075-4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1788278621075-4 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node rect,#publish-mermaid-1788278621075-4 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621075-4 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621075-4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    检测到 Leader 故障

    Controller 介入

    从 ISR 中选择新 Leader

    更新集群元数据

    通知所有 Broker

    生产者和消费者获取新元数据

    连接到新 Leader

    旧的 Leader 恢复

    成为 Follower

    从新 Leader 同步数据

    重新加入 ISR

    五、四大组件的协作机制

    5.1 生产者写入流程

    生产者向 Kafka 写入消息时,Broker、Partition、Replica 和 ISR 协同工作,确保数据被可靠地存储。以下是详细的写入流程:

  • 选择分区:生产者可以通过指定分区策略(如轮询、哈希等)选择目标分区,或者让 Broker 根据消息的 key 自动选择分区。
  • 连接 Leader:生产者连接到目标分区的 Leader 副本所在的 Broker。
  • 发送消息:生产者将消息发送给 Leader Broker。消息包含分区号、消息内容、时间戳等信息。
  • 写入日志:Leader Broker 将消息写入本地日志,并分配一个唯一的偏移量。
  • 复制到 Follower:Leader 将消息复制到所有 Follower 副本。Follower 将消息写入本地日志并向 Leader 发送确认。
  • 等待确认:Leader 等待所有 ISR 中的副本确认写入。如果 min.insync.replicas 设置为 2,则至少需要 2 个副本(包括 Leader)确认写入。
  • 返回结果:Leader 向生产者返回写入确认(ACK),表示消息已成功写入所有必要的副本。
  • 元数据更新:Kafka 更新集群的元数据,记录最新的分区状态和 ISR 信息。
  • ControllerFollower Broker 2Follower Broker 1Leader Broker生产者ControllerFollower Broker 2Follower Broker 1Leader Broker生产者#publish-mermaid-1788278621170-5{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;}}#publish-mermaid-1788278621170-5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621170-5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621170-5 .error-icon{fill:#552222;}#publish-mermaid-1788278621170-5 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278621170-5 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278621170-5 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278621170-5 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278621170-5 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278621170-5 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278621170-5 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278621170-5 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278621170-5 .marker.cross{stroke:#333333;}#publish-mermaid-1788278621170-5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278621170-5 p{margin:0;}#publish-mermaid-1788278621170-5 .actor{stroke:#9370DB;fill:#ECECFF;stroke-width:1;}#publish-mermaid-1788278621170-5 rect.actor.outer-path[data-look=\”neo\”]{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 rect.note[data-look=\”neo\”]{stroke:#aaaa33;fill:#fff5ad;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 text.actor>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621170-5 .actor-line{stroke:#9370DB;}#publish-mermaid-1788278621170-5 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#publish-mermaid-1788278621170-5 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#publish-mermaid-1788278621170-5 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#publish-mermaid-1788278621170-5 [id$=\”-arrowhead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278621170-5 .sequenceNumber{fill:white;}#publish-mermaid-1788278621170-5 [id$=\”-sequencenumber\”]{fill:#333;}#publish-mermaid-1788278621170-5 [id$=\”-crosshead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278621170-5 .messageText{fill:#333;stroke:none;}#publish-mermaid-1788278621170-5 .labelBox{stroke:#9370DB;fill:#ECECFF;filter:none;}#publish-mermaid-1788278621170-5 .labelText,#publish-mermaid-1788278621170-5 .labelText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621170-5 .loopText,#publish-mermaid-1788278621170-5 .loopText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621170-5 .sectionTitle,#publish-mermaid-1788278621170-5 .sectionTitle>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621170-5 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#9370DB;fill:#9370DB;}#publish-mermaid-1788278621170-5 .note{stroke:#aaaa33;fill:#fff5ad;}#publish-mermaid-1788278621170-5 .noteText,#publish-mermaid-1788278621170-5 .noteText>tspan{fill:black;stroke:none;font-weight:normal;}#publish-mermaid-1788278621170-5 .activation0{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621170-5 .activation1{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621170-5 .activation2{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621170-5 .actorPopupMenu{position:absolute;}#publish-mermaid-1788278621170-5 .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));}#publish-mermaid-1788278621170-5 .actor-man circle,#publish-mermaid-1788278621170-5 line{fill:#ECECFF;stroke-width:2px;}#publish-mermaid-1788278621170-5 g rect.rect{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));stroke:#9370DB;}#publish-mermaid-1788278621170-5 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node rect,#publish-mermaid-1788278621170-5 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621170-5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}发送消息到指定分区写入本地日志,分配偏移量复制消息确认写入复制消息确认写入检查 ISR 确认数量更新元数据更新 ISR 状态返回更新结果返回写入确认

    5.2 消费者读取流程

    消费者从 Kafka 读取消息时,Broker、Partition、Replica 和 ISR 同样协同工作,确保数据被高效地读取。以下是详细的读取流程:

  • 消费者组协调:消费者属于一个消费者组,Kafka 使用消费者组机制实现消息的并行处理和负载均衡。
  • 分区分配:当消费者加入或离开消费者组时,Group Coordinator 会重新分配分区给消费者,确保每个分区最多被一个消费者消费。
  • 连接 Leader:消费者连接到分区的 Leader 副本所在的 Broker,从 Leader 读取消息。
  • 拉取消息:消费者向 Leader 发送FetchRequest,指定要读取的起始偏移量和最大消息数量。
  • 返回消息:Leader 从本地日志中读取请求范围内的消息,返回给消费者。Leader 不会等待 Follower 的响应,因为读取操作不涉及数据复制。
  • 更新偏移量:消费者可以手动提交偏移量,或者让 Kafka 自动提交。偏移量保存在 Kafka 内部主题 __consumer_offsets 中。
  • 处理消息:消费者处理接收到的消息,并根据业务需求决定是否提交偏移量。
  • 故障转移:如果消费者长时间没有提交偏移量,或者消费者所在 Broker 发生故障,Group Coordinator 可能会将分区重新分配给其他消费者。
  • 偏移量存储Group CoordinatorLeader Broker消费者偏移量存储Group CoordinatorLeader Broker消费者#publish-mermaid-1788278621199-6{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;}}#publish-mermaid-1788278621199-6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621199-6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621199-6 .error-icon{fill:#552222;}#publish-mermaid-1788278621199-6 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278621199-6 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278621199-6 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278621199-6 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278621199-6 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278621199-6 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278621199-6 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278621199-6 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278621199-6 .marker.cross{stroke:#333333;}#publish-mermaid-1788278621199-6 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278621199-6 p{margin:0;}#publish-mermaid-1788278621199-6 .actor{stroke:#9370DB;fill:#ECECFF;stroke-width:1;}#publish-mermaid-1788278621199-6 rect.actor.outer-path[data-look=\”neo\”]{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 rect.note[data-look=\”neo\”]{stroke:#aaaa33;fill:#fff5ad;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 text.actor>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621199-6 .actor-line{stroke:#9370DB;}#publish-mermaid-1788278621199-6 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#publish-mermaid-1788278621199-6 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#publish-mermaid-1788278621199-6 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#publish-mermaid-1788278621199-6 [id$=\”-arrowhead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278621199-6 .sequenceNumber{fill:white;}#publish-mermaid-1788278621199-6 [id$=\”-sequencenumber\”]{fill:#333;}#publish-mermaid-1788278621199-6 [id$=\”-crosshead\”] path{fill:#333;stroke:#333;}#publish-mermaid-1788278621199-6 .messageText{fill:#333;stroke:none;}#publish-mermaid-1788278621199-6 .labelBox{stroke:#9370DB;fill:#ECECFF;filter:none;}#publish-mermaid-1788278621199-6 .labelText,#publish-mermaid-1788278621199-6 .labelText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621199-6 .loopText,#publish-mermaid-1788278621199-6 .loopText>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621199-6 .sectionTitle,#publish-mermaid-1788278621199-6 .sectionTitle>tspan{fill:black;stroke:none;}#publish-mermaid-1788278621199-6 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#9370DB;fill:#9370DB;}#publish-mermaid-1788278621199-6 .note{stroke:#aaaa33;fill:#fff5ad;}#publish-mermaid-1788278621199-6 .noteText,#publish-mermaid-1788278621199-6 .noteText>tspan{fill:black;stroke:none;font-weight:normal;}#publish-mermaid-1788278621199-6 .activation0{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621199-6 .activation1{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621199-6 .activation2{fill:#f4f4f4;stroke:#666;}#publish-mermaid-1788278621199-6 .actorPopupMenu{position:absolute;}#publish-mermaid-1788278621199-6 .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));}#publish-mermaid-1788278621199-6 .actor-man circle,#publish-mermaid-1788278621199-6 line{fill:#ECECFF;stroke-width:2px;}#publish-mermaid-1788278621199-6 g rect.rect{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));stroke:#9370DB;}#publish-mermaid-1788278621199-6 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node rect,#publish-mermaid-1788278621199-6 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621199-6 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}注册消费者组分配分区连接 Leader发送FetchRequest从本地日志读取消息返回消息和元数据处理消息提交偏移量更新偏移量继续请求下一条消息

    5.3 故障恢复与数据一致性保证

    在 Kafka 集群中,Broker、Partition、Replica 和 ISR 协同工作,确保在发生故障时能够快速恢复并保持数据一致性。以下是故障恢复和数据一致性保证的机制:

  • Leader 故障恢复:
    • Controller 检测到 Leader 副本故障
    • 从 ISR 中选举新的 Leader
    • 更新集群元数据,通知所有 Broker 和客户端
    • 客户端自动连接到新的 Leader
    • 旧的 Leader 恢复后,成为 Follower 并重新同步数据
  • Follower 故障恢复:
    • Controller 检测到 Follower 副本故障
    • 如果 Follower 在 ISR 中,将其暂时移出 ISR
    • Follower 恢复后,从 Leader 同步落后的数据
    • 当 Follower 追上 Leader 的数据后,重新加入 ISR
  • Broker 故障恢复:
    • 当 Broker 完全故障时,其上的所有副本都会被标记为不可用
    • Controller 触发 Leader 选举过程,为每个分区的 Leader 选择新的副本
    • 故障的 Broker 恢复后,其上的副本成为 Follower,从新的 Leader 同步数据
  • 数据一致性保证:
    • 生产者写入时,只有当 ISR 中所有副本都成功复制消息后,才会向生产者确认写入
    • 通过 min.insync.replicas 参数控制至少需要多少个副本成功写入
    • 通过 acks 参数控制生产者的确认级别(all、1、0)
    • 消费者可以控制偏移量的提交时机,确保消息被正确处理后才提交
  • 数据冗余与可用性:
    • 通过复制机制确保数据在多个 Broker 上有副本
    • 通过 ISR 机制确保只有最新的副本才能被选举为 Leader
    • 通过 replication.factor 参数控制每个 Partition 的副本数量

    #publish-mermaid-1788278621232-7{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;}}#publish-mermaid-1788278621232-7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621232-7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1788278621232-7 .error-icon{fill:#552222;}#publish-mermaid-1788278621232-7 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1788278621232-7 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1788278621232-7 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1788278621232-7 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1788278621232-7 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1788278621232-7 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1788278621232-7 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1788278621232-7 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1788278621232-7 .marker.cross{stroke:#333333;}#publish-mermaid-1788278621232-7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1788278621232-7 p{margin:0;}#publish-mermaid-1788278621232-7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1788278621232-7 .cluster-label text{fill:#333;}#publish-mermaid-1788278621232-7 .cluster-label span{color:#333;}#publish-mermaid-1788278621232-7 .cluster-label span p{background-color:transparent;}#publish-mermaid-1788278621232-7 .label text,#publish-mermaid-1788278621232-7 span{fill:#333;color:#333;}#publish-mermaid-1788278621232-7 .node rect,#publish-mermaid-1788278621232-7 .node circle,#publish-mermaid-1788278621232-7 .node ellipse,#publish-mermaid-1788278621232-7 .node polygon,#publish-mermaid-1788278621232-7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621232-7 .rough-node .label text,#publish-mermaid-1788278621232-7 .node .label text,#publish-mermaid-1788278621232-7 .image-shape .label,#publish-mermaid-1788278621232-7 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1788278621232-7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1788278621232-7 .rough-node .label,#publish-mermaid-1788278621232-7 .node .label,#publish-mermaid-1788278621232-7 .image-shape .label,#publish-mermaid-1788278621232-7 .icon-shape .label{text-align:center;}#publish-mermaid-1788278621232-7 .node.clickable{cursor:pointer;}#publish-mermaid-1788278621232-7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1788278621232-7 .arrowheadPath{fill:#333333;}#publish-mermaid-1788278621232-7 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1788278621232-7 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1788278621232-7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278621232-7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621232-7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621232-7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1788278621232-7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1788278621232-7 .cluster text{fill:#333;}#publish-mermaid-1788278621232-7 .cluster span{color:#333;}#publish-mermaid-1788278621232-7 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;}#publish-mermaid-1788278621232-7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1788278621232-7 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1788278621232-7 .icon-shape,#publish-mermaid-1788278621232-7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1788278621232-7 .icon-shape p,#publish-mermaid-1788278621232-7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1788278621232-7 .icon-shape .label rect,#publish-mermaid-1788278621232-7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1788278621232-7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1788278621232-7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1788278621232-7 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node rect,#publish-mermaid-1788278621232-7 [data-look=\”neo\”].cluster rect,#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621232-7 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1788278621232-7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}Leader 故障Follower 故障Broker 故障

    检测到故障

    故障类型?

    从 ISR 选举新 Leader

    暂时移出 ISR

    重新分配分区

    更新集群元数据

    Follower 恢复

    触发 Leader 选举

    通知客户端

    从 Leader 同步数据

    Follower 重新加入 ISR

    数据一致性恢复

    六、实战应用与最佳实践

    6.1 Broker 集群配置优化

    为了实现高可用和高性能,Kafka Broker 集群的配置至关重要。以下是一些关键的配置优化建议:

  • 硬件资源分配:
    • 为 Broker 分配足够的内存,用于缓存和请求处理
    • 使用高速存储设备(如 SSD)提高 I/O 性能
    • 确保网络带宽充足,避免成为瓶颈
  • 关键参数配置:
    • num.network.threads 和 num.io.threads:根据并发请求量调整
    • socket.send.buffer.bytes 和 socket.receive.buffer.bytes:优化网络缓冲区大小
    • log.segment.bytes:合理设置日志段大小,平衡 I/O 性能和存储效率
    • zookeeper.connect:配置 ZooKeeper 连接字符串,用于集群协调
  • 监控与调优:
    • 监控 Broker 的 CPU、内存、磁盘 I/O 和网络使用情况
    • 定期检查日志大小和分区分布,避免某些 Broker 负载过高
    • 根据业务需求调整并发线程数和缓冲区大小
  • 高可用性配置:
    • 设置 replication.factor 为 3 或更高
    • 合理设置 min.insync.replicas 和 unclean.leader.election.enable
    • 配置多个 ZooKeeper 节点或使用 KRaft 协调模式

    | 参数名 | 推荐值 | 说明 |

    |——-|——-|——|

    | num.network.threads | 3-4 | 网络处理线程数 |

    | num.io.threads | 8-16 | I/O 处理线程数 |

    | socket.send.buffer.bytes | 102400 | 发送缓冲区大小 |

    | socket.receive.buffer.bytes | 102400 | 接收缓冲区大小 |

    | log.segment.bytes | 1073741824 | 日志段大小(1GB) |

    | replication.factor | 3 | 副本数量 |

    | min.insync.replicas | 2 | ISR 中最小副本数 |

    6.2 Partition 与 Replica 的合理规划

    合理规划 Partition 和 Replica 是确保 Kafka 集群性能和可用性的关键:

  • Partition 数量规划:
    • 根据业务吞吐量需求确定 Partition 数量,每个 Partition 的理想吞吐量约为 10-50 MB/s
    • 避免过多或过少的 Partition,过多的 Partition 会导致元数据开销增加,而过少的 Partition 会限制并行处理能力
    • 随着业务增长,可以动态增加 Partition 数量
  • Partition 分布策略:
    • 使用合理的分区键,确保消息均匀分布在各个 Partition 上
    • 避免热点问题,即某些 Partition 的消息量远高于其他 Partition
    • 考虑将相关性强的消息放在同一个 Partition 中,保证消息顺序
  • Replica 规划:
    • 设置合理的 replication.factor,通常为 3
    • 确保同一个 Partition 的副本分布在不同的 Broker 上,避免单点故障
    • 考虑机架感知,将副本分布在不同的机架上,提高容灾能力
  • ISR 策略优化:
    • 根据业务需求调整 replica.lag.time.max.ms 和 replica.lag.max.messages
    • 监控 ISR 大小,确保足够多的副本用于故障恢复
    • 考虑使用 unclean.leader.election.enable=false 防止数据丢失

    | 规划方面 | 最佳实践 | 注意事项 |

    |———|———|———|

    | Partition 数量 | 根据吞吐量需求确定,每 Partition 10-50 MB/s | 避免过多或过少,动态调整 |

    | Partition 分布 | 使用合理的分区键,均匀分布 | 避免热点问题,考虑消息顺序 |

    | Replica 数量 | 通常设置为 3 | 确保分布在不同的 Broker 上 |

    | ISR 策略 | 合理设置滞后参数,监控 ISR 大小 | 平衡数据一致性和可用性 |

    6.3 ISR 策略调优

    ISR 策略的调优对 Kafka 集群的数据一致性和可用性有重要影响。以下是一些调优建议:

  • 滞后参数调优:
    • replica.lag.time.max.ms:默认为 30 秒,可以根据网络条件和负载进行调整
    • replica.lag.max.messages:默认为 4000,可以根据消息大小和吞吐量调整
    • 这些参数需要根据实际业务场景进行调优,避免过于严格或过于宽松
  • ISR 大小控制:
    • min.insync.replicas:控制生产者写入时需要等待的副本数量
    • 较大的值可以提供更好的数据一致性,但可能会影响写入性能
    • 通常设置为 2 或 3,根据业务对一致性的要求调整
  • Leader 选举策略:
    • unclean.leader.election.enable:默认为 false,不允许从非 ISR 副本中选举 Leader
    • 设置为 true 可以提高可用性,但有数据丢失风险
    • 根据业务对数据一致性的要求选择合适的值
  • 监控与调优:
    • 定期监控 ISR 状态,确保副本同步正常
    • 监控滞后指标,及时发现和解决同步问题
    • 调整相关参数后,监控集群性能指标的变化

    | 参数名 | 默认值 | 调优建议 | 影响因素 |

    |——-|——-|———|———|

    | replica.lag.time.max.ms | 30000 | 根据网络条件和负载调整 | 网络延迟、Broker 负载 |

    | replica.lag.max.messages | 4000 | 根据消息大小和吞吐量调整 | 消息大小、生产者吞吐量 |

    | min.insync.replicas | 1 | 根据一致性要求设置为 2 或 3 | 数据一致性要求、写入性能 |

    | unclean.leader.election.enable | false | 根据业务需求选择 true 或 false | 数据一致性要求、可用性要求 |

    赞(0)
    未经允许不得转载:171主机测评 » Kafka 架构深度拆解:Broker、Partition、Replica 与 ISR 的协作机制
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址