4、Kafka集群搭建:单机部署、集群配置、ZooKeeper角色、常用配置参数调优
好,咱们进入第四章。前面聊完了Kafka的设计理念和核心概念,现在该动手了。
这一章,我会带你从零搭一个Kafka集群。单机怎么玩、集群怎么配、ZooKeeper到底在里头干啥、哪些参数必须调——咱们一次说透。
我个人习惯,学一个新东西,先跑通单机,再上集群。这样出问题了,排查范围小。
4.1 单机部署:先跑起来再说
单机部署其实就三步:下载、解压、启动。但这里头有几个坑,我先帮你踩一遍。
4.1.1 环境准备
- JDK:Kafka 3.x 要求 JDK 11+。我建议用 JDK 17,稳。
- ZooKeeper:Kafka 3.x 虽然开始去ZK依赖,但生产环境还是建议带着ZK跑。
- 操作系统:Linux 首选。Windows 也能跑,但别在生产上用。
4.1.2 下载与配置
# 下载 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
解压完,看一眼目录结构。核心就几个:bin/(启动脚本)、config/(配置文件)、logs/(运行日志)。
改一下 config/server.properties:
# 基础配置
broker.id=0
listeners=PLAINTEXT://localhost:9092
log.dirs=/tmp/kafka-logs
zookeeper.connect=localhost:2181
嗯,这里要注意:log.dirs 别用默认的 /tmp 目录。我遇到过,系统重启后 /tmp 被清空,Kafka 直接报错找不到日志段文件。改成持久化路径,比如 /data/kafka/logs。
4.1.3 启动验证
# 先启动 ZooKeeper
bin/zookeeper-server-start.sh config/zookeeper.properties &
# 再启动 Kafka
bin/kafka-server-start.sh config/server.properties &
# 创建测试主题
bin/kafka-topics.sh --create --topic test-topic --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
# 查看主题列表
bin/kafka-topics.sh --list --bootstrap-server localhost:9092
看到 test-topic 出现在列表里,单机部署就成功了。简单吧?
& 让进程后台运行。但生产环境建议用 systemd 或 supervisor 管理进程,不然终端一关服务就停了。
4.2 集群配置:三台机器才是起步
单机只能玩玩,生产环境至少三台 broker。为什么是三台?你想想看,副本因子通常设3,如果只有两台机器,一台挂了,ISR 就只剩一个副本,容错能力大打折扣。
4.2.1 集群规划
假设有三台机器:kafka1、kafka2、kafka3。每台机器上都要部署 Kafka 和 ZooKeeper。
| 节点 | broker.id | 监听端口 | 日志目录 |
|---|---|---|---|
| kafka1 | 0 | 9092 | /data/kafka/logs |
| kafka2 | 1 | 9092 | /data/kafka/logs |
| kafka3 | 2 | 9092 | /data/kafka/logs |
4.2.2 核心配置项
每台机器的 server.properties 配置大同小异,区别主要在 broker.id 和 listeners。
# kafka1 的配置
broker.id=0
listeners=PLAINTEXT://kafka1:9092
advertised.listeners=PLAINTEXT://kafka1:9092
log.dirs=/data/kafka/logs
zookeeper.connect=kafka1:2181,kafka2:2181,kafka3:2181
offsets.topic.replication.factor=3
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=2
这里有个关键点:advertised.listeners。这个配置是告诉客户端「你应该连哪个地址」。如果配错了,客户端能连上集群,但生产消费会报错。我曾经踩过这个坑,配成了 localhost,结果远程客户端连上来,拿到的是 localhost:9092,当然连不上。
4.2.3 启动集群
每台机器上依次启动 ZooKeeper 和 Kafka:
# 在 kafka1 上
bin/zookeeper-server-start.sh config/zookeeper.properties &
bin/kafka-server-start.sh config/server.properties &
# 在 kafka2 上(同样操作)
# 在 kafka3 上(同样操作)
启动完成后,验证集群状态:
bin/kafka-broker-api-versions.sh --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092
如果看到三个 broker 都返回了版本信息,集群就搭好了。
4.3 ZooKeeper 角色:集群的「大脑」
ZooKeeper 在 Kafka 集群里到底干啥?说白了,它就是个协调者。Kafka 自己搞不定的事情,交给 ZK 来管。
4.3.1 ZooKeeper 的核心职责
- Broker 注册与发现:每个 broker 启动时,会在 ZK 上注册一个临时节点。其他 broker 和客户端通过 ZK 知道集群里有哪些节点。
- Controller 选举:集群里有一个特殊的 broker 叫 Controller,负责分区 leader 的选举。Controller 挂了,ZK 会触发重新选举。
- 主题与分区元数据:主题有哪些分区、分区 leader 是谁、ISR 列表是什么——这些信息都存在 ZK 里。
- 消费者组偏移量:老版本的 Kafka 把消费偏移量存在 ZK 里。新版本虽然改存在内部主题
__consumer_offsets里,但 ZK 仍然参与消费者组的协调。
4.3.2 ZooKeeper 集群部署
ZK 本身也是一个集群,通常部署奇数个节点(3、5、7)。为什么是奇数?因为 ZK 的选举机制需要过半同意,奇数节点能避免平票。
配置 config/zookeeper.properties:
dataDir=/data/zookeeper/data
clientPort=2181
maxClientCnxns=60
tickTime=2000
initLimit=10
syncLimit=5
server.0=kafka1:2888:3888
server.1=kafka2:2888:3888
server.2=kafka3:2888:3888
每台机器上还要在 dataDir 目录下创建一个 myid 文件,内容就是对应的 server ID:
# kafka1 上
echo "0" > /data/zookeeper/data/myid
# kafka2 上
echo "1" > /data/zookeeper/data/myid
# kafka3 上
echo "2" > /data/zookeeper/data/myid
4.4 常用配置参数调优
配置参数是门学问。调好了,性能翻倍;调不好,各种诡异问题。下面是我在实际项目中总结的几个关键参数。
4.4.1 Broker 核心参数
| 参数名 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
num.network.threads |
3 | CPU核数 × 2 | 网络线程数,处理客户端请求 |
num.io.threads |
8 | CPU核数 × 2 | I/O线程数,处理磁盘读写 |
log.retention.hours |
168 | 72(3天) | 日志保留时间,根据业务调整 |
log.segment.bytes |
1GB | 1GB | 日志段文件大小,一般不用改 |
log.retention.bytes |
-1 | -1(不限) | 日志保留总大小,按磁盘容量设 |
4.4.2 生产者参数调优
生产者的核心是吞吐量和可靠性之间的权衡。
acks:acks=all最安全,但延迟高;acks=1性能好,但可能丢数据。我建议核心业务用all,日志采集用1。batch.size:默认16KB。如果消息体小,可以调到32KB或64KB,减少网络请求次数。linger.ms:默认0。可以设成5-10ms,让消息在缓冲区多等一会儿,凑成一批再发,吞吐量能提升不少。compression.type:建议用snappy或lz4。压缩比高,CPU开销小。
4.4.3 消费者参数调优
fetch.min.bytes:默认1。可以调到1KB或更高,减少拉取次数。max.poll.records:默认500。如果每条消息处理时间长,可以调小,防止超时导致 rebalance。session.timeout.ms:默认45秒。如果网络不稳定,可以适当调大,避免误判消费者死亡。
max.poll.records 设成5000,结果消费者处理不过来,触发了 rebalance。rebalance 期间所有分区都暂停消费,整个系统吞吐量直接腰斩。后来我改成1000,配合 max.poll.interval.ms 设成5分钟,问题解决。
4.5 集群架构总览
说了这么多,咱们用一张图把整个集群架构串起来。这张图展示了三台 broker、三台 ZK、以及它们之间的交互关系。
从这张图可以看得很清楚:ZK 集群在上层做协调,Broker 集群在下层做数据存储和转发,客户端通过任意 broker 接入集群。整个架构的核心就是「ZK 管元数据,Broker 管数据」。
4.6 本章小结
这一章我们走完了从单机到集群的全过程。单机部署是热身,集群配置是实战,ZooKeeper 角色是理解架构的关键,参数调优是性能保障。
我个人觉得,搭建集群本身不难,难的是理解每个配置背后的原理。你想想看,如果不知道 advertised.listeners 是干嘛的,出了问题只能瞎猜。所以,多动手、多踩坑、多总结——这是成为资深工程师的唯一路径。