跳到主要内容

kafka生产者性能调优

· 阅读需 8 分钟
勾玉aniki
博客作者,py&go后端开发,爱好动漫。邮箱tangssst@qq.com

介绍

搞消息队列的应该没人不知道kafka,就算你用别的队列比如rabbit或者rocket,也应该听过。kafka的一个显著特点就是高性能,因此被广泛用于日志采集上,我在研发环境做过大量的测试,研究过几乎全部的生产者参数,总结了一些生产者性能的调参方法。

这里只讨论生产者调优,你也可以加大集群节点,加高集群网络带宽来提升吞吐,不过不在本次讨论范围内。

以下是我抽取的和调优有关的重要参数,并附带了个人总结,自己看吧

参数

  • max.request.size建议调大(不能大于broker的message.max.bytes)

    • 生产者发送的 请求大小,可以指能发送的 单个消息的最大值,也可以指单个请求里 所有消息的总大小。默认1048576(1mb)。
    • 限制单条消息大小、限制发送请求大小。
    • 注意生产者该配置不能大于broker的 message.max.bytes配置,也不能大于消费者的 max.partition.fetch.bytes 配置,否则消费者无法拉取!
  • buffer.memory建议调大(例如100*000000)

    • 生产者实例整体使用的内存缓冲区字节数,默认33mb(33554432)。如果缓冲区到达的速度比发送的速度快, Producer 就会阻塞,如果阻塞的时间超过 max.block.ms 配置的时长,则会抛出TimeoutException。
  • batch.size建议调大(例如524288)

    • producer会把发往同一分区的多条消息封装进一个batch中,当batch满了后,producer才会把消息发送出去。但是也不一定等到满了,这和另外一个参数linger.ms有关。默认16kb(16384)

    • 大量的小batch,会给网络IO带来的极大的压力。

    • 过小会降低吞吐,过大会占用内存,可以调到524288(512kb),但不能大于 max.request.size。

  • linger.ms建议调大(例如100ms)

    • 要是一个Batch迟迟无法凑满, 生产者将等待给定的延迟时间,以便将在到达的其他记录合并到本批次中;

    • 优先级低于 batch.size,满足batch.size 后会忽略 linger.ms;默认为0(不等待);

    • 追求低延迟,默认为0即可, 追求吞吐,降低网络io次数,调大该值,可以修改为100ms,

  • acks:这个参数用来指定分区中必须要有多少个副本收到这条消息,之后生产者才会认为这条消息是成功写入的

    建议为1(不保证绝对不丢失的话)ack只是表示写入到page cache中

    • 0 :producer 不会等待服务器的反馈。该消息会被立刻添加到 socket buffer 中并认为已经发送完成。在这种情况下,服务器是否收到请求是没法保证的,并且参数 retries 也不会生效(因为客户端无法获得失败信息)。每个记录返回的 offset 总是被设置为-1。
    • 1 :leader 节点会将记录写入本地日志,并且在所有 follower 节点反馈之前就先确认成功。如果消息写入leader副本并返回成功响应给生产者,且在被其他follower副本拉取之前leader副本崩溃,那么此时消息还是会丢失,因为新选举的leader副本中并没有这条对应的消息。
    • all或-1 :leader 节点会等待所有同步中的副本确认之后再确认这条记录是否发送完成。只要至少有一个同步副本存在,记录就不会丢失。这种方式是对请求传递的最有效保证。acks=-1与acks=all是等效的。并不意味着消息就一定可靠,因为ISR中可能只有leader副本,这样就退化成了acks=1的情况。要获得更高的消息可靠性需要配合 min.insync.replicas 等参数
  • compression.type建议为gzip

    • Producer 生成数据时可使用的压缩类型。默认值是none(即不压缩)。可配置的压缩类型包括:none, gzip, snappy, 或者 lz4(压缩率最高),推荐gizp。

    • 开启压缩可以极大调高发送性能!

  • retries建议配置(不要求顺序的话)(配合retry.backoff.ms)

    • 重试次数,默认0。若设置大于0的值,则客户端会将发送失败的记录重新发送;
    • 元数据信息失效、副本数量不足、超时、位移越界或未知分区等会触发重试
    • max.in.flight.requests.per.connection >1时,记录的顺序可能会被改变,例如先a后b消息,但是a消息失败重试,但b已经发出去了,那么顺序就乱了。
    • kafka支持精确一次,因此重试不会导致重复发送,
  • retry.backoff.ms:重试间隔,建议配置。估算好异常恢复的时间,单位ms。默认100ms

  • max.in.flight.requests.per.connection建议配置

    • 默认5。设置客户端在单个连接上能够发送的未确认请求的最大数量,默认为5,超过此数量会造成阻塞。
    • 设置大的值可以提高吞吐量但会增加内存使用,但当设置值大于1而且发送失败时,如果启用了重试配置,有可能会改变消息的顺序。设置为1时,即使重新发送消息,也可以保证发送的顺序和写入的顺序一致。

总结

  • 最重要的是开启压缩,可以极大增加吞吐。你可能会担心消费者没有解压能力,其实可以选择gzip压缩算法,大部分生产者、消费者客户端都有处理gzip的能力。
  • 其次是acks,这个不说了,一般设置成1就好,处于性能和可靠性的中间,你要追求极致性能可以改为0,会降低可靠性。
  • 然后batch.size调大,liner.ms调大,这些本质上是增加生产延迟,攒一大批数据后一次发送,可以降低网络io次数,如果你的网络延迟比较高,这个会比较重要。
  • 除了上面的调参外,也可以增加生产者实例个数,增加topic的分区数,这些也能非常大程度提高吞吐。

其他的就是一些可靠性的配置,自己权衡了。