Kafka参数调优

集群规划

如果你需要要部署大规模的 Kafka 集群,建议的方式是,拆分成多个互相独立的小集群部署,每个小集群都使用一组独立的 ZooKeeper 提供服务。这样,每个 ZooKeeper 中存储的数据相对比较少,并且如果某个 ZooKeeper 集群故障,只会影响到一个小的 Kafka 集群,故障的影响面相对小一些。

kafka集群性能调优实战

千亿级数据量kafka集群性能调优实战总结

1.broker

配置优化都是修改server.properties文件中参数值
Kafka性能调优

kafka性能调优

jvm和PageCache

pagecache kafka

开启压缩

开启压缩发送传输种提高kafka消息吞吐量的有效办法
(‘gzip’, ‘snappy’, ‘lz4’, ‘zstd’)
producer:

 // 开启 GZIP 压缩
 props.put("compression.type", "lz4");

broker:

compression.type=producer(默认值)

建议使用默认值。
Broker 默认 compression.type=producer,表示brokr会自动适应producerd的压缩算法,也可以指定为compression.type=gzip,注意一定要和produce的端的压缩算法一样。否则broker端会收到消息后解压再压缩为broker端指定的压缩算法,导致 Broker 端 CPU 使用率飙升。
consumer:
无需配置参数。
Kafka 会将启用了哪种压缩算法封装进消息集合中,这样当 Consumer 读取到消息集合时,它自然就知道了这些消息使用的是哪种压缩算法。

在开启压缩时,Kafka 选择一批消息一起压缩,每一个批消息就是一个压缩分段。

使用者也可以通过参数来控制每批消息的大小。我们之前讲过,在 Kafka 中,生产者生成一个批消息发给服务端,在服务端中是不会拆分批消息的。那按照批来压缩,意味着,在服务端也不用对这批消息进行解压,可以整批直接存储,然后整批发送给消费者。最后,批消息由消费者进行解压。也就是说 Producer 发送压缩消息到 Broker 后,Broker 照单全收并原样保存起来。当 Consumer 程序请求这部分消息时,Broker 依然原样发送出去,当消息到达 Consumer 端后,由 Consumer 自行解压缩还原成之前的消息。

启用压缩场景

如果cpu负载比较高,不适合启用压缩;

如果带宽不足,而cpu负载不高,最适合启用压缩,节约大量的带宽;

尽量避免消息格式不一致带来的解压缩消耗。
在这里插入图片描述
在这里插入图片描述
吞吐量要求比较高的建议使用:lz4
网络带宽和磁盘资源不充足的建议使用:snappy

2. producer

  • buffer.memory:33554432 (32m)
    #在Producer端用来存放尚未发送出去的Message的缓冲区大小。缓冲区满了之后可以选择阻塞发送或抛出异常,由block.on.buffer.full的配置来决定。

  • compression.type:none
    #默认发送不进行压缩,推荐配置一种适合的压缩算法,可以大幅度的减缓网络压力和Broker的存储压力。

  • linger.ms:0
    #Producer默认会把两次发送时间间隔内收集到的所有Requests进行一次聚合然后再发送,以此提高吞吐量,而linger.ms则更进一步,这个参数为每次发送增加一些delay,以此来聚合更多的Message。

  • batch.size:16384
    #Producer会尝试去把发往同一个Partition的多个Requests进行合并,batch.size指明了一次Batch合并后Requests总大小的上限。如果这个值设置的太小,可能会导致所有的Request都不进行Batch。

  • acks:1
    #这个配置可以设定发送消息后是否需要Broker端返回确认。

0: 不需要进行确认,速度最快。存在丢失数据的风险。
1: 仅需要Leader进行确认,不需要ISR进行确认。是一种效率和安全折中的方式。
all: 需要ISR中所有的Replica给予接收确认,速度最慢,安全性最高,但是由于ISR可能会缩小到仅包含一个Replica,所以设置参数为all并不能一定避免数据丢失。

buffer.memory 内存缓冲的大小

Kafka的客户端发送数据到服务器,一般都是要经过缓冲的:KafkaProducer发送出去的消息都是先进入到客户端本地的内存缓冲里,然后把很多消息收集成一个一个的Batch,再发送到Broker上去的。
在这里插入图片描述
“buffer.memory”设置KafkaProducer能够使用的内存缓冲的大小的,默认值是32MB。

  • 如果要是内存设置的太小,可能导致一个问题:消息快速的写入内存缓冲里面,但是Sender线程来不及把Request发送到Kafka服务器。
“buffer.memory”如何确定

“buffer.memory”这个参数应该结合自己的实际情况来进行压测,你需要测算一下在生产环境,你的用户线程会以每秒多少消息的频率来写入内存缓冲。

比如说每秒300条消息,那么你就需要压测一下,假设内存缓冲就32MB,每秒写300条消息到内存缓冲,是否会经常把内存缓冲写满?经过这样的压测,你可以调试出来一个合理的内存大小。

“batch.size”大小如何确定

“batch.size”决定了你的每个Batch要存放多少数据就可以发送出去了。
比如说你要是给一个Batch设置成是16KB的大小,那么里面凑够16KB的数据就可以发送了。

这个参数的默认值是16KB,一般可以尝试把这个参数调节大一些,然后利用自己的生产环境发消息的负载来测试一下。

  比如说发送消息的频率就是每秒300条,那么如果比如“batch.size”调节到了32KB,或者64KB,是否可以提升发送消息的整体吞吐量。因为理论上来说,提升batch的大小,可以允许更多的数据缓冲在里面,那么一次Request发送出去的数据量就更多了,这样吞吐量可能会有所提升。

“batch.size”也不能无限的大,过于大了之后,要是数据老是缓冲在Batch里迟迟不发送出去,那么岂不是你发送消息的延迟就会很高。比如说,一条消息进入了Batch,但是要等待5秒钟Batch才凑满了64KB,才能发送出去。那这条消息的延迟就是5秒钟。所以需要在这里按照生产环境的发消息的速率,调节不同的Batch大小自己测试一下最终出去的吞吐量以及消息的 延迟,设置一个最合理的参数。

“linger.ms”

“linger.ms”他的含义就是说一个Batch被创建之后,超过“linger.ms”的时间,不管这个Batch有没有写满,都必须发送出去了。
避免一个Batch迟迟凑不满,导致消息一直积压在内存里发送不出去的情况。这是一个很关键的参数。这个参数一般要非常慎重的来设置,要配合batch.size一起来设置。举个例子,首先假设你的Batch是32KB,那么你得估算一下,正常情况下,一般多久会凑够一个Batch,比如正常来说可能20ms就会凑够一个Batch。那么你的linger.ms就可以设置为25ms,也就是说,正常来说,大部分的Batch在20ms内都会凑满,但是你的linger.ms可以保证,哪怕遇到低峰时期,20ms凑不满一个Batch,还是会在25ms之后强制Batch发送出去。

  如果要是你把linger.ms设置的太小了,比如说默认就是0ms,或者你设置个5ms,那可能导致你的Batch虽然设置了32KB,但是经常是还没凑够32KB的数据,5ms之后就直接强制Batch发送出去,这样也不太好其实,会导致你的Batch形同虚设,一直凑不满数据。
compression.type

compression.type:none
可以设置值:none, gzip, snappy, or lz4.
#默认发送不进行压缩,推荐配置一种适合的压缩算法(gzip, snappy, or lz4.),可以大幅度的减缓网络压力和Broker的存储压力。

acks:1

#这个配置可以设定发送消息后是否需要Broker端返回确认。

0: 不需要进行确认,速度最快。存在丢失数据的风险。
1: 仅需要Leader进行确认,不需要ISR进行确认。是一种效率和安全折中的方式。
all: 需要ISR中所有的Replica给予接收确认,速度最慢,安全性最高,但是由于ISR可能会缩小到仅包含一个Replica,所以设置参数为all并不能一定避免数据丢失。

生产消费最大消息

这里的消息大小是指的一批次发送的消息大小,不是一条消息大小

max.request.size:生产端能发送的最大消息大小 默认0.9M

message.max.bytes: Broker端 可以接受 Producer 发送过来的消息大小,默认值为0.9M

replica.fetch.max.bytes: broker端可复制的消息的最大字节数。这个值应该比message.max.bytes大,否则broker会接收此消息,但无法将此消息复制出去,从而造成数据丢失。默认: 1MB

fetch.max.bytes:消费者单次从 Broker 获取消息的最大字节数,默认50

以上三个参数设置大小要求:

max.request.size < message.max.bytes < fetch.max.bytes
 max.request.siz < replica.fetch.max.bytes 

topic属性配置,也有一个参数,叫 max.message.bytes,它只针对某个主题生效,可动态配置,可覆盖全局的 message.max.bytes,好处就是可以针对不同主题去设置 Broker 接收消息的大小,而且不用重启 Broker。

示例:

producer端:max.request.size=5242880(5M)broker:message.max.bytes=6291456(6M)consumer:fetch.max.bytes=7340032(7M)

producer: max.request.size

Kafka设计的初衷是迅速处理短小的消息,一般10K大小的消息吞吐性能最好(可参见LinkedIn的kafka性能测试)。但有时候,我们需要处理更大的消息,比如XML文档或JSON内容,一个消息差不多有10-100M,这种情况下,Kakfa应该如何处理?
针对这个问题,有以下几个建议:

最好的方法是不直接传送这些大的数据。如果有共享存储,如NAS, HDFS, S3等,可以把这些大的文件存放到共享存储,然后使用Kafka来传送文件的位置信息。

第二个方法是,将大的消息数据切片或切块,在生产端将数据切片为10K大小,使用分区主键确保一个大消息的所有部分会被发送到同一个kafka分区(这样每一部分的拆分顺序得以保留),如此以来,当消费端使用时会将这些部分重新还原为原始的消息。

第三,Kafka的生产端可以压缩消息,如果原始消息是XML,当通过压缩之后,消息可能会变得不那么大。在生产端的配置参数中使用compression.codec和commpressed.topics可以开启压缩功能,压缩算法可以使用GZip或Snappy。

不过如果上述方法都不是你需要的,而你最终还是希望传送大的消息,那么,则可以在kafka中设置下面一些参数:
broker 配置:

 ​    ​message.max.bytes (默认:1000000) – broker能接收消息的最大字节数,这个值应该比消费端的fetch.message.max.bytes更小才对,否则broker就会因为消费端无法使用这个消息而挂起。

​    ​log.segment.bytes (默认: 1GB) – kafka数据文件的大小,确保这个数值大于一个消息的长度。一般说来使用默认值即可(一般一个消息很难大于1G,因为这是一个消息系统,而不是文件系统)。

replica.fetch.max.bytes (默认: 1MB) – broker可复制的消息的最大字节数。这个值应该比message.max.bytes大,否则broker会接收此消息,但无法将此消息复制出去,从而造成数据丢失。

batch.size和max.request.size的关系

由于每次创建 ProducerBatch 都需要分配一个 batch.size 大小的内存空间,频繁创建和关闭会导致性能极大开销,所以 RecordAccumulator 内部有个 BufferPool,它实现了缓存的复用,只不过只针对 batch.size 大小的 BufferByte 进行复用,如果大于 batch.size 的 ProducerBatch,它并不会加入 BufferPool 中,也就不会复用。

之前有个疑问就是:假如 max.request.size 大于 batch.size,那么该条消息会不会分多个 batch 发送到 broker?

答案显然是不会,根据上述所说,如果一个 ProducerRecord 就已经超出了 batch.size 的大小,那么 ProducerBatch 仅包含一个 ProducerRecord,并且该 ProducerBatch 并不会加入到 BufferPool 中。

所以,在 Kafka Producer 调优过程中,根据业务需求,需要特别注意 batch.size 与 max.request.size 之间的大小值的设定,避免内存空间频繁地创建和关闭。

2.Consumer

  • num.consumer.fetchers:1
    #启动Consumer的个数,适当增加可以提高并发度。

  • fetch.min.bytes:1
    #每次Fetch Request至少要拿到多少字节的数据才可以返回。

#在Fetch Request获取的数据至少达到fetch.min.bytes之前,允许等待的最大时长。对应上面说到的Purgatory中请求的超时时间。

  • fetch.wait.max.ms:100

3. topic

1.分区

kafka读写的单位是partition,因此,将一个topic拆分为多个partition可以提高吞吐量。但是,这里有个前提,就是不同partition需 要位于不同的磁盘(可以在同一个机器)。如果多个partition位于同一个磁盘,那么意味着有多个进程同时对一个磁盘的多个文 件进行读写,使得操作系统会对磁盘读写进行频繁调度,也就是破坏了磁盘读写的连续性。

num.partitions=5

推荐配置:

默认partition数量1,如果topic在创建时没有指定partition数量,默认使用此值。Partition的数量选取也会直接影响到Kafka集群的吞吐性能,配置过小会影响消费性能,根据集群数量,建议不要为集群数量的整数倍。

4.副本同步

6.replica复制配置

num.replica.fetchers=3
replica.fetch.min.bytes=1
replica.fetch.max.bytes=5242880

推荐配置:

每个follow从leader拉取消息进行同步数据,follow同步性能由这几个参数决定,分别为:

拉取线程数(num.replica.fetchers):fetcher配置多可以提高follower的I/O并发度,单位时间内leader持有更多请求,相应负载会增大,需要根据机器硬件资源做权衡,建议适当调大;

最小字节数(replica.fetch.min.bytes):一般无需更改,默认值即可;

最大字节数(replica.fetch.max.bytes):默认为1MB,这个值太小,推荐5M,根据业务情况调整

最大等待时间(replica.fetch.wait.max.ms):follow拉取频率,频率过高,leader会积压大量无效请求情况,无法进行数据同步,导致cpu飙升。配置时谨慎使用,建议默认值,无需配置。

  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值