2. Kafka核心概念与集群部署

Kafka这东西,说白了就是一个「消息高速公路」。我在做实时ETL之前,其实对它的理解也就停留在「能存能取」的层面。直到有一次,线上流量突然暴涨,Kafka集群扛住了,我才真正意识到它的设计有多巧妙。

这一章,咱们把Kafka的核心概念掰开揉碎,再聊聊单机和集群怎么搭。嗯,你跟着我走一遍,后面跟Flink对接的时候,心里就有底了。

2.1 Kafka架构:谁在干什么

先看一张整体架构图,我习惯把Kafka集群想象成一个「物流中心」。

Kafka 核心架构图 Producer A Producer B Producer C Kafka Cluster (Broker) Broker 1 (Leader) Broker 2 (Follower) Broker 3 (Follower) ZooKeeper Consumer 1 Consumer 2 Consumer 3 说明: Producer 将消息发送到 Broker 集群,Broker 负责存储和管理数据。 Consumer 从 Broker 拉取消息进行消费。ZooKeeper 负责集群元数据管理和 Leader 选举。

架构里这几个角色,我一个个说清楚:

  • Producer(生产者):负责把数据扔进Kafka。我在项目中见过很多新手一股脑全塞一个Topic,结果下游消费不过来。记住,合理分区是关键。
  • Broker(代理节点):Kafka集群的每个服务器就是一个Broker。它负责接收、存储、分发消息。我建议生产环境至少3台起步,不然挂了就尴尬了。
  • Consumer(消费者):从Broker拉数据。注意,Consumer是主动拉,不是Broker推。这样能防止消费端被压垮。
  • ZooKeeper:老版本必须依赖它做集群协调。新版本虽然可以脱离ZK,但我个人习惯还是带着,稳定。

2.2 Topic与Partition:数据怎么组织

Topic是Kafka里最核心的抽象。你可以把它理解成一个「数据分类标签」。比如订单数据放一个Topic,用户行为放另一个Topic。

但光有Topic还不够。一个Topic可以拆成多个Partition(分区)。为什么要分区?说白了就是为了并行。你想想看,如果只有一个分区,那所有数据都挤在一个队列里,消费速度肯定上不去。

我的经验:分区数不是越多越好。我见过有人一个Topic设了100个分区,结果Broker只有3台,每个Broker要管30多个分区,反而拖慢了性能。一般建议分区数是Broker数量的2-3倍。

每个分区内部是有序的,但分区之间不保证顺序。如果你要求全局有序,那就只能设一个分区——但性能就别指望了。实际项目中,大部分场景只需要分区内有序就够了。

来看一个Topic和Partition的关系表:

概念 说明 我踩过的坑
Topic 消息的逻辑分类,类似数据库的表 Topic命名要规范,别用中文或特殊字符
Partition Topic的物理分片,每个分区是一个有序队列 分区数一旦设定,后期扩容很麻烦
Offset 分区内每条消息的唯一编号 Consumer要自己维护Offset,别搞丢了
Replica 分区的副本,用于容错 副本数建议2-3,太多浪费存储

2.3 Producer与Consumer:生产与消费的细节

Producer:怎么发消息

Producer发送消息时,可以指定分区策略。我常用的方式有三种:

  1. 轮询:默认方式,均匀分布到各分区。适合没有key的场景。
  2. 按key哈希:相同key的消息进同一个分区,保证有序。比如按订单ID哈希。
  3. 自定义分区器:自己写逻辑。我曾经为了把高优先级消息单独放一个分区,写了个自定义分区器。

另外,Producer有个acks参数,控制消息的可靠性:

  • acks=0:发出去就不管了,性能最高,但可能丢数据。
  • acks=1:Leader确认收到就算成功。我一般用这个,平衡性能和可靠性。
  • acks=all:所有副本都确认才算成功。最安全,但慢。

注意:如果你做的是金融或交易类ETL,建议用acks=all。我有个朋友做日志采集用了acks=0,结果Broker重启丢了十几万条日志,排查了一整天。

Consumer:怎么消费

Consumer以Consumer Group为单位消费。同一个Group内的Consumer不会重复消费同一个分区。这设计很巧妙——你加机器就能提升消费速度。

举个例子:一个Topic有4个分区,你的Consumer Group有2个消费者,那每个消费者分2个分区。如果加到4个消费者,就一人一个分区。如果加到5个消费者,有一个会闲着——因为分区数不够分。

我曾经犯过一个错:Consumer Group里某个消费者挂了,我以为它会自动重平衡,结果等了5分钟还没反应。后来发现是session.timeout.ms设得太长了。嗯,这个参数要调小一点,比如30秒。

2.4 单机模式部署:快速上手

单机模式适合学习和测试。我带你走一遍:

# 1. 下载Kafka(假设版本3.5.0)
wget https://downloads.apache.org/kafka/3.5.0/kafka_2.13-3.5.0.tgz
tar -xzf kafka_2.13-3.5.0.tgz
cd kafka_2.13-3.5.0

# 2. 启动ZooKeeper(Kafka自带了一个)
bin/zookeeper-server-start.sh config/zookeeper.properties &

# 3. 启动Kafka Broker
bin/kafka-server-start.sh config/server.properties &

# 4. 创建一个Topic
bin/kafka-topics.sh --create --topic test-topic \
  --bootstrap-server localhost:9092 \
  --partitions 3 --replication-factor 1

# 5. 查看Topic详情
bin/kafka-topics.sh --describe --topic test-topic \
  --bootstrap-server localhost:9092

启动后,你可以用kafka-console-producer.sh和kafka-console-consumer.sh测试收发消息。我建议你亲手敲一遍,感受一下。

2.5 集群模式部署:生产环境标配

生产环境至少3台机器。假设你有3台服务器:kafka1、kafka2、kafka3。

每台机器上都要修改config/server.properties:

# broker.id 每台机器必须不同
broker.id=1   # 第二台设为2,第三台设为3

# 监听地址
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://kafka1:9092  # 每台改成自己的主机名

# 日志目录
log.dirs=/data/kafka/logs

# ZooKeeper连接
zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181

# 副本数
default.replication.factor=3

# 最小同步副本数
min.insync.replicas=2

关键参数说明:

  • default.replication.factor=3:每个分区有3个副本,挂一台机器不影响。
  • min.insync.replicas=2:至少2个副本同步才算写入成功。配合acks=all使用,保证数据不丢。
  • log.dirs:建议用单独的磁盘,别跟系统盘混在一起。我见过有人放根目录,结果磁盘写满导致集群崩溃。

启动集群:

# 每台机器依次执行
bin/kafka-server-start.sh config/server.properties &

验证集群状态:

bin/kafka-topics.sh --describe --topic test-topic \
  --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092

你会看到类似这样的输出:

Topic: test-topic  Partition: 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
Topic: test-topic  Partition: 1  Leader: 2  Replicas: 2,3,1  Isr: 2,3,1
Topic: test-topic  Partition: 2  Leader: 3  Replicas: 3,1,2  Isr: 3,1,2

看到Leader分布在不同的Broker上,说明集群正常工作。Isr(In-Sync Replicas)列显示所有副本都在同步状态,完美。

避坑指南:我曾经部署集群时,忘了改advertised.listeners,结果客户端连不上。原因是客户端通过这个地址访问Broker,如果配成localhost,其他机器当然连不上。记住,advertised.listeners要配成其他机器能访问的IP或主机名。

2.6 本章小结

Kafka的核心概念其实不复杂:Topic是分类,Partition是分片,Producer是生产者,Consumer是消费者。集群部署的关键是副本数和分区数的合理配置。