kafka broker配置

kafka现在是所有队列组件里最常用的,虽然跟Rabbitmq这些相比还缺乏一些特性,但是它实在是成长的太快了,而且支持集群化,这个是最赞的,同时由于使用0拷贝,日志追加,所以它的磁盘效率非常高。

但是kafka的运维难度前期并不大,但是在后期主要的难点是在扩容,缩容阶段。主要是因为磁盘IO,网络IO的原因。导致了很多瓶颈点产生。

本文是读了「kafka权威指南」第二章的一个摘要总结。

broker整体配置

log.dirs

kafka是把所有消息都写入到磁盘,这个参数可以指定多个目录进行消息写入。而写入的原则是最少使用原则。
但是我们在实际使用中,不建议写多个,宁愿使用raid,LVM条带方式来扩展单目录的写入速度。

num.recovery.threads.per.data.dir

这个参数看名字是崩溃后恢复时候多少线程来处理每个消息目录。
但是在书里说明共有3种情况会使用这个

  • 服务器正常启动,用户打开每个分区的日志片段
  • 服务器崩溃重启,用于检查和截短每个分区的日志片段。
  • 服务器正常关闭,用于关闭日志片段。
    如果我们设置为8,那就是每个消息目录会产生8个线程进行处理。

auto.create.topics.enable

如果设置为true,那会在下列3种情况下自动创建topic

  • 当一个生产者开始往topic写入消息时
  • 当一个消费者开始从topic读取消息时
  • 当任意一个客户端向主题发送元数据请求时
    这个看各自情况吧,一般大型互联网公司应该都会设置为false,因为这样可以手动创建topic的时候指定很多topic的参数。特别是你的kafka里存放的topic类型区别很大的时候。

topic配置

0.8版本以及之前的版本允许topic的配置覆盖服务器的默认配置。而现在的版本需要使用管理工具来设置这些参数。

num.partitions

kafka topic的partition数量只能增加,不能减少。
一般来说partition数量肯定要大于broker数量。
至于如何确定分区的数量,作者列出了如下几条:

  • topic需要达到多少吞吐量? 每秒的写入量是多少。
  • 从单个分区读取数据的最大吞吐量是多少?这个大小肯定是小于整体topic的吞吐量的。
  • 估算生产者向单个分区写入数据的吞吐量,不过生产者的速度一般比消费者快得多,所以要给生产者多估算一些吞吐量。
  • 每个broker包含的分区个数、可用的磁盘空间和网络带宽。
  • 如果消息是按照不同的key来写入分区的,那么为已有的topic新增分区就会很困难。
  • 单个broker对分区个数是有限制的,因为分区越多,占用的内存越多,完成leader选举需要的时间也越长。

根据经验来说,把单个分区的大小限制在25GB以内可以得到比较理想的效果。

log.retention.ms

这里其实有3个参数都可以,一般我们使用log.retention.hours来设置,毕竟看着好认识。还有就是log.retention.minutes
当我们指定了多个参数,那就以最小的为准。但是我们千万不要这样干,对于后面排查起来就麻烦了。

log.retention.bytes

这个就是表示单个分区的保留大小。

上面这两个参数只要任意一个条件得到满足,消息就会被删除。

log.segment.bytes

这个是设置消息片段的大小,默认是1GB。只有当日志片段达到了指定的上线,当前日志片段就会被关闭,一个新的才会打开。
所以当你每个分区日志量小的情况下,一定要设置下这个参数。
比如一个分区每天只有100M的消息,log.segment.bytes是默认设置,那么需要10天才能写满一个日志片段。而log.retention.ms设置为604800000(也就是一周),那么这个日志片段最多需要17天才会过期。
因为要等到日志片段里的最后一个消息过期才能被删除。

log.segment.ms

这个默认是没有设置的。
主要是基于时间来设置的话,一个topic的多个分区在一个服务器上会同时达到话,这样导致磁盘性能下降。

message.max.bytes

限制单个消息的大小。默认是1000000,也就是1MB。这个大小是压缩后的消息大小,解压开来(broker的CPU主要是干这个了)会远远超过这个大小。
这个值一定要跟客户端协同好。