最佳实践 - Amazon Managed Streaming for Apache Kafka
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

最佳实践

本主题概述使用 Amazon MSK 时应遵循的一些最佳实践。

调整集群的大小:每个代理的分区数量

下表显示了建议的每个代理的分区数量(包括领导副本和跟随者副本)。

代理类型 建议的每个代理的分区数量(包括领导副本和跟随者副本)。
kafka.t3.small 300
kafka.m5.largekafka.m5.xlarge 1000
kafka.m5.2xlarge 2000
kafka.m5.4xlargekafka.m5.8xlargekafka.m5.12xlargekafka.m5.16xlargekafka.m5.24xlarge 4000
kafka.m7g.largekafka.m7g.xlarge 1000
kafka.m7g.2xlarge 2000
kafka.m7g.4xlargekafka.m7g.8xlargekafka.m7g.12xlarge、或 kafka.m7g.16xlarge 4000

如果每个代理的分区数量超过建议值,并且您的集群过载,则可能会阻止您执行以下操作:

  • 更新集群配置

  • 更新集群的 Apache Kafka 版本

  • 将集群更新为较小的代理类型

  • 将 Amazon Secrets Manager 密钥与具有 SASL/SCRAM 身份验证的集群相关联

大量分区还可能导致 Prometheus 抓取 CloudWatch 和抓取时缺少 Kafka 指标。

有关选择分区数的指导,请参阅 Apache Kafka 支持每个集群 20 万个分区。我们还建议您执行自己的测试,以确定适合您代理的类型。有关不同代理类型的更多信息,请参阅代理类型

调整集群的大小:每个集群的代理数量

要确定 MSK 集群的适当代理数量并了解成本,请参阅 MSK Sizing and Pricing 电子表格。此电子表格提供了与类似的、自我管理的基于 EC2 的 Apache Kafka 集群相比,估计的 MSK 集群大小和相关 Amazon MSK 成本。有关电子表格中的输入参数的更多信息,请将鼠标指针悬停在参数描述的上方。此表提供的是保守估计值,为新集群提供了一个起点。集群的性能、大小和成本取决于您的用例,建议您通过实际测试进行验证。

要了解底层基础架构如何影响 Apache Kafka 性能,请参阅大数据博客中的调整您的 Apache Kafka 集群规模以优化性能和成本的最佳实践。 Amazon 这篇博客文章提供了有关如何调整集群大小以满足吞吐量、可用性和延迟要求的信息。它还提供了诸如何时应纵向扩展,何时应横向扩展等问题的答案,以及有关如何持续验证生产集群大小的指导。

优化 m5.4xl、m7g.4xl 或更大实例的集群吞吐量

使用 m5.4xl、m7g.4xl 或更大的实例时,您可以通过调整 num.io.threads 和 num.network.threads 配置来优化集群吞吐量。

Num.io.threads 是代理用于处理请求的线程数。添加更多线程(不超过实例类型支持的 CPU 核心数量)有助于提高集群的吞吐量。

Num.network.threads 是代理用于接收所有传入请求和返回响应的线程数。网络线程将传入请求放在请求队列中,以供 io.threads 处理。将 num.network.threads 设置为实例类型支持的 CPU 核心数量的一半,即可充分使用新的实例类型。

重要

如果不先增加 num.io.threads,请勿增加 num.network.threads,因为这可能会导致与队列饱和相关的拥塞。

推荐设置
实例类型 num.io.threads 的推荐值 num.network.threads 的推荐值

m5.4xl

16

8

m5.8xl

32

16

m5.12xl

48

24

m5.16xl

64

32

m5.24xl

96

48

m7g.4xlarge

16

8

m7g.8xlarge

32

16

m7g.12xlarge

48

24

m7g.16xlarge

64

32

使用最新的 Kafka AdminClient 来避免主题 ID 不匹配问题

当您使用低于 2.8.0 的 Kafka 版本并带有标志--zookeeper为使用 Kafka AdminClient 版本 2.8.0 或更高版本的集群增加或重新分配主题分区时,主题的 ID 会丢失(错误:与分区的主题 ID 不匹配)。请注意,--zookeeper 标志在 Kafka 2.5 中已弃用,并从 Kafka 3.0 开始删除。请参阅 Upgrading to 2.5.0 from any version 0.8.x through 2.4.x

为防止主题 ID 不匹配,请使用 Kafka 客户端版本 2.8.0 或更高版本进行 Kafka 管理员操作。或者,2.5 及更高版本的客户端可以使用 --bootstrap-servers 标志代替 --zookeeper 标志。

构建高度可用的集群

使用以下建议,以便在更新期间(例如更新代理类型或 Apache Kafka 版本时)或 Amazon MSK 更换代理时,保持 MSK 集群的高可用性。

  • 设置三可用区集群。

  • 确保复制因子(RF)至少为 3。请注意,在滚动更新期间,RF 为 1 可能会导致分区离线;而 RF 为 2 可能会导致数据丢失。

  • 将最小同步副本数 (minISR) 设置为最多 RF - 1。minISR 等于 RF 可能会阻止在滚动更新期间生成到集群。当一个副本处于脱机状态时,minISR 为 2 使三向复制主题可用。

  • 确保客户端连接字符串至少包含来自每个可用区的一个代理。在客户端的连接字符串中具有多个代理,则可在特定代理脱机进行更新时实现失效转移。有关如何获取具有多个代理的连接字符串的信息,请参阅获取 Amazon MSK 集群的引导代理

监控 CPU 使用率

Amazon MSK 强烈建议您将代理的总 CPU 使用率(定义为 CPU User + CPU System)保持在 60% 以下。当集群的总 CPU 可用率至少达到 40% 时,Apache Kafka 可以在必要时在集群中的代理之间重新分配 CPU 负载。例如,当 Amazon MSK 检测到代理故障并从中恢复时,就有必要这样做;在这种情况下,Amazon MSK 会执行自动维护,如进行修补。另一个例子是当用户请求更改代理类型或升级版本时;在这两种情况下,Amazon MSK 会部署滚动工作流程,一次让一个代理离线。当具有领导分区的代理离线时,Apache Kafka 会重新分配分区领导权,以将工作重新分配给集群中的其他代理。通过遵循此最佳实践,您可以确保集群中有足够的 CPU 余量来容忍此类操作事件。

您可以使用 Amazon CloudWatch 指标数学来创建复合指标,即CPU User + CPU System。设置当复合指标达到 60% 的平均 CPU 利用率时触发的警报。触发此警报时,请使用以下选项之一扩展集群:

  • 选项 1(推荐):将您的代理类型更新为下一个较大的类型。例如,如果当前类型为 kafka.m5.large,则更新集群以使用 kafka.m5.xlarge。请记住,当您更新集群中的代理类型时,Amazon MSK 会以滚动方式使代理离线,并暂时将分区领导权重新分配给其他代理。每个代理的规模更新通常需要 10-15 分钟。

  • 选项 2:如果主题中的所有消息都是从使用轮询写入的生成器那里摄取的(换句话说,消息没有密钥,顺序对使用器来说并不重要),请通过添加代理来扩展集群。还要向吞吐量最高的现有主题添加分区。接下来,使用 kafka-topics.sh --describe 来确保将新添加的分区分配给新代理。与前一个选项相比,此选项的主要优点是您可以更精细地管理资源和成本。此外,如果 CPU 负载明显超过 60%,则可使用此选项,因为这种形式的扩展通常不会导致现有代理的负载增加。

  • 选项 3:通过添加代理来扩展集群,然后使用名为 kafka-reassign-partitions.sh 的分区重新分配工具来重新分配现有分区。但是,如果您使用此选项,则在重新分配分区后,集群将需要花费资源将数据从一个代理复制到另一个代理。与前两个选项相比,这可能会在一开始显著增加集群的负载。因此,Amazon MSK 不建议在 CPU 利用率高于 70% 时使用此选项,因为复制会导致额外的 CPU 负载和网络流量。仅当前两个选项不可行时,Amazon MSK 才建议使用此选项。

其他建议:

  • 作为负载分配的代理,监控每个代理的 CPU 总利用率。如果代理的 CPU 利用率一直不均衡,则可能表明集群内的负载分布不均。Amazon MSK 建议使用 Cruise Control 通过分区分配持续管理负载分配。

  • 监控生成和使用延迟。生成和使用延迟会随着 CPU 利用率呈线性增加。

  • JMX 抓取间隔:如果您使用 Prometheus 功能启用开源监控系统,则建议您为 Prometheus 主机配置 (prometheus.yml) 使用 60 秒或更长的抓取间隔 (scrape_interval: 60s)。降低抓取间隔可能会导致集群上的 CPU 使用率过高。

监控磁盘空间

为避免存储消息的磁盘空间不足,请创建KafkaDataLogsDiskUsed监控指标的 CloudWatch 警报。当此指标的值达到或超过 85% 时,请执行下列一项或多项操作:

  • 使用 自动扩缩。您也可以手动增加代理存储空间,如 手动扩展 中所述。

  • 缩短消息保留期或减小日志大小。有关如何做到这一点的信息,请参阅调整数据保留参数

  • 删除未使用的主题。

有关如何设置和使用警报的信息,请参阅使用 Amazon CloudWatch 警报。有关 Amazon MSK 指标的完整列表,请参阅 监控 Amazon MSK 集群

调整数据保留参数

使用消息不会将其从日志中删除。要定期释放磁盘空间,您可以明确指定一个保留时间段,即消息在日志中保留的时间。您也可以指定保留日志大小。当达到保留时间段或保留日志大小时,Apache Kafka 会开始从日志中删除非活动段。

要在集群级别指定保留策略,请设置以下一个或多个参数:log.retention.hourslog.retention.minuteslog.retention.mslog.retention.bytes。有关更多信息,请参阅 自定义 MSK 配置

您也可以在主题级别指定保留参数:

  • 要为每个主题指定一个保留时间段,请使用以下命令。

    kafka-configs.sh --bootstrap-server $bs --alter --entity-type topics --entity-name TopicName --add-config retention.ms=DesiredRetentionTimePeriod
  • 要为每个主题指定一个保留日志大小,请使用以下命令。

    kafka-configs.sh --bootstrap-server $bs --alter --entity-type topics --entity-name TopicName --add-config retention.bytes=DesiredRetentionLogSize

您在主题级别指定的保留参数优先于集群级别参数。

在不正常关闭后加快日志恢复

在不正常关闭后,代理可能需要一段时间才能重新启动,因为它需进行日志恢复。默认情况下,Kafka 仅对每个日志目录使用一个线程来执行此恢复。例如,如果您有成千上万个分区,则日志恢复可能需要数个小时才能完成。为加快日志恢复,建议使用配置属性 num.recovery.threads.per.data.dir 增加线程数量。您可以将它设置为 CPU 核心的数量。

监控 Apache Kafka 内存

建议您监控 Apache Kafka 使用的内存。否则,集群可能会变得不可用。

要确定 Apache Kafka 使用了多少内存,您可以监控 HeapMemoryAfterGC 指标。HeapMemoryAfterGC 是垃圾回收后使用的总堆内存百分比。我们建议您创建一个 CloudWatch 警报,当HeapMemoryAfterGC增幅超过 60% 时会采取行动。

可用于减少内存使用的步骤会有所不同,具体取决于您配置 Apache Kafka 的方式。例如,如果您使用事务性消息传递,则可以将 Apache Kafka 配置中的 transactional.id.expiration.ms 值从 604800000 毫秒减少到 86400000 毫秒(从 7 天减少到 1 天)。这减少了每个事务的内存占用。

请勿添加非 MSK 代理

如果您使用 Apache ZooKeeper 命令添加代理,则这些代理不会被添加到您的 MSK 集群中,并且您的 Apache ZooKeeper 将包含有关该集群的错误信息。这可能会导致丢失数据。有关受支持的集群操作,请参阅Amazon MSK 的工作原理

启用传输中加密

有关传输中加密以及如何启用此加密的信息,请参阅传输中加密

重新分配分区

要将分区移动到同一集群上的不同代理,您可以使用名为 kafka-reassign-partitions.sh 的分区重新分配工具。例如,在添加新代理来扩展集群后,您可以通过将分区重新分配给新代理来重新使集群达到平衡。有关如何向集群添加代理的信息,请参阅扩展 Amazon MSK 集群。有关分区重新分配工具的信息,请参阅 Apache Kafka 文档中的扩展集群