在选择压缩算法的时候,首先要考虑的就是压缩比和压缩速率。压缩比主要是为了节省网络带宽和磁盘存储空间,而压缩速率主要影响吞吐量。
一般来说,压缩比越高,压缩速率越低;压缩比越低,压缩速率越高。
在现代操作系统中,基本都支持交换区,也叫做 swap 分区。当操作系统发现可用的物理内存不足的时候,就会把物理内存里的一部分页淘汰出来,放到磁盘上,也就是放到 swap 分区。
你也可以把 swap 分区看作是“虚拟内存”。那么你可以想到,如果触发了这种交换,性能就会显著下降。交换越频繁,下降越快。
在 Linux 中有一个参数,叫做 vm.swappniess,它控制住了使用交换区的积极性。比如说 vm.swappniess 在大多数 linux 发行版上默认值都是 60,也就是比较积极地使用交换区。而追求性能的中间件,如消息队列、数据库等都会尽量避免触发交换,也就是把 vm.swappniess 调小。
有一种说法是当内存使用率超过 40% 的时候就开始使用 swap 分区,但是这种说法其实不够准确,因为是否交换在 Linux 2.6 以后的版本后还参考了别的因素。
在消息不丢失那一节课里面。在尝试优化 acks 的时候,如果追求性能,那么就应该把 acks 设置为 0。(可能会丢消息)
如果追求消息不丢失,那么就应该把 acks 设置为 all
优化批次有两个好处,对于生产者本身来说,它发送消息的速率更快;对于 Kafka 来说,同样数量的消息,批次越大,性能越好。
所以当你的发送者遇到瓶颈之后,就可以尝试调大批次的参数来进一步提高发送性能。和批次有关的有两个参数:linger.ms 和 batch.size。前者是凑够一个批次的最大等待时间,后者是一个批次最大能有多少字节。你可以先简单介绍你的优化手段,关键词是调大批次。
之前遇到过一个生产者发送消息的性能问题。后来我们经过排查之后,发现是因为发送性能太差,导致发送缓冲池已经满了,阻塞了发送者。这个时候我们注意到其实发送速率还没有达到 broker 的阈值,也就是说,broker 其实是处理得过来的。在这种情况下,最直接的做法就是加快发送速率,也就是调大 batch.size 参数,从原本的 100 调到了 500,就没有再出现过阻塞发送者的情况了。
调大批次究竟能有多大的优化效果和调整前后批次大小、消息平均大小、borker 负载有关。好的时候 TPS 可以翻倍,差的时候可能也就是提升 10% 不到。所以最好亲自动手试一试业务调整这个参数性能究竟能提升多少。
为了进一步提高 Kafka 的吞吐量,开启了 Kafka 的压缩功能,使用了 LZ4 压缩算法。
Kafka 是一个非常依赖内存的应用,所以可以调小 vm.swappniess 参数来优化内存。为了优化 Kafka 的性能,可以调小 vm.swappiness。比如说调整到 10,这样就可以充分利用内存;也可以调整到 1,这个值在一些 linux 版本上是指进行最少的交换,但是不禁用交换。目前我们公司用的就是 10。
为什么不直接禁用 swap 呢?
Kafka 也是一个网络 IO 频繁的应用,所以调整网络有关的读写缓冲区,效果也会更好。对应的参数有 6 个。
这些参数记不住没有关系,记住一个点调大读写缓冲区就可以。
另外一个优化方向是调大读写缓冲区。Scoket 默认读写缓冲区可以考虑调整到 128KB;Socket 最大读写缓冲区可以考虑调整到 2MB,TCP 的读写缓冲区最小值、默认值和最大值可以设置为 4KB、64KB 和 2MB。不过这些值究竟多大,还是要根据 broker 的硬件资源来确定。
Kafka 显然也是一个磁盘 IO 密集的应用。优化磁盘 IO 的两个方向就是调整文件系统,使用 XFS,并且禁用 atime。atime 是指文件最后的访问时间,而本身 Kafka 用不上。
Kafka 也是一个磁盘 IO 密集的应用,所以可以从两个方向优化磁盘 IO。一个是使用 XFS 作为文件系统,它要比 EXT4 更加适合 Kafka。另外一个是禁用 Kafka 用不上的 atime 功能。
从分区和主分区数据同步的过程受到了几个参数的影响。
这些参数都是跟机器有关的,需要通过不断测试来确认这些参数的最佳值。如果记不住细节,那就记住都调大。尤其是后三个,调大它们的效果,就是为了让从分区一批次同步尽可能多的数据。
Kafka 的主从分区同步也可以优化。首先调整从分区的同步数据线程数量,比如说调整到 3,这样可以加快同步速率,但是也会给主分区和网络带宽带来压力。其次是调整同步批次的最小和最大字节数量,越大则吞吐量越高,所以都尽量调大。最后也可以调整从分区的等待时间,在一批次中同步尽可能多的数据。
Kafka 是运行在 JVM 上的,所以理论上来说任何优化 Java 性能的措施,对 Kafka 也一样有效果。如果你是面试 Java 岗位,那么这个点会非常适合你,因为你可以同时展示你对 JVM 的理解,让你赢得竞争优势。
优化 JVM 首先就是考虑优化 GC,即优化垃圾回收。而优化 GC 最重要的就是避免 full GC。full GC 是指整个应用都停下来等待 GC 完成。它会带来两方面影响。一方面是发送者如果设置 acks 为 1 或者 all,都会被阻塞,Kafka 吞吐量下降。
基本的思路就是调大 JVM 的堆,并且在堆很大的情况下,启用 G1 垃圾回收器。
之前我们的 Kafka 集群还出过 GC 引发的性能问题。我们有一个 Kafka 的堆内存很大,有 8G,但是垃圾回收器还是用的 CMS。触发了 full GC 之后,停顿时间就会很长,导致 Kafka 吞吐量显著下降,并且有时候还会导致 Kafka 认为主分区已经崩溃,触发主从选举。
在这种情况下,有两个优化思路,一个是考虑优化 CMS 本身,比如说增大老年代,但是这个治标不治本,可以缓解问题,但是不能根治问题。所以综合之下我选了另外一个方向,直接切换到 G1 回收器。G1 回收器果然表现得非常好,垃圾回收频率和停顿时间都下降了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。