1. Kafka 为什么会出现在业务系统中

以银行交易系统为例。用户发起转账、刷卡消费、还款或理财申购之后,交易系统通常不只需要完成交易入账,还会触发风控、反洗钱、清算、客户通知、账务核算、数据分析等下游系统。

如果交易系统直接调用所有下游系统,系统之间耦合度会很高:

交易系统
├──调用风控系统
├──调用反洗钱系统
├──调用清算系统
├──调用客户通知系统
├──调用账务核算系统
└──调用数据分析系统

这种设计的问题很明显:

  1. 下游系统如果变慢,交易主流程也可能被拖慢。
  2. 某个下游系统不可用,交易系统可能被迫失败或反复重试。
  3. 新增一个下游系统时,交易系统往往也要改代码。
  4. 流量突然增大时,下游系统可能被瞬时流量打穿。

引入 Kafka 后,交易系统只需要把“交易已受理”“账户余额已变动”“转账已完成”这样的事件写入 Kafka 中,下游系统再按照自己的节奏消费。

交易系统 → Kafka Topic:bank-transaction-events
                    ├──风控系统消费
                    ├──反洗钱系统消费
                    ├──清算系统消费
                    ├──客户通知系统消费
                    ├──账务核算系统消费
                    └──数据分析系统消费

这样做带来的好处有:

含义在银行交易场景中的表现
解耦生产者不直接依赖所有消费者交易系统不用逐个调用反洗钱、清算、数据分析
削峰Kafka 暂存突发流量下游按自己的处理能力慢慢消费
异步写入消息后即可继续主流程交易主链路不用等待所有下游处理完成
可回放消息保留一段时间,可重新消费对账或数据分析出错后,可以重新拉取历史交易事件

这里也要注意边界。Kafka 能降低上下游之间的直接依赖,但不是“所有系统故障都不影响业务”。如果交易系统自己不可用,就不会产生新的交易事件;如果 Kafka 集群不可用,生产者写入消息也会受到影响。

2. Kafka 中一条消息会经过哪些组件

Kafka 的基础数据流如下图所示:

Producer → Topic → Partition → Broker
                              ↓
                         Consumer Group
                              ↓
                           Consumer
概念含义作用
Producer生产者发送消息的一方,比如交易系统、日志采集程序
Topic主题消息的逻辑分类,比如 bank-transaction-events
Partition分区Topic 下的数据分片,决定并行能力和局部顺序
BrokerKafka 节点真正保存数据、处理读写请求的服务器
Consumer消费者读取并处理消息的一方,比如风控系统
Consumer Group消费者组一组共同消费同一个 Topic 的消费者
Offset位移消费者组在某个 Partition 中读到的位置
Replica副本Partition 的冗余拷贝,用于提高可用性
Leader主副本对外提供读写服务的 Partition 副本
Follower从副本从 Leader 同步数据,等待故障时接替

Producer 不会把消息直接交给 Consumer,而是写入 Topic 下的某个 Partition;Partition 存储在 Broker 上;Consumer 通过 Consumer Group 的方式读取 Partition;Offset 记录消费进度;副本机制保证 Broker 故障时数据仍有机会继续服务。

3. Topic 与 Partition

Topic 是消息的逻辑分类。比如:

bank-transaction-events   保存交易流水事件
account-change-events     保存账户变动事件
risk-alert-events         保存风控告警事件

但 Kafka 不会把一个 Topic 当成一个单独的大文件来处理。Topic 会被拆成多个 Partition:

Topic
├──Partition 0
├──Partition 1
├──Partition 2
└──Partition 3

Partition 是 Kafka 中非常关键的概念

  1. 数据可以拆开存储,不必全部压在一个节点上。
  2. 生产和消费可以并行处理,提高吞吐量。
  3. 每个 Partition 内部可以保证消息顺序。

这里有一个容易踩坑的点:Kafka 只保证单个 Partition 内部有序,不保证整个 Topic 全局有序。

例如:

Partition 0:A → B → C
Partition 1:D → E → F

Kafka 可以保证 A、B、CPartition 0 内的顺序,也可以保证 D、E、FPartition 1 内的顺序,但不会保证整个 Topic 中一定是 A、B、C、D、E、F 这种全局顺序。

4. Consumer Group:同组分工,不同组独立

假设 bank-transaction-events 有 4 个 Partition,一个消费者组中有 2 个消费者:

Consumer Group:risk-control-group

Partition 0 → Consumer A
Partition 1 → Consumer A
Partition 2 → Consumer B
Partition 3 → Consumer B

这表示风控系统的两个消费者实例一起处理这 4 个 Partition

如果同一个 Topic 又被反洗钱系统消费,反洗钱系统可以使用另一个消费者组:

Consumer Group:aml-group

Partition 0 → Consumer C
Partition 1 → Consumer C
Partition 2 → Consumer D
Partition 3 → Consumer D

这样,风控系统和反洗钱系统都能读到交易消息。它们的消费进度互不影响。

因此,可以得到两个结论:

场景是否会重复消费同一条消息说明
同一个消费者组内的多个消费者不会重复消费同一个 Partition 的同一条消息组内是分工关系
不同消费者组可以各自消费同一条消息组间是独立关系

一个消费者组的有效消费并行度,可以先用这个公式理解:

有效并行度 = min(Partition 数量, Consumer 数量)

也就是说,如果 Topic 只有 3 个 Partition,即使同一个消费者组里启动 5 个 Consumer,最多也只有 3 个 Consumer 真正工作,剩下 2 个会空闲。

5. Offset

Offset 是 Partition 内部每条消息的位置编号。

Partition 0

Offset 0:交易 A
Offset 1:交易 B
Offset 2:交易 C
Offset 3:交易 D

Offset 有几个关键点:

  1. Offset 只在当前 Partition 内有意义。
  2. 不同 Partition 可以都有 Offset 0
  3. Offset 不是消息的全局唯一 ID。
  4. Consumer Group 通过 Offset 记录自己消费到了哪里。

例如,风控系统消费到 Partition 0Offset 10,反洗钱系统可能只消费到 Offset 3。这两个进度是独立的,因为它们属于不同的消费者组。

Partition 0

risk-control-group 当前 Offset:10
aml-group          当前 Offset:3

消费消息并不会让消息立刻从 Kafka 中删除。Kafka 的消息是否保留,主要由 Topic 的保留策略决定,比如保留 7 天或保留到一定大小。Offset 只是记录“某个消费者组读到了哪里”。

这也是 Kafka 能支持历史数据回放的原因:只要消息还在,就可以调整 Offset,让消费者从更早的位置重新读取。

6. Broker

Broker 是 Kafka 集群中的服务节点,可以粗略理解成一台运行 Kafka 的服务器。

一个 Kafka 集群通常由多个 Broker 组成:

Kafka Cluster
├──Broker 1
├──Broker 2
└──Broker 3

Topic 的 Partition 会分布在不同 Broker 上:

Topic:bank-transaction-events,4 个 Partition

Broker 1:Partition 0
Broker 2:Partition 1
Broker 3:Partition 2
Broker 1:Partition 3

这种分布式存储带来并行能力,也带来一个问题:如果某个 Broker 宕机,而 Partition 只有一份数据,那么这个 Partition 就无法继续提供服务。

Kafka 通过副本机制解决这个问题。

7. 副本

一个 Partition 可以有多个副本。副本数量由副本因子决定。

比如:

Partition 数量:4
副本因子:2

表示每个 Partition 有 2 份副本。总副本数为:

总副本数 = Partition 数量 × 副本因子
总副本数 = 4 × 2 = 8

但这 8 份副本不是 8 个 Follower。每个 Partition 都有一个 Leader,剩下的才是 Follower。

Leader 数量 = Partition 数量 = 4
Follower 数量 = 总副本数 - Leader 数量 = 8 - 4 = 4

示例:

Partition 0:Leader + Follower
Partition 1:Leader + Follower
Partition 2:Leader + Follower
Partition 3:Leader + Follower

Producer 和 Consumer 通常与 Leader 交互。Follower 从 Leader 同步数据。当某个 Leader 所在 Broker 宕机时,如果 Follower 数据同步得比较新,就可以接替 Leader 工作。

这里第一周只需要先理解一个大方向:Follower 的价值不是提高消费并行度,而是在 Leader 出问题时接替它,保证系统可用性。

副本因子也不能随便设置。一个 Partition 的多个副本需要放在不同 Broker 上才有意义,所以副本因子不能超过 Broker 数量。比如集群只有 3 个 Broker,副本因子就不能设置为 4。

8. Partition 和副本的区别

最容易混淆的是:副本数量增加,不代表同一个消费者组的消费并行度增加。

例如:

Topic 有 4 个 Partition
副本因子为 2
总副本数为 8

虽然总副本数是 8,但一个消费者组的最大有效消费并行度仍然是 4,因为消费并行度主要看 Partition 数量。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐