服务公告
Kafka:性能优化
发布时间:2026-04-26 08:00
搞过Kafka集群的人都懂,最烦的是消息堆积、消费者卡死、吞吐量上不去,明明压测的时候好好的,一到生产环境就拉胯。今天把这几年调优Kafka踩过的坑整理成实战手册,照着做能解决80%的性能问题。
一、操作步骤
步骤1:先看消费者lag,这是最直观指标
# 查看所有消费者组 lag 情况
kafka-consumer-groups.sh --bootstrap-server 你的节点:9092 --all-groups --describe
# 预期输出(正常状态lag接近0)
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG
my-consumer test-topic 0 123456 123456 0
my-consumer test-topic 1 789012 789012 0如果LAG持续增长,说明消费者跟不上生产速度。别急着加机器,先看下面几个参数。
步骤2:调整fetch.min.bytes和fetch.max.wait.ms(消费者端)
# 消费者配置文件consumer.properties
fetch.min.bytes=1048576 # 每次fetch最少拉1MB,减少网络往返
fetch.max.wait.ms=500 # broker最多等500ms再返回数据
# CentOS/RHEL路径
/etc/kafka/consumer.properties
# Ubuntu路径
/etc/kafka/consumer.properties这两个参数配合使用,broker会等满1MB数据或者超时时间到了才返回,比默认的小包频繁拉取效率高3-5倍。
步骤3:JVM堆内存设置——Kafka对内存敏感
# CentOS/RHEL - Kafka启动脚本
export KAFKA_HEAP_OPTS="-Xms8g -Xmx8g -XX:+UseG1GC"
# Ubuntu - systemd方式
# /etc/systemd/system/kafka.service
Environment="KAFKA_HEAP_OPTS=-Xms8g -Xmx8g -XX:+UseG1GC"
# 重启生效
sudo systemctl restart kafka
sudo systemctl status kafka # 确认进程内存占用⚠️ 警告:内存不要设太大,否则GC停顿时间变长反而影响性能,建议物理内存的50%以内。
步骤4:调整num.network.threads和num.io.threads(Broker端)
# server.properties
# 网络处理线程数 - CPU核心数的2倍
num.network.threads=12
# IO处理线程数 - CPU核心数的2到3倍
num.io.threads=24
# CentOS/RHEL路径
/etc/kafka/server.properties
# Ubuntu路径
/etc/kafka/server.properties这两个参数管着Broker处理请求的能力,线程不够会导致请求排队,客户端感觉就是卡。
步骤5:刷盘策略——吞吐量和数据安全的关键权衡
# server.properties
log.flush.interval.ms=1000 # 消息落盘间隔,太频繁影响性能
log.flush.interval.messages=50000 # 每5万条消息强制刷盘
log.flush.scheduler.interval.ms=1000 # 定期检查是否需要刷盘
# 如果追求吞吐量可以设成这样(丢数据风险提高)
log.flush.interval.ms=5000
log.flush.interval.messages=100000高并发场景下默认的刷盘策略太保守,调大后吞吐量能翻倍,但记得做好监控。
步骤6:调整replica.lag.time.max.ms防止误踢出消费者
# server.properties
replica.lag.time.max.ms=30000 # 30秒内follower没同步就认为掉队
replica.lag.max.messages=10000 # CentOS/RHEL旧版本用这个参数
# 建议生产环境
replica.lag.time.max.ms=60000 # 网络抖动时给更多缓冲时间网络抖动时这个参数设太小会把正常的follower踢出去,导致ISR收缩,数据安全性反而降低。
步骤7:批量发送参数(生产者端)
# producer.properties
batch.size=1048576 # 批量大小16KB,调大能提高吞吐
linger.ms=10 # 等待时间,0是低延迟,10是高吞吐
buffer.memory=67108864 # 64MB缓冲区
compression.type=snappy # 压缩格式,snappy性能好,gzip压缩率高
# CentOS/RHEL路径
/etc/kafka/producer.properties
# Ubuntu路径
/etc/kafka/producer.properties批量+压缩这两个参数配合好,单机吞吐量从10万/s能拉到30万/s。
步骤8:验证调优效果——压测工具跑一遍
# 用Kafka官方压测脚本
# 生产者压测
kafka-producer-perf-test.sh
--topic perf-test
--num-records 1000000
--throughput 500000
--record-size 1024
--producer-props bootstrap.servers=节点:9092 acks=1
# 预期输出(调优后应该明显提升)
1000000 records sent, 456123.456 records/sec, 456.12 MB/sec压测结果和调优前对比,吞吐量提升不到30%就说明瓶颈可能在别的方向,比如网络带宽或磁盘IO。
二、常见问题FAQ
Q:消息堆积了几百万,删掉旧partition还是堆积怎么办?
A:别急着删partition,那是治标不治本。先看消费者端fetch配置是不是太小,10个消费者拉不动就加到20个,同时检查消费者代码有没有阻塞数据库操作这种拖后腿的操作。还有个坑是同一个消费者组里有人pause了但没resume,导致整个组卡死。
Q:Kafka进程内存占用远超Xmx设置的值,正常吗?
A:正常,Kafka用到了off-heap内存,主要是页缓存。如果机器内存64G,Kafka用了20G物理内存,JVM堆才设了8G,这是正常的page cache。如果你想限制物理内存使用,用cgroup或者systemd的MemoryLimit限制,别靠JVM参数。
Q:网络带宽没跑满但吞吐量上不去,哪里有问题?
A:大概率是单分区瓶颈。Kafka单分区是单线程写的,如果生产者发送很快但单分区吞吐量上不去,整机吞吐就被限制了。解决办法是把Topic分区数调多,让多线程并行写。但注意消费者也要对应增加分区数,不然多分区没意义。
Q:压测的时候TPS很高,但实际运行一段时间后越来越慢?
A:八成是GC问题,G1的停顿时间可以加上-XX:MaxGCPauseMillis=20限制,或者换ZGC(Java 11以上)。另外检查下日志文件是不是没配置滚动,磁盘空间满了直接歇菜。
Q:跨数据中心延迟高,有什么优化手段?
A:跨机房Kafka延迟主要在网络,这个优化空间有限。可以做的是:Producer端开启async模式+大的linger.ms减少请求次数;Broker端把acks设成1而不是-1;网络层面如果能加专线带宽比优化Kafka参数有效得多。
三、总结
Kafka性能调优的核心就三点:消费者lag监控要到位、内存和网络线程配置要匹配机器硬件、生产端批量压缩组合要打满带宽。调参不是一次性工作,是持续观察持续优化的过程。
延伸阅读:
- Confluent官方的Kafka调优白皮书
- Apache Kafka官方文档的performance章节
- Monitoring Kafka best practices(监控Lag、吞吐量、GC时间三件套)
相关推荐
上一篇: Memcached:故障排查
下一篇: Mac使用技巧:终端命令