标签搜索

Kafka集群优化指南

mrui
2025-12-10 / 0 评论 / 6 阅读 / 正在检测是否收录...

因Kafka具有吞吐量大,低延迟,高伸缩,高可靠性,高并发等特性,深受各大公司的喜爱,可以作为削峰填谷神器。

但是Kafka“入门容易精通难”,它的很多默认配置,非常保守,像是给笔记本电脑用的,不是给服务器用的。

因此,用好Kafka,可以从以下几个方面进行优化。

关闭Swap

JVM 最怕什么?最怕内存不够用,操作系统把它的内存页置换到 Swap 分区去。那一瞬间,GC 停顿时间(Stop The World)能长到让你怀疑人生。Kafka 是跑在 JVM 上的,一旦发生 Swap,Broker 就算没挂,延迟也得飙到好几秒。

sysctl -w vm.swappiness=1

别设成 0,设成 1,告诉内核,除非内存真的真的枯竭了,否则别动我的 Swap。最好直接在 /etc/fstab 里把 swap 这一行注释掉,永绝后患。

设置文件句柄数(File Descriptors)

Kafka 个狂暴的写手。它会打开无数个 Socket 连接,还会打开无数个日志分段文件(Segment Logs)。Linux 默认的 1024 个句柄,远远不够Kafka消耗的。

修改 /etc/security/limits.conf,参照系统条件调整,例如下面的参数:

soft nofile 100000
hard nofile 100000

设置合理的存储位置

Kafka 追求的是极致的顺序写盘速度。必须用物理盘! SSD 当然爽,但其实普通的 HDD 机械硬盘做 RAID 10 也完全够用,因为 Kafka 是顺序写,机械盘的顺序写性能并不差。

但是不要把Kafka的数据目录挂载到网络存储NFS。也不要使用RAID 5级别的盘。

RAID 5 的写性能惩罚太重了。不如直接用 JBOD(Just a Bunch of Disks),配置多个 log.dirs,让 Kafka 自己去把数据分摊到不同的盘上。这样坏一块盘,只丢一部分数据(靠副本恢复),总比 RAID 重建的时候整个阵列性能拖垮要强。

合理配置ZooKeeper

虽然现在的 Kafka 推出了 Kraft 模式(去 ZK 模式),但在生产环境,暂时还是使用 Zookeeper 保险一些。Kraft 虽好,但还得再跑个一两年才敢说是真的稳。

ZK 集群搭建没啥好说的,节点数必须是奇数,3 个或者 5 个。为啥?为了防脑裂,过半数机制嘛。

适当优化tickTime:默认是 2000ms。如果网络环境稍微抖一下,或者 GC 稍微卡一下,ZK 就会觉得节点挂了。稍微调大点,比如 3000ms 甚至 tickTime=2000 配合 initLimit 和 syncLimit 调大倍数,给网络抖动留点面子。

ZK 的 dataLogDir 最好和 dataDir 分开,放在不同的磁盘上。ZK 对事务日志的写入延迟非常敏感,别让它跟快照文件抢磁盘 IO。

优化server.properties配置

1. broker.id

这个不用说了吧,每个节点必须不一样。

2. listeners 和 advertised.listeners

这是新手最大的噩梦,没有之一。 多少人死在这上面,外网死活连不上,或者内网通了外网不通。

listeners 是你耳朵听哪里的声音。比如 PLAINTEXT://0.0.0.0:9092,意思是只要是发到这台机器 9092 端口的,我都听。

advertised.listeners 是你对外发出去的名片。告诉客户端:“嘿,你要找我,请打这个电话”。

如果你在云服务器上,内网有个 IP 192.168.0.2,外网有个公网 IP 8.8.8.8。

listeners 你就写内网 IP 或者 0.0.0.0。

advertised.listeners 你必须写客户端能访问到的那个 IP。如果你的生产者在公网,这儿就得填 8.8.8.8。如果你填了内网 IP,客户端连上一看:“哦,去连 192.168.0.2”,然后它根本访问不到这个内网 IP,直接超时报错。

3. num.partitions

默认是 1。很多教程让你改大点,但是建议不要修改。

这个是全局默认配置。你把它改成 100,以后随便建个测试 Topic 都是 100 个分区,成千上万个分区会把 ZK 和 Controller 累死的。

保持默认 1 或者 3 就行了。真正重要的 Topic,建的时候手动指定分区数。

4. log.retention.hours

默认 168 小时(7天)。

问问你们的存储预算。如果流量巨大,7天的数据能把你磁盘撑爆。我就见过因为日志没清掉,磁盘满了,Kafka 直接宕机的。对于很多日志类业务,保留 48 小时甚至 24 小时通常就够了。

配合 log.retention.bytes 使用效果更佳,比如限制每个分区最大 1GB,双保险。

5. min.insync.replicas

这是数据安全的核心。

默认是 1。这太危险了。如果是 1,只要 Leader 自己活着,它就敢告诉你“写入成功”。万一 Leader 下一秒挂了,副本还没同步过去,数据就丢了。

建议设成 2。也就是说,至少得有两个节点(Leader + 一个 Follower)确认收到了消息,才算成功。

当然,这得配合生产者的 acks=all 使用。

如果你设了 min.insync.replicas=2,但是你的集群一共只有 2 个节点,那只要挂一台,你的集群就变成“只读”了,写入会全部失败。所以,3 节点集群是起步价。

JVM相关设置

Kafka 的设计理念非常特别。它极度依赖操作系统的 Page Cache(页缓存)。它读写文件,其实都是在跟操作系统的内存打交道,然后由操作系统异步刷到盘里。

如果给 JVM 堆内存分了 30G,那留给操作系统的 Page Cache 就少了 30G。Kafka 反而会变慢。

对于 Kafka Broker 来说,堆内存(Heap)通常 6G 到 10G 就绰绰有余了。它不需要在堆里缓存大量数据,它只是做个搬运工。剩下的几十 G 内存,全部留给操作系统去做 Page Cache,这才是性能起飞的秘密。

修改启动脚本 kafka-server-start.sh,找到 KAFKA_HEAP_OPTS,改成:

-Xmx6G -Xms6G

记得加上 G1 垃圾回收器,JDK 1.8 以后 G1 的表现还是很稳的:

-XX:+UseG1GC

使用Systemd管理服务

使用 nohup bin/kafka-server-start.sh config/server.properties &不方便不安全也不好管理,推荐使用Systemd进行统一管理。

使用systemctl start kafka要安全规范许多。还能配置开机自启,进程挂了自动重启。

vim /usr/lib/systemd/system/kafka.service

[Unit]
Description=Apache Kafka
Requires=zookeeper.service
After=zookeeper.service

[Service]
Type=simple
User=kafka
ExecStart=/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/server.properties
ExecStop=/usr/local/kafka/bin/kafka-server-stop.sh
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

查看日志验证服务状态

用自带的 kafka-console-producer.sh 往里灌几条数据,再开个 kafka-console-consumer.sh 看看能不能读出来。

还得看日志!

去 logs/server.log 里看一眼。有没有 Error?有没有频繁的 GC 警告?有没有 Connection refused?

如果有 Controller 频繁切换的日志,那说明你的网络或者 ZK 不稳,赶紧查,别等业务上线了再查。

配置监控项

Kafka 这东西,内部黑盒。你必须得配监控。

最起码,得搞个 Kafka Eagle(现在叫 EFAK)或者 Prometheus + Grafana。

你要盯着两个最重要的指标:

Consumer Lag(消费积压):这是业务死活的晴雨表。

Under Replicated Partitions(未同步分区):这个指标如果不为 0,说明有 Broker 掉队了或者挂了,数据处于危险状态,必须立刻马上处理。

0

评论 (0)

取消