Kafka核心技术与实战 07 08 重要的集群参数配置

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

  • advertised.listeners - advertised.listeners主要是为外网访问用的。如果clients在内网环境访问Kafka不需要配置这个参数。

常见的玩法是:你的Kafka Broker机器上配置了双网卡,一块网卡用于内网访问(即我们常说的内网IP);另一个块用于外网访问。那么你可以配置listeners为内网IP,advertised.listeners为外网IP。

Topic 管理

  • auto.create.topics.enable:是否允许自动创建 Topic。不能自立为王

  • unclean.leader.election.enable:是否允许 Unclean Leader 选举。宁缺毋滥

  • auto.leader.rebalance.enable:是否允许定期进行 Leader 选举。江山不易改

数据留存方面

  • log.retention.{hour|minutes|ms}:这是个“三兄弟”,都是控制一条消息数据被保存多长时间。从优先级上来说 ms 设置最高、minutes 次之、hour 最低。数据寿命 hours=168

  • log.retention.bytes:这是指定 Broker 为消息保存的总磁盘容量大小。祖宅大小 -1 表示没限制

  • message.max.bytes:控制 Broker 能够接收的最大消息大小。祖宅大门宽度,默认 1000012=976KB

Topic 级别参数


保存消息

Topic 级别参数会覆盖全局 Broker 参数的值,而每个 Topic 都能设置自己的参数值,这就是所谓的 Topic 级别参数。

  • retention.ms:规定了该 Topic 消息被保存的时长。默认是 7 天,即该 Topic 只保存最近 7 天的消息。一旦设置了这个值,它会覆盖掉 Broker 端的全局参数值。

  • retention.bytes:规定了要为该 Topic 预留多大的磁盘空间。和全局参数作用相似,这个值通常在多租户的 Kafka 集群中会有用武之地。当前默认值是 -1,表示可以无限使用磁盘空间。

  • max.message.bytes:它决定了 Kafka Broker 能够正常接收该 Topic 的最大消息大小

JVM 参数


使用 Java 8

  • Heap Size,建议6GB,默认的 1GB 有点小,最好还是监控一下实时的堆大小,特别是GC之后的live data大小,通常将heapsize设置成其1.5~2倍就足以了

  • JAVA7 如果 Broker 所在机器的 CPU 资源非常充裕,建议使用 CMS 收集器。启用方法是指定-XX:+UseCurrentMarkSweepGC

  • JAVA7 否则,使用吞吐量收集器。开启方法是指定-XX:+UseParallelGC

  • Java 8 G1,在没有任何调优的情况下,G1 表现得要比 CMS 出色,主要体现在更少的 Full GC,需要调整的参数更少等,所以使用 G1 就好了。

操作系统参数


  • 文件描述符限制,ulimit -n 1000000,不设置的话后果很严重,比如你会经常看到“Too many open files”的错误。

  • 文件系统类型,文件系统类型的选择。这里所说的文件系统指的是如 ext3、ext4 或 XFS 这样的日志型文件系统。根据官网的测试报告,XFS 的性能要强于 ext4,所以生产环境最好还是使用 XFS。对了,最近有个 Kafka 使用 ZFS 的数据报告,貌似性能更加强劲,有条件的话不妨一试。

  • Swappiness,swap 的调优。网上很多文章都提到设置其为 0,将 swap 完全禁掉以防止 Kafka 进程使用 swap 空间。我个人反倒觉得还是不要设置成 0 比较好,我们可以设置成一个较小的值。为什么呢?因为一旦设置成 0,当物理内存耗尽时,操作系统会触发 OOM killer 这个组件,它会随机挑选一个进程然后 kill 掉,即根本不给用户任何的预警。但如果设置成一个比较小的值,当开始使用 swap 空间时,你至少能够观测到 Broker 性能开始出现急剧下降,从而给你进一步调优和诊断问题的时间。基于这个考虑,我个人建议将 swappniess 配置成一个接近 0 但不为 0 的值,比如 1。

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

常见问题


  • 把message.max.bytes设置地挺大,但是java生产者发送1M以上数据就失败,集群也重启过

producer、broker、consumer三端都需要调整

broker: message.max.bytes和replica.fetch.max.bytes

consumer:fetch.message.max.bytes

  • G1是jdk9中默认的,jdk8还是需要显式指定的

  • 修改 Topic 级 max.message.bytes,还要考虑以下两个吧?

还要修改 Broker的 replica.fetch.max.bytes 保证复制正常

消费还要修改配置 fetch.message.max.bytes

  • 页缓存属于磁盘缓存(Disk cache)的一种,主要是为了改善系统性能。重复访问磁盘上的磁盘块是常见的操作,把它们保存在内存中可以避免昂贵的磁盘IO操作。

既然叫页缓存,它是根据页(page)来组织的内存结构。每一页包含了很多磁盘上的块数据。Linux使用Radix树实现页缓存,主要是加速特定页的查找速度。另外一般使用LRU策略来淘汰过期页数据。总之它是一个完全由内核来管理的磁盘缓存,用户应用程序通常是无感知的。

无论应用还是数据库 甚至操作系统,为了防止直接操作磁盘,都会有缓存这一层

路径下有多个.log文件才有可能删除消息,如果只有一个.log文件是不会开启的,即使满足条件也不行。