kafka-broker配置
常规配置
常规配置指的是一些在使用单机安装时可以直接使用的默认值,这可以满足大部分的开发需求。但是在部署到其他环境时,需要格外小心,这些参数是单个服务器最基本的配置,他们中的大部分需要经过修改之后才可以用在生产环境里
- broker.id
每个broker都需要有一个标识符,使用broker.id来表示。默认值为0,在部署到生产环境时,这个broker.id在集群中需要是唯一的,一般可以使用host的名字缩写来代替。 - port
kafka启动的时候监听的端口,默认是9092。可以任意指派,但是不要小于1024,否则需要管理员权限,不建议。 - zookeeper.connect
kafka的通信是基于zookeeper的,kafka的元数据保存在zookeeper中。connect可以指定一个zookeeper列表,格式为:hostname:port/path。这里的path使用默认值chroot比较好,官网提示使用chroot是最佳实践。可以使用zookeeper列表来保证zookeeper和kafka之间的高可用。 - log.dirs
kafka把所有的消息都保存在磁盘上,log.dirs就是指定保存在磁盘上的哪个目录。如果有多个dir,kafka会根据“最少使用原则“,就是哪个目录下面子目录最少就在哪个目录下面新增分区。 - num.recovery.threads.per.data.dir
kafka会在如下三种情况下启用可配置的线程池来处理日志片段:
- 服务器正常启动,需要打开每个分区的日志片段
- 服务器崩溃后重启,需要检查和截短每个分区的日志片段
- 服务器正常关闭,需要关闭日志片段
默认情况下,每个日志目录只是用一个线程,因为这些线程只是在服务器启动和关闭的时候会用到,所以完全可以设置大量的线程来加快这一过程。
这个参数的意思是每个分区路径开几个线程。比如log.dir有三个路径,这个参数配置了8,那么恢复那三个目录,就需要一共24个线程。
- auto.create.topics.enable
默认值是true,表示自动创建主题。默认情况下,kafka会在下面几种情况下创建主题:
- 生产者开始写入消息
- 消费者开始读取消息
- 客户端向主题发送元数据
很多时候,这些行为都是非预期的。而且根据kafka协议,如果一个主题不先被创建,根本无法知道它是否已经存在。
如果想要显式的创建主题,而不是自动创建,可以设置该值为false。
主题的默认配置
除了上面的kafka的常规配置外。针对创建出来的主题,也是需要进行配置的。可以通过管理工具为每个主题单独配置一些参数,实现定制化或者优化,比如:分区个数、数据保留策略。
服务器提供的默认配置可以作为基准,默认值适用于大部分使用场景。
- num.partitions
指定新创建的主题将包含多少个分区。自动创建主题的时候,该值就是新创建主题的分区数。
kafka通过分区来实现对主题的横向扩展,所以当有新的broker进入同一个topic的broker集群的时候,可以通过分区个数来实现集群的负载均衡。
设置该值的几个依据:
- 主题需要多大的吞吐量?例如:希望每秒钟写入100kb还是1gb?
- 从单个分区读取数据的最大吞吐量是多少?每个分区一般都会有一个消费者,如果是消费者是写数据库操作,那么一般速度不会超过50mb每秒,那么也就代表从一个分区读取数据的最大吞吐量不需要超过50mb每秒
- 可以通过类似于上面的方法来对生产者的写入吞吐量来进行估算。不过一般生产者会比消费者的吞吐量大,因为很多数据是不需要处理或者是很多系统的并发结果
- 每个broker包含的分区个数,可用的磁盘空间、网络带宽
- 如果消息是按照不同的键来写入分区的,那么为已有的主题新建分区就会很困难,因为这意味着需要修改代码才能让消息进入新增的分区
- 单个broker对分区的数量大小是有限制的,因为分区越多,占用的内存越多,完成首领选举的时间也越长
下面是一个计算例子:
如果估算出来读取和写入主题的速度大概是每秒1gb,每个消费者每秒可以处理50mb数据,那么可以算出来需要至少20个分区。这样就可以让20个消费者同时读取,从而达到每秒钟1GB的吞吐量。ps:书上说:如果不知道这些信息,那么根据经验,把分区的大小限制在25GB以内可以得到比较理想的效果。
- log.retention.ms
kafka根据时间来决定数据将会被保留多久。默认使用log.retention.hours参数来配置时间,默认值为168小时,也就是一周。除此以外,还有其他两个参数log.retenion.minutes和log.retention.ms
坑:根据时间保留数据是通过检查磁盘上日志片段文件的最后修改时间来实现的。一般来说,最后修改时间就是日志片段的关闭时间,也就是文件里最后一个消息的时间戳。如果使用管理工具在服务器间移动分区,最后修改时间就不准确了。时间误差可能导致这些分区过多的保留数据。
- log.retention.bytes
除了使用时间限制保留的消息之外,还可以通过消息的字节数来判断消息是否过期。它的值通过参数retention.bytes来指定,作用在每一个分区上。也就是说,如果有一个包含8个分区的主题,并且该参数被设置为1GB,那么这个主题最多可以保留8GB的数据。所以当主题的分区个数增加时,整个主题可以保留的数据也随之增加。
这个参数可以和上面的时间参数搭配使用,那个提前到达,都会直接删除到达删除条件的消息。
- log.segment.bytes
以上的设置都作用在日志片段上,而不是作用在单个消息上。当消息到达broker时,他们被追加到分区的当前日志片段上。当日志片段大小达到log.segment.bytes时,当前日志片段就会关闭,等待过期,并会重新开启一个日志片段,这个参数的值越小,就会越频繁的关闭和分配新文件,从而降低磁盘写入的整体效率。
如果主题的消息量不大,那么如何调整这个参数的大小就变得尤为重要。例如,如果一个主题每天只接受100mb的消息,而log.segment.bytes使用默认设置,那么需要10天时间才能填满一个日志片段。因为在日志片段被关闭之前消息是不会过期的,所以如果log.retention.ms被设置为一周,那么日志片段最多需要在17天才会过期。而不是一周的时间,因为根据配置的过期时间,还需要在保留7天时间。
ps:使用时间戳获取偏移量。在使用时间戳获取日志偏移量时,kafka会检查分区里最后修改时间大于指定时间戳的日志片段(已经被关闭的),该日志片段的前一个文件的最后修改时间小于指定时间戳,然后,kafka返回该日志片段开头的偏移量。对于使用时间戳获取偏移量的操作来说,日志片段越小,结果越准确。
- log.segment.ms
该参数指定了日志片段多长时间被关闭。和上面的一样,两者同时存在的情况下,容量和时间哪个先到达上线,日志片段就会被关闭。
ps:对于那些长时间达不到日志上限的,可以通过这个参数来关闭文件分区。如果打开文件过多,会导致磁盘性能受到影响。
- message.max.bytes
broker通过设置该参数来限制单个消息的大小,默认值是1mb。如果生产者尝试发送的消息大于该值,那么消息不仅不会被接收,还会受到一个broker返回的错误信息。这个大小是消息压缩后的大小。
这个值对参数有显著的影响。值越大,那么负责处理网络连接和请求的线程就需要花越多的时间来处理这些请求。他还会增加磁盘写入块的大小,从而影响IO吞吐量。
ps:消费者客户端设置的fetch.message.max.bytes必须与服务器端设置的消息大小进行协调。如果这个值比message.max.bytes小,那么消费者就无法读取比较大的消息,导致出现消费者被阻塞的情况。在为集群里的broker配置replica.fetch.max.bytes参数时,也遵循同样的原则。
起风了,努力生存