2. Kafka核心概念与集群部署
Kafka这东西,说白了就是一个「消息高速公路」。我在做实时ETL之前,其实对它的理解也就停留在「能存能取」的层面。直到有一次,线上流量突然暴涨,Kafka集群扛住了,我才真正意识到它的设计有多巧妙。
这一章,咱们把Kafka的核心概念掰开揉碎,再聊聊单机和集群怎么搭。嗯,你跟着我走一遍,后面跟Flink对接的时候,心里就有底了。
2.1 Kafka架构:谁在干什么
先看一张整体架构图,我习惯把Kafka集群想象成一个「物流中心」。
架构里这几个角色,我一个个说清楚:
- 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发送消息时,可以指定分区策略。我常用的方式有三种:
- 轮询:默认方式,均匀分布到各分区。适合没有key的场景。
- 按key哈希:相同key的消息进同一个分区,保证有序。比如按订单ID哈希。
- 自定义分区器:自己写逻辑。我曾经为了把高优先级消息单独放一个分区,写了个自定义分区器。
另外,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是消费者。集群部署的关键是副本数和分区数的合理配置。