目录
二. 文件系统选择(Filesystem Selection)
2.1. 常规文件系统说明(General Filesystem Notes)
2.4. 更换 KRaft 控制器磁盘(Replace KRaft Controller Disk)
一. 前言
磁盘容量是一个值得讨论的话题,需要多大的磁盘容量取决于需要保留的消息数量。如果服务器每天会收到 1TB 消息,并且保留7天,那么就需要 7TB 的存储空间,而且还要为其他文件提供至少10%的额外空间。除此之外,还需要提供缓冲区,用于应付消息流量的增长和波动。
在决定扩展 Kafka 集群规模时,存储容量是一个需要考虑的因素。通过让 Topic 拥有多个分区,集群的总流量可以被均衡到整个集群,而且如果单个 Broker 无法支撑全部容量,可以让其他Broker 提供可用的容量。存储容量的选择同时受到集群复制策略的影响。
二. 文件系统选择(Filesystem Selection)
Kafka 使用磁盘上的常规文件,因此它对特定的文件系统没有硬依赖。然而,使用率最高的两个文件系统是 EXT4 和 XFS。从历史上看,EXT4 使用得更多,但最近对 XFS 文件系统的改进表明,它在不影响稳定性的情况下,对 Kafka 的工作负载具有更好的性能特征。
使用各种文件系统创建和装载选项,在具有大量消息负载的集群上执行了比较测试。Kafka 中被监控的主要度量是“Request Local Time”,表示追加操作所花费的时间。XFS 带来了更好的本地时间(160ms 和 250ms+ 是 EXT4 的最佳配置,),以及更低的平均等待时间。XFS 性能也显示出磁盘性能的可变性较小。
2.1. 常规文件系统说明(General Filesystem Notes)
对于 Linux 系统上用于数据目录的任何文件系统,建议在装载时使用以下选项:
- noatime:此选项禁止在读取文件时更新文件的 atime(上次访问时间)属性。这可以消除大量的文件系统写入,尤其是在引导消费者的情况下。Kafka 根本不依赖 atime 属性,因此禁用它是安全的。
2.2. XFS 说明(XFS Notes)
XFS 文件系统具有大量的自动调优功能,因此无论是在文件系统创建时还是在装载时,都不需要对默认设置进行任何更改。唯一值得考虑的调整参数是:
- largeio:这会影响 stat 调用报告的首选 I/O 大小。虽然这可以在较大的磁盘写入上实现更高的性能,但在实践中,它对性能的影响很小或没有影响。
- nobarrier:对于具有电池备份缓存的底层设备,此选项可以通过禁用定期写入刷新来提供更高的性能。但是,如果底层设备表现良好,它将向文件系统报告不需要刷新,并且此选项将无效。
2.3. EXT4 说明(EXT4 Notes)
EXT4 是 Kafka 数据目录一个有用的文件系统选择,但要想获得最大的性能,需要调整几个装载选项。此外,这些选项在故障情况下通常是不安全的,并将导致更多的数据丢失和损坏。对于单个Broker 故障,这不是什么大问题,因为可以擦除磁盘并从集群中重建副本。在多次故障的情况下,如停电,这可能意味着底层文件系统(以及数据)损坏,不容易恢复。可以调整以下选项:
- data=writeback:Ext4 默认为 data=ordered,这会对某些写入进行强排序。Kafka 不需要这种排序,因为它在所有未刷新的日志上进行非常偏执的数据恢复。此设置删除了排序约束,似乎可以显著减少延迟。
- 禁用日志记录:日志记录是一种折衷:它使服务器崩溃后的重新启动更快,但它引入了大量额外的锁定,从而增加了写入性能的差异。那些不关心重新启动时间并希望减少写入延迟峰值的主要来源的人可以完全关闭日志记录。
- commit=num_secs:这将调整 ext4 提交到其元数据日志的频率。将其设置为较低的值可减少崩溃期间未刷新数据的丢失。将其设置为更高的值将提高吞吐量。
- nobh:当使用 data=writeback 模式时,此设置控制额外的排序保证。这对于 Kafka 来说应该是安全的,因为我们不依赖于写顺序,并提高了吞吐量和延迟。
- delalloc:延迟分配意味着文件系统在发生物理写入之前避免分配任何块。这允许 ext4 分配较大的数据块而不是较小的页面,并有助于确保数据按顺序写入。此功能非常适合吞吐量。它似乎确实涉及到文件系统中的一些锁定,这增加了一些延迟差异。
2.4. 更换 KRaft 控制器磁盘(Replace KRaft Controller Disk)
当 Kafka 被配置为使用 KRaft 时,控制器将集群元数据存储在 metadata.log.dir 中指定的目录中,或者如果未配置 metadata.log.dir,则存储在第一个日志目录中。有关详细信息,请参阅metadata.log.dir 的文档。
如果集群元数据目录中的数据由于硬件故障或需要更换硬件而丢失,则在配置新的控制器节点时应小心。在大多数控制器具有所有提交的数据之前,不应格式化和启动新的控制器节点。要确定大多数控制器是否具有提交的数据,请运行 kafka-metadata-quorum.sh 工具来描述复制状态:
> bin/kafka-metadata-quorum.sh --bootstrap-server broker_host:port describe --replication
NodeId LogEndOffset Lag LastFetchTimestamp LastCaughtUpTimestamp Status
1 25806 0 1662500992757 1662500992757 Leader
... ... ... ... ... ...
检查并等待,直到大多数控制器的滞后很小。如果 Leader 的末端偏移量没有增加,则可以等到多数情况下滞后为0;否则,您可以选择最新的 Leader 端偏移量,并等待所有副本都到达它。检查并等待,直到大多数控制器的 LastFetchTimestamp 和 LastCaughUpTimestamp 彼此接近。此时,格式化控制器的元数据日志目录更安全。这可以通过运行 kafka-storage.sh 命令来完成。
> bin/kafka-storage.sh format --cluster-id uuid --config server_properties
上面的 bin/kafka-storage.sh 格式命令可能会失败,并显示一条消息,如 Log directory... 已格式化。当使用组合模式时,只有元数据日志目录丢失,而其他目录没有丢失,就会发生这种情况。在这种情况下,也只有在这种情况中,才能使用 --ignore-formatted 选项运行 kafka-storage.sh 格式 化命令。
格式化日志目录后启动 KRaft 控制器。
> /bin/kafka-server-start.sh server_properties