跳转至

Kafka 架构

整体架构

image-20250214170826487

Topic

通过主题实现业务的隔离,同一个业务的消息放在同一个主题中。

命令行创建 topic

进入 kafka 容器的命令行界面:

docker exec -it broker /bin/bash

进入脚本目录:

cd /opt/kafka/bin

创建 topic:

./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic test

查看现有topic:

./kafka-topics.sh --list --bootstrap-server localhost:9092

删除 topic:

./kafka-topics.sh --delete --bootstrap-server localhost:9092 --topic test

代码中使用 Topic

spring 的 kafka template 中,不需要提前创建主题,只要向某个主题发送消息,就自动创建了

生产者:

发送到指定的 topic

kafaTemplate.send("topic", msg);

消费者:

@KafkaListener(topics = "topic", ...)

Partition 分片

每个 Topic 可以划分为多个 Partition(分片)

命令行创建分片

创建:

./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic test --partitions 3

更改:

./kafka-topics.sh --alter --bootstrap-server localhost:9092 --topic test --partitions 5

注意分片数量只能增加不能改小

分片的逻辑结构

image-20250214185738620

同一个 partition 中数据有序;同一个 topic 下的不同 partition 之间数据无序

数据流入哪个分片

  1. 指定 partition(很少这样做)
  2. 指定了 Key,则根据 Key 的 Hash 对 partition 的数量取模来决定进入哪个 partition。只要发送时指定了相同的 Key,则消息回发送到同一个 partition
  3. 没有指定 partition 也没有指定 key,则使用轮流调度的方法,重复循环

消费者组

image-20250627130738163

同一个 Partition 只能被同一个消费者组(Consumer Group)中的一个消费者消费,但是可以被不同的消费者组中的 consumer 同时消费

一种良好的实践是,一个消费者组负责一个 topic 的消费。

(但是一个消费者组的不同消费者消费不同的 topic 是允许的,一个 topic 也可以被多个消费者组消费(此时消费者组之间各自独立,各自维护 __consumer_offsets)

假设有一个 Topic,包含 3 个 Partition(P0、P1、P2),以及一个消费者组(Group A)中有 2 个消费者(C1、C2):

  • Kafka 可能会将 Partition 分配如下:
    • C1 消费 P0 和 P1
    • C2 消费 P2
  • 如果消费者组中有 3 个消费者,则每个消费者会消费一个 Partition。
  • 如果消费者组中有 4 个消费者,则有一个消费者会处于空闲状态。

Broker

Broker 可以理解为 partition 的载体

Broker 就是一个 Kafka 服务器节点,服务器节点上运行了 Kafka 的应用程序。

Broker 可以用于:

  • 存储消息
  • 接收客户端的连接
  • 支持客户端查询其他 Broker 的信息
  • 接收客户端的读写请求

集群部署

image-20250627131648882

单机部署就只有一个 Broker,集群则是有多个 Broker 协作提供服务,集群中一个 Broker 使用一个唯一的 ID 来标识

Leader - Follower 的概念是 partition 级别的,所有的读操作 / 写操作都是对 leader 进行操作

Broker 和 Partition 的关系

一个 Partition 只会存在一个 Broker 上,一个 Broker 可以存多个 Partition

image-20250214191205198

Partition 放在 Broker 上的规则就是首先随机挑选一个 Broker 放 Topic 的 partition0,随后顺序依次向后放这个 Topic 下的其他 Partitions

当发生网络分区或节点故障(触发Partition Tolerance)时,Kafka通过配置在AP或CP之间权衡:

  • CP模式:配置

    acks=all
    

    min.insync.replicas=N
    

    (N为副本数),要求所有ISR副本确认写入。此时若部分副本不可用,系统会拒绝写入(牺牲可用性),但保证数据强一致性

  • AP模式
    配置acks=1或允许非ISR副本选举(unclean.leader.election.enable=true),即使部分副本未同步,系统仍可继续服务(牺牲一致性),优先保证可用性

客户端如何连接集群

每个 Broker 都会有其他 Broker 的信息,客户端:

  1. 访问任意一台 Broker
  2. 得到所有 Broker 的信息列表
  3. 生产者首先确认是需要放到哪个 partition,再找到这个 partition 所在的 broker