核心配置精讲:server.properties 中那些决定性能的关键参数
说实话,我见过太多团队把 Kafka 集群搭起来就跑,配置几乎全默认。结果呢?线上流量一上来,要么磁盘写爆,要么网络线程堵死,要么日志把磁盘撑满。嗯,今天咱们就掰开揉碎,聊聊 server.properties 里那几个真正决定集群生死的参数。
我个人习惯,调优之前先画一张图,把参数之间的依赖关系理清楚。你想想看,如果连参数影响哪个模块都不清楚,调优就是瞎蒙。
1. log.segment.bytes —— 日志分段,别小看这个值
这个参数控制单个日志段文件的最大字节数。默认是 1GB。很多人觉得没必要改,但我在项目中吃过亏。
有一次,某个 Topic 的流量特别大,每秒写入几十 MB。默认 1GB 的段文件,大概几分钟就切一个。段文件太多,导致文件句柄数飙升,连 ls 命令都卡半天。后来我把 log.segment.bytes 调大到 4GB,段文件数量直接降到原来的四分之一,问题解决。
那到底怎么设?我给你一个参考思路:
| 场景 | 建议值 | 理由 |
|---|---|---|
| 高吞吐写入(>50MB/s) | 4GB - 8GB | 减少段文件数量,降低文件句柄压力 |
| 低吞吐写入(<5MB/s) | 512MB - 1GB | 保持默认即可,段文件少不影响性能 |
| 日志清理频繁的场景 | 256MB - 512MB | 小段文件清理更快,减少 GC 停顿 |
小技巧:我习惯同时调整 log.roll.hours。比如设了 4GB 分段,再把滚动时间设成 24 小时。这样段文件要么写满 4GB 才切,要么满 24 小时强制切,避免长时间不写导致段文件过大。
2. num.network.threads —— 网络线程,集群的咽喉
这个参数控制 Broker 处理网络请求的线程数。默认是 3。说实话,3 个线程在现在的硬件条件下根本不够用。
我曾经帮一个客户排查问题,他们的集群 Broker 的 CPU 才用了 20%,但客户端就是超时。一看监控,网络线程池队列积压了几万个请求。把 num.network.threads 从 3 调到 8,问题立刻消失。
为什么?因为网络线程负责接收请求、解析协议、分发到 IO 线程。如果网络线程不够,请求在入口就堵死了,CPU 再闲也没用。
我建议的配置公式:
# 一般建议:num.network.threads = CPU核心数
# 如果网卡队列多(比如 8 队列),可以设为 CPU核心数 * 2
num.network.threads=8
# IO 线程一般设为 CPU核心数 * 2
num.io.threads=16
注意:网络线程不是越多越好。线程太多会导致上下文切换开销过大。我曾经见过有人设成 32,结果 CPU 全花在线程切换上,吞吐量反而下降。建议从 8 开始,逐步加压测试,找到拐点。
3. log.retention.hours —— 日志保留时间,磁盘的命根子
这个参数决定消息在 Kafka 中保留多久。默认是 168 小时,也就是 7 天。很多团队上线时没想清楚,直接保持默认,结果磁盘爆了。
我记得有个案例:某公司每天产生 2TB 数据,保留 7 天就是 14TB。他们只配了 10TB 磁盘,第 5 天就写满了。后来改成保留 3 天,配合压缩策略,磁盘使用率降到 60%。
这里有个关键点:log.retention.hours 是硬删除,时间一到就清理。但如果你同时开启了压缩(cleanup.policy=compact),那保留时间只对未压缩的段有效。
我一般这样评估:
- 日志类数据:保留 24-72 小时。丢了也不心疼,关键是实时性。
- 业务消息:保留 7 天。万一消费端挂了,还有时间恢复。
- 审计/合规数据:保留 30 天以上。但建议用压缩策略,只保留每个 Key 的最新值。
避坑指南:我曾经遇到一个坑——log.retention.hours 设了 24 小时,但磁盘还是涨。查了半天发现是 log.retention.bytes 没设。如果 Topic 数据量极小,24 小时都写不满一个段文件,Kafka 不会触发清理。建议两个参数都设:log.retention.bytes=-1(不限制大小),或者设一个合理的上限。
4. 其他几个不能忽略的参数
除了上面三个,还有几个参数我每次调优都会看:
| 参数 | 默认值 | 我的建议 | 说明 |
|---|---|---|---|
| log.cleaner.threads | 1 | 2-4 | 压缩清理线程,多线程能加速日志清理,减少磁盘占用 |
| log.cleaner.dedupe.buffer.size | 128MB | 512MB - 2GB | 去重缓冲区,越大压缩效率越高,但占用更多内存 |
| compression.type | producer | lz4 或 zstd | Broker 端压缩,能减少磁盘占用和网络传输,但增加 CPU 开销 |
| unclean.leader.election.enable | false | false | 千万别开!允许非 ISR 副本成为 Leader 会导致数据丢失 |
个人经验:我一般先调 num.network.threads 和 num.io.threads,这两个直接影响吞吐。然后根据磁盘容量和写入速度调 log.segment.bytes 和 log.retention.hours。最后再根据 CPU 使用率决定是否开启压缩。顺序很重要,别一上来就全改。
5. 实战:一次完整的参数调优过程
给你看一个我最近做的调优案例。集群配置:32 核 CPU,64GB 内存,4 块 NVMe 磁盘(RAID 0)。
初始配置(默认):
num.network.threads=3
num.io.threads=8
log.segment.bytes=1073741824 # 1GB
log.retention.hours=168
log.cleaner.threads=1
压测结果:吞吐量 80MB/s,P99 延迟 120ms。网络线程队列经常积压到 5000+。
调优后:
num.network.threads=8
num.io.threads=16
log.segment.bytes=4294967296 # 4GB
log.retention.hours=72
log.cleaner.threads=4
压测结果:吞吐量 220MB/s,P99 延迟 35ms。网络线程队列几乎为 0。
你看,参数调好了,性能翻倍都不止。但要注意,这个配置只适合这个场景。你的集群如果磁盘慢、CPU 少,就得重新算。
最后提醒一句:改参数之前,一定先备份 server.properties。我见过有人改完重启起不来的,就是因为参数写错了。改完后用 kafka-configs.sh 验证一下,别直接重启。