当前位置: 首页 > news >正文

【八股消消乐】Kafka集群 full GC 解决方案

在这里插入图片描述

😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点,期待与你一同探索、学习、进步,一起卷起来叭!

目录

  • 题目
  • 答案
    • 优化生产者
      • 优化acks
      • 优化批次
      • 启用压缩
    • 优化broker
      • 优化 swap
      • 优化网络读写缓冲区
      • 优化磁盘 IO
      • 优化主从同步
      • 优化JVM

题目

💬技术栈:RocketMQ、Kafka、RabbitMQ

🔍简历内容:为解决xx业务高峰期响应时间长、客户端超时问题,通过优化acks、批次并将压缩算法从 Snappy 更换为 LZ4,提高生产者发送效率。经排查,kafka 集群触发了 full GC 之后,停顿时间就会很长,导致 Kafka 吞吐量显著下降,有时候还会导致 Kafka 认为主分区已经崩溃触发主从选举,通过调大 JVM 的堆,并且在堆很大的情况下,启用 G1 垃圾回收器解决了问题。

🚩面试问:Kafka 还有一些参数也对性能有影响,你能介绍一下你是如何优化的吗?


在这里插入图片描述

💡建议暂停思考10s,你有答案了嘛?如果你有不同题解,欢迎评论区留言、打卡。


答案

简历准备:

  • 你维护的业务在使用消息队列的时候,后面优化措施中提到的参数取值都是多少?
  • 你们公司消息队列的各个参数有没有被调过?为什么调?
  • 是否遇到过和消息队列有关的 Bug?如果有,那么怎么解决的?
  • 维护的业务使用消息队列时的 QPS 是多少

场景准备:高并发的消息队列使用场景,要求高效发送、高效消费,不然就会有问题,比如说出现消息积压或者生产者阻塞的问题。

整理思路:从消息队列的生产者、broker 和消费者这三方出发。

优化生产者

优化acks

场景:有一个系统在一个高并发场景下会发送消息到 Kafka,结果发现这个接口在业务高峰的时候响应时间很长,客户端经常遇到超时的问题

排查后:写这段代码的人直接复制了已有的发送消息代码,而原本人家的业务追求的是消息不丢,所以 acks 设置成了 all。实际上这个业务并没有那么严格的消息不丢的要求,完全可以把 acks 设置为 0。

效果:这么一调整,整个接口的响应时间就显著下降了,客户端那边也很少再出现超时的问题。

不过追求消息不丢失的业务场景就不能把 acks 设置为 0 或者 1,这时候就只能考虑别的优化手段,比如说优化批次。

优化批次

场景:生产者发送消息的性能问题。

排查后:因为发送性能太差,导致发送缓冲池已经满了,阻塞了发送者。这个时候我们注意到其实发送速率还没有达到 broker 的阈值,也就是说,broker 其实是处理得过来的。

解决方案:在这种情况下,最直接的做法就是加快发送速率,也就是调大 batch.size 参数,从原本的 100 调到了 500,就没有再出现过阻塞发送者的情况了。

在这里插入图片描述

当然,批次也不是说越大越好。

原因:批次大了的话,生产者这边丢失数据的可能性就比较大。而且批次大小到了一个地步之后,性能瓶颈就变成了 broker 处理不过来了,再调大批次大小是没有用的。最好的策略,还是通过压测来确定合适的批次大小


发送者被阻塞也可能是因为缓冲池太小

解决方案:调大缓冲池

原因:topic、分区太多,每一个分区都有一块缓冲池装着批量消息,导致缓冲池空闲缓冲区不足,这一类不是因为发送速率的问题导致的阻塞,就可以通过调大缓冲池来解决。

在这里插入图片描述

所以发送者阻塞要仔细分析,如果是发送速率的问题,那么调大发送缓冲区是治标不治本的。如果发送速率没什么问题,确实就是因为缓冲池太小引起的,就可以调大缓冲池。如果现实中,也比较难区别这两种情况,就可以考虑先调大批次试试,再调整缓冲池。

启用压缩

场景:Kafka 默认是不启用压缩的,为了进一步提高 Kafka 的吞吐量,我也开启了 Kafka 的压缩功能,使用了 LZ4 压缩算法。【为了进一步提高 Kafka 的吞吐量,我将压缩算法从 Snappy 换到了 LZ4。】

一定要做性能测试

优化broker

优化 swap

Kafka 是一个非常依赖内存的应用,所以可以调小 vm.swappniess 参数来优化内存。

为了优化 Kafka 的性能,可以调小 vm.swappiness。比如说调整到 10,这样就可以充分利用内存;也可以调整到 1,这个值在一些 linux 版本上是指进行最少的交换,但是不禁用交换。目前我们公司用的就是 10。

为什么不直接禁用 swap 呢?

物理内存总是有限的,所以直接禁用的话容易遇到内存不足的问题。我们只是要尽可能优化内存,如果物理内存真的不够,那么使用交换区也比系统不可用好

在这里插入图片描述

优化网络读写缓冲区

Kafka 也是一个网络 IO 频繁的应用,所以调整网络有关的读写缓冲区,效果也会更好。对应的参数有6个。

  • net.core.rmem_default 和 net.core.wmem_default:Socket 默认读写缓冲区大小。
  • net.core.rmem_max 和 net.core.wmem_max:Socket 最大读写缓冲区。
  • net.ipv4.tcp_wmem 和 net.ipv4.tcp_rmem:TCP 读写缓冲区。它们的值由空格分隔的最小值、默认值、最大值组成。可以考虑调整为 4KB、64KB 和 2MB。

回答模板:调大读写缓冲区。Scoket 默认读写缓冲区可以考虑调整到 128KB;Socket 最大读写缓冲区可以考虑调整到 2MB,TCP 的读写缓冲区最小值、默认值和最大值可以设置为 4KB、64KB 和 2MB。不过这些值究竟多大,还是要根据 broker 的硬件资源来确定。

优化磁盘 IO

Kafka 也是一个磁盘 IO 密集的应用,所以可以从两个方向优化磁盘 IO。
(1)使用 XFS 作为文件系统,它要比 EXT4 更加适合 Kafka。相比于 EXT4,XFS 性能更好。在同等情况下,使用 XFS 的 Kafka 要比 EXT4 性能高 5% 左右。XFS还有别的优点,例如扩展性更好,支持更多、更大的文件。
(2)禁用 Kafka 用不上的 atime 功能

优化主从同步

总结: 都调大,它们的效果,就是为了让从分区一批次同步尽可能多的数据

从分区和主分区数据同步的过程受到了几个参数的影响。

  • num.replica.fetchers:从分区拉取数据的线程数量,默认是1。你可以考虑设置成 3。
  • replica.fetch.min.bytes:可以通过调大这个参数来避免小批量同步数据
  • replica.fetch.max.bytes:这个可以调大,比如说调整到 5m,但是不要小于 message.max.byte,也就是不要小于消息的最大长度。
  • replica.fetch.wait.max.ms:如果主分区没有数据或者数据不够从分区的最大等待时间,可以考虑同步调大这个值和 replica.fetch.max.bytes。
    在这里插入图片描述

首先调整从分区的同步数据线程数量,比如说调整到 3,这样可以加快同步速率,但是也会给主分区和网络带宽带来压力。

其次是调整同步批次的最小和最大字节数量,越大则吞吐量越高,所以都尽量调大。

最后也可以调整从分区的等待时间,在一批次中同步尽可能多的数据。

不过调大到一定地步之后,瓶颈就变成了从分区来不及处理。或者调大到超过了消息的并发量,那么也没意义了。

Kafka 这种机制可以看作是典型的批量拉数据模型。在这个模型里面,要着重考虑的就是多久拉一次,没有怎么办,一次拉多少?在实现这种模型的时候,让用户根据自己的需要来设定参数是一个比较好的实践。

优化JVM

Kafka 是运行在 JVM 上的,所以理论上来说任何优化 Java 性能的措施,对 Kafka 也一样有效果。

优化 JVM:

(1)首先就是考虑优化 GC,即优化垃圾回收。而优化 GC 最重要的就是避免 full GC。full GC 是指整个应用都停下来等待 GC 完成。它会带来两方面影响。一方面是发送者如果设置 acks 为 1 或者 all,都会被阻塞,Kafka 吞吐量下降

在这里插入图片描述

(2)如果 full GC 时间太长,那么主分区可能会被认为已经崩溃了,Kafka 会重新选择主分区;而如果是从分区,那么它会被挪出 ISR,进一步影响 acks 设置为 all 的发送者

在这里插入图片描述

基本的思路就是调大 JVM 的堆,并且在堆很大的情况下,启用 G1 垃圾回收器

之前我们的 Kafka 集群还出过 GC 引发的性能问题。我们有一个 Kafka 的堆内存很大,有 8G,但是垃圾回收器还是用的 CMS。触发了 full GC 之后,停顿时间就会很长,导致 Kafka 吞吐量显著下降,并且有时候还会导致 Kafka 认为主分区已经崩溃,触发主从选举

优化思路:

(1)一个是考虑优化 CMS 本身,比如说增大老年代,但是这个治标不治本,可以缓解问题,但是不能根治问题。
(2)直接切换到 G1 回收器。G1 回收器果然表现得非常好,垃圾回收频率和停顿时间都下降了。


往期精彩专栏内容,欢迎订阅:

🔗【八股消消乐】20250711:浅尝Kafka性能优化
🔗【八股消消乐】20250630:消息队列优化—重复消费
🔗【八股消消乐】20250629:消息队列优化—消息丢失
🔗【八股消消乐】20250627:消息队列优化—消息积压
🔗【八股消消乐】20250625:消息队列优化—消息有序
🔗【八股消消乐】20250624:消息队列优化—延迟消息
🔗【八股消消乐】20250623:消息队列优化—系统架构设计
🔗【八股消消乐】20250622:Elasticsearch查询优化
🔗【八股消消乐】20250620:Elasticsearch优化—检索Labubu
🔗【八股消消乐】20250619:构建微服务架构体系—保证服务高可用
🔗【八股消消乐】20250615:构建微服务架构体系—链路超时控制
🔗【八股消消乐】20250614:构建微服务架构体系—实现制作库与线上库分离
🔗【八股消消乐】20250612:构建微服务架构体系—限流算法优化
🔗【八股消消乐】20250611:构建微服务架构体系—降级策略全总结
🔗【八股消消乐】20250610:构建微服务架构体系—熔断恢复抖动优化
🔗【八股消消乐】20250609:构建微服务架构体系—负载均衡算法如何优化
🔗【八股消消乐】20250608:构建微服务架构体系—服务注册与发现
🔗【八股消消乐】20250607:MySQL存储引擎InnoDB知识点汇总
🔗【八股消消乐】20250606:MySQL参数优化大汇总
🔗【八股消消乐】20250605:端午节产生的消费数据,如何分表分库?
🔗【八股消消乐】20250604:如何解决SQL线上死锁事故
🔗【八股消消乐】20250603:索引失效与优化方法总结
🔗【八股消消乐】20250512:慢SQL优化手段总结
🔗【八股消消乐】20250511:项目中如何排查内存持续上升问题
🔗【八股消消乐】20250510:项目中如何优化JVM内存分配?
🔗【八股消消乐】20250509:你在项目中如何优化垃圾回收机制?
🔗【八股消消乐】20250508:Java编译优化技术在项目中的应用
🔗【八股消消乐】20250507:你了解JVM内存模型吗?
🔗【八股消消乐】20250506:你是如何设置线程池大小?
🔗【八股消消乐】20250430:十分钟带背Duubo中大厂经典面试题
🔗【八股消消乐】20250429:你是如何在项目场景中选取最优并发容器?
🔗【八股消消乐】20250428:你是项目中如何优化多线程上下文切换?
🔗【八股消消乐】20250427:发送请求有遇到服务不可用吗?如何解决?

📌 [ 笔者 ]   文艺倾年
📃 [ 更新 ]   2025.7.11
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

在这里插入图片描述

http://www.lryc.cn/news/585965.html

相关文章:

  • 系统分析师-计算机系统-输入输出系统
  • 计算机视觉与深度学习 | 基于Matlab的多特征融合可视化指纹识别系统(附完整代码)
  • 3 c++提高——STL常用容器(一)
  • 深度学习图像分类数据集—铜片划痕识别分类
  • RocketMQ-
  • 基于springboot+Vue的二手物品交易的设计与实现
  • MySQL 内外连接
  • 仅27M参数!SamOutVX轻量级语言模型刷新认知,小身材也有大智慧
  • 贪心算法题解——跳跃游戏【LeetCode】
  • day68—DFS—二叉树的所有路径(LeetCode-257)
  • 贪心算法题解——划分字母区间【LeetCode】
  • 【LeetCode453.最小操作次数使数组元素相等】
  • 代码训练LeetCode(45)旋转图像
  • 【Linux-云原生-笔记】Apache相关
  • 【Modern C++ Part9】Prefer-alias-declarations-to-typedefs
  • 内网穿透系列九:开源的网络穿透与组网工具 EasyTier,支持多种数据传输通道,去中心化,兼具高效与安全
  • Kafka Schema Registry:数据契约管理的利器
  • 对日开发 秀丸文本编辑器 添加文本变换模块
  • 聊一聊Spring框架接口测试常见场景有哪些?
  • 学习C++、QT---22(QT中QTextStream库读取文件、写入文件的讲解)
  • docker搭建 与镜像加速器
  • win10安装Rust Webassembly工具链(wasm-pack)报错。
  • C++中Lambda表达式 [ ] 的写法
  • AI 时代的分布式多模态数据处理实践:我的 ODPS 实践之旅、思考与展望
  • 深入解析 Stack 和 Queue:从原理到实战应用
  • 每日算法刷题Day46 7.12:leetcode前缀和3道题和差分2道题,用时1h30min
  • pgsql模板是什么?
  • Redis Geospatial 功能详解及多边形包含判断实现
  • 【JVM|类加载】第三天
  • 专业硬件检测工具 AIDA64 Extreme V7.70.7500 至尊版