Kafka集群怎么搭才不炸?这篇万字避坑指南,建议收藏落灰
昨晚有个做开发的朋友请我撸串,几瓶黄汤下肚,抱着我哭。说他们组自己搭的 Kafka 集群,最近老是莫名其妙的 Rebalance,消费端卡得跟PPT似的,运维又不给力,锅全扣他头上了。
我一听,这剧本我熟啊。
很多公司不管大不大,都喜欢用 Kafka。为啥?吞吐量大啊,削峰填谷神器啊。但是,Kafka 这玩意儿属于“入门容易精通难”,它的很多默认配置,说实话,那是给笔记本电脑用的,不是给服务器用的。
咱们今天不搞那些念经似的理论,直接上干货。假设你要搞个 3 节点的集群(最起码的配置),系统是 CentOS 7 或者 8,咱们一步步来,把那些坑都给你填平了。
咱先别急着解压安装包
很多人上来就 wget,别急。
在这之前,有几件关于操作系统的事儿,你必须得干。这就像盖房子,地基没打好,你盖个别墅也是危房。
第一,把那个该死的 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 个句柄?那是打发叫花子的。
去 /etc/security/limits.conf,给它加满:
* soft nofile 100000
* hard nofile 100000少于十万,你都不好意思说你在跑 Kafka。
第三,磁盘的选择。
我有次去救火,发现他们把 Kafka 的数据目录挂载在了一块 NFS(网络存储)上。我当时就想报警。
Kafka 追求的是极致的顺序写盘速度。必须用物理盘! SSD 当然爽,但其实普通的 HDD 机械硬盘做 RAID 10 也完全够用,因为 Kafka 是顺序写,机械盘的顺序写性能并不差。
重点来了: 如果你有几块盘,不要做 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。
Kafka 的重头戏:server.properties
好了,主角登场。解压 Kafka 包,进入 config 目录,打开那个长得吓人的 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 这么牛逼,我给它分个 32G 内存不过分吧?
大错特错!
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
启动!别用 nohup 了求求你
都 2025 年了,还在用 nohup bin/kafka-server-start.sh config/server.properties &?
这也太土了,而且不安全。进程挂了谁给你拉起来?
写个 Systemd 服务文件吧,也就几行字的事儿。/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这样,systemctl start kafka,多优雅。还能配置开机自启,进程挂了自动重启。
验证一下,别高兴太早
服务起起来了,绿灯亮了,就算完了?
年轻。
你得亲自去发几条消息试试。
用自带的 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 掉队了或者挂了,数据处于危险状态,必须立刻马上处理。
总结
搭一套 Kafka 集群,真不是解压运行那么简单。
你是要当那个每天提心吊胆、手机一响就哆嗦的“救火队员”,还是想当个喝着茶水看监控波澜不惊的“稳健老哥”,全看你部署的时候那点细节功夫下没下到位。
参数调优这事儿,没有标准答案,只有最适合你业务场景的答案。但我上面提的这些,是无数个通宵熬出来的血泪教训,照着做,至少能保你底盘不崩。
行了,这篇要是对你有用,别光顾着收藏。赶紧关注 @运维躬行录。
咱这儿不整那些虚头巴脑的概念,只聊最真实的运维坑,只给最实用的避雷针。下次咱们聊聊怎么不动声色地给 Kafka 集群做在线扩容,那才是真的刺激。
转发给你的兄弟们,咱们下回见!