Kafka最重要的集群参数配置

Posted by JustDoDT on September 23, 2019

概述

本博客主要从 Kafka Broker端,Topic端,JVM 端参数,操作系统级别参数说起。目前 Kafka Broker 端提供了近200个参数,这其中绝大部分参数都不用关心。

Broker 端参数

Broker 是需要配置存储信息的,即 Broker 使用哪些磁盘。那么针对存储信息的重要参数有以下几个:

  • log.dirs 这个是非常重要的参数,指定了 Broker 需要使用的若干个文件目录路径。这个参数没有默认值,需要自己指定
  • log.dir 注意这是 dir ,结尾没有 s ,说明她只能表示单个路径,她是补充上一个参数用的。

怎么设置这2个参数呢?

只要设置 log.dirs 就行了,不要设置 log.dir 。而且更重要的是,在生产环境中一定要为 log.dirs 设置多个路径,具体格式是一个 CSV 格式,比如/home/kafka1,/home/kafka2,/home/kafka3。如果有条件最好保证这些目录挂载到不同的物理磁盘上。

为什么要这样做?

  • 提升读写性能 比起单块磁盘,多块磁盘同时读写数据有更高的吞吐量
  • 能够实现故障转移 即 Failover,这是 Kafka 1.1 版本新引入的强大功能。要知道在以前,只要 Kafka Broker 使用的任何一块磁盘挂掉了,整个 Broker 进程都会关闭。但是自 1. 1 开始,这种情况被修正了,坏掉的磁盘上的数据会自动转移到其他正常的磁盘上,而且 Broker 还能正常工作。如果没有 Failover 的话,我们只能依靠 RAID 来提供保障。

ZooKeeper 端的参数

  • zookeeper.connect 这也是一个CSV格式的参数,比如可以指定她的值为 zk1:2181 ,zk2:2181,zk3:2181
  • 如果让多个 Kafka 集群使用同一套 ZooKeeper 集群,那么这个参数应该怎么设置呢?
  • 假设有2套集群,那么2套集群的zookeeper.connect 参数可以这样指定:zk1:2181,zk2:2181,zk3:2181/kafka1和zk1:2181,zk2:2181,zk3:2181/kafka2

Topic 端的参数

  • auto.create.topics.enable 是否自动创建 Topic

这个参数建议设置为 false ,即不允许自动创建 Topic

  • unclean.leader.election.enable 是否允许 Unclean Leader 选举

这个参数建议设置为 false,坚决不让落后太多的副本竞选 Leader 。这样做的后果是这个分区就不可用了,因为没有 Leader。如果设置为 True ,那么 Kafka 允许你从那些 “跑得慢” 的副本中选一个出来当 Leader 。这样做的后果是数据可能丢失,因为这些副本保存的数据本来就不全。

  • auto.leader.rebalance.enable 是否允许定期进行 Leader 选举

这个参数建议设置为 false。如果将她设置为 true 表示允许 Kafka 定期的对一些 Topic 分区进行 Leader 重选举,当然这个重选举不是无脑进行的,她满足一定的条件才会发生。这个参数是换 Leader ,不是选 Leader。比如 Leader A 一直表现得很好,但若此参数设置为 true,那么可能一段时间后 Leader A 就要强行卸任为 Leader B。由于换一次的 Leader 代价很高的,原本向 A 发送请求的所有客户端都要切换为向 B 发送请求,而且这种换 Leader 本质上没有任何性能收益。

数据存储方面的参数

  • log.retention.{hour|minutes|ms}

这是个“三兄弟”,都是控制一条消息数据被保存多长时间。从优先级上来说 ms 设置最高,minutes 次之,hour 最低,但是通常设置为 hour 级别,比如 log.retention.hour=168表示默认保存7天的数据,自动删除7天前的数据。

  • log.retention.bytes 这是指定 Broker 为消息保存的总磁盘容量大小

这个值的默认值为-1,表明你想在这台 Broker 上保存多少数据都可以

  • message.max.bytes 控制 Broker 能够接收的最大消息大小

此参数默认值是 1000012 太少了,还不到 1MB。实际场景中突破 1MB 的消息太多了,因此尽量把此参数设置大一些。

Broker 端参数

  • listeners 监听器,其实就是告诉外部连接者要通过什么协议访问指定主机名和端口开放的 Kafka 服务。

  • advertised.listeners 和 listeners 相比多了个 advertised 。Advertised 的含义表示宣称的,公布的,就是说这组监听器是 Broker 用于对外发布的。

    什么是监听器?

    从构成上,监听器是由若干个逗号分隔的三元组,每个三元组的格式为<协议名称,主机名,端口号>。这里的协议名称可能是标准的名字,比如PLAINTEXT 表示明文传输、SSL 表示使用 SSL 或 TSL 加密传输等;也可能是你自己定义的协议名字,比如 CONTROLLER://localhost:9092

JVM 端参数

  • KAFKA_HEAP_OPTS 指定堆大小,建议此参数设置为 6GB

如果用默认的 1GB 有点小,毕竟 Kafka Broker 在与客户端进行交互时会在 JVM 堆上创建大量的 ByteBuffer 实例,Heap Size 不能太小。

  • export KAFKA_HEAP_OPTS=--Xms6g --Xmx6g
  • KAFKA_JVM_PERFORMANCE_OPTS 指定 GC 参数

JVM 端还有一个重要的参数就说垃圾回收器的设置,也就是平时我们常说的 GC 设置。如果你依然使用 Java 7,那么可以根据如下的法则选择合适的垃圾回收器。

如果 Broker 所在机器的 CPU 资源非常充裕,建议使用 CMS 收集器。启用方法是指定 -XX:+UseCurrentMarkSweepGC;否则使用吞吐量收集器,开启方法指定 -XX:+UseParallelGC;如果使用的是 Java 8 ,那么默认的 G1 收集器就行。在没有任何调优的情况下,G1 表现要比 CMS 出色,主要体现在更少的 Full GC,需要调整的参数更少等,所以使用 G1就好了。

  • export KAFKA_JVM_PERFORMANCE_OPTS= -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:bin/kafka-server-start.sh config/server.properties

操作系统的参数

  • 文件描述符限制

通常情况下需要调整此参数的值,如果不调整的话会出现 “Too many open files” 的错误。使用ulimit -n 1000000

  • 文件系统类型

这里的文件系统指的是 ext3、ext4 或 XFS 这样的日志类型文件系统。根据官网的测试报告,XFS 的性能要强于 ext4,生产环境最好用 XFS。

  • Swappiness

swap 调优,建议设置为一个很小的值,比如0到1之间的数字。因为一旦设置为0,当物理内存耗尽的时候,操作系统就会触发 OOM killer 这个组件,她会随机挑战一个进程然后 kill 掉,即根本不给用户任何的预警。但如果设置为一个较小的值,当开始使用 swap 空间时,你至少可以观测到 Broker 性能开始出现急剧下降,从而给你进一步调优和诊断问题的时间。

  • 提交时间

提交时间也可以理解为 Flush 落盘时间。向 Kafka 发送数据并不是真要等数据被写入磁盘才会认为成功,而是只要数据被写入到操作系统的页缓存(Page Cache)上就可以了,随后操作系统根据 LRU 算法会定期将页缓存上的 脏数据 刷到磁盘上。这个定期就是由提交时间来确定的,默认是 5 秒。一般情况下我们会认为这个时间太频繁了,可以适当地增加提交间隔来降低物理磁盘的写操作。如果在页缓存中的数据在写入磁盘前机器宕机了,那岂不是数据就丢失了。的确,这种情况数据确实丢失了,但鉴于 Kafka 在软件层面已经提供了多副本的冗余机制,因此这里稍微调整提交间隔去换取性能还是一个合理的做法。