扩展基于Kafka的工作负载的最佳实践

Apache Kafka 以其处理大量实时事件的能力而闻名。然而,为了处理数百万个事件,我们在实现 Kafka 生产者服务和消费者服务时需要遵循某些最佳实践。

在开始使用 Kafka之前,让我们了解何时使用 Kafka:

  • 高流量事件流当您的应用程序/服务生成连续的事件流,如用户活动事件、网站点击事件、传感器数据事件、日志事件或股市更新时,Kafka 处理大规模低延迟的能力非常有用。
  • 实时分析。Kafka 在构建实时数据处理管道方面尤其非常有用,在这些管道中,数据需要在到达时立即处理。它允许您将数据流式传输到分析引擎,如 Kafka Streams、Apache Spark 或 Flink,以进行即时分析/洞察和流式或批处理。
  • 解耦应用程序。作为中央消息中心,它可以解耦应用程序的不同部分,使服务能够独立开发和扩展,鼓励负责任的分离原则。
  • 系统间数据集成在集成分布式系统时,Kafka可以高效地在不同团队/项目之间传输数据,充当可靠的数据代理。

与其他队列系统的关键区别

以下是Apache Kafka与ActiveMQ、ZeroMQ和VerneMQ等系统的区别:

持久性存储

Kafka将事件存储在分布式日志中,允许随时重放数据并在系统/节点故障时保持数据持久性,不像一些依赖于内存存储(如Redis)的传统消息队列。

分区

数据分布在经纪人/主题之间,实现大数据流的并行处理和高吞吐量。这有助于消费者线程连接到单个分区,促进水平扩展。

消费者组

多个消费者可以订阅同一主题并从分区内的不同偏移量读取,允许不同团队的重复消费模式用于不同目的消费和处理相同数据。一些示例包括:

  • 由ML团队消费的用户活动以便检测可疑活动
  • 建议团队构建推荐系统
  • 广告团队生成相关广告

Kafka生产者最佳实践

批处理大小和等待时间

通过配置batch.sizelinger.ms,可以提高Kafka生产者的吞吐量。 batch.size是批处理的最大字节大小。 Kafka在发送给生产者之前会尝试进行批处理。

linger.ms确定生产者等待将其他消息添加到批处理中进行处理的最大时间(以毫秒为单位)。

通过配置batch sizelinger.ms设置,可以显著提高系统的性能,控制在将数据发送到处理系统之前累积多少数据,从而实现更好的吞吐量和降低延迟,尤其是在处理大量数据时。它还可能根据所选择的值引入轻微的延迟。特别是,具有正确的linger.ms的大批处理大小可以优化数据传输效率。

压缩

通过启用compression.type配置,还可以通过压缩来增加吞吐量。生产者可以在将数据发送到代理之前使用gzipsnappylz4对数据进行压缩。对于大数据量,该配置有助于减少压缩开销,提高网络效率。它还节省带宽并提高系统的吞吐量。此外,通过设置适当的序列化器和键序列化器,我们可以确保数据以与您的消费者兼容的格式进行序列化。

重试和幂等性

为确保Kafka生产者的可靠性,应启用重试和幂等性。通过配置retries,生产者可以在一定数量的尝试内,自动重新发送任何未在经纪人处获得ack的数据批次。

确认

此配置控制在考虑消息发送成功之前从代理那里需要的确认级别。通过选择正确的acks级别,您可以控制应用程序的可靠性。以下是此配置的可接受值。

  • 0 – 最快,但不能保证消息传递。
  • 1 – 消息在写入主代理后得到确认,提供基本的可靠性。
  • all – 仅当所有副本都确认后,消息才被视为传递,确保高耐用性。

根据工作负载进行配置调优

您应该开始跟踪指标,例如消息发送率、批量大小和错误率,以识别性能瓶颈。根据功能/数据的修改或更新,定期检查并调整生产者设置。

Kafka消费者最佳实践

消费者组

每个Kafka消费者都应属于一个消费者组;一个消费者组可以包含一个或多个消费者。通过在组中创建更多消费者,您可以扩展以从所有分区读取,从而允许您处理大量数据。group.id 配置有助于识别消费者所属的消费者组,从而在多个消费者之间实现负载均衡,这些消费者从同一主题消费。最佳实践是使用有意义的组ID,以便在您的应用程序中轻松识别消费者组。

偏移量提交

您可以控制何时提交偏移量,这可以帮助避免数据丢失。有两种提交偏移量的方法:自动和手动。对于高吞吐量的应用程序,您应考虑手动提交以获得更好的控制。

  • auto.offset.reset – 定义当消费者开始消费没有提交偏移量的主题时要执行的操作(例如,新主题或消费者首次加入组时)。 选项包括earliest(从开头读取)、latest(从末尾读取)或none(抛出错误)。 在大多数情况下选择”earliest”,以避免新消费者加入组时丢失数据。控制消费者开始消费数据的方式,确保在消费者重新启动或加入组时保持正确行为。
  • enable.auto.commit – 帮助配置定期自动提交偏移量。通常,在大多数生产场景中,我们将值设置为false,这样我们就不需要高可靠性,并且可以在应用程序逻辑中手动提交偏移量,以确保精确一次处理。提供控制以管理偏移提交,从而更好地控制数据处理。
  • auto.commit.interval.msinterval指定以毫秒为单位的时间间隔,在此间隔内,如果enable.auto.commit设置为true,则偏移量将自动提交。根据您的应用程序处理时间进行修改,以避免由于意外故障而导致数据丢失。

Fetch Size和Max Poll Records

该配置有助于控制每个请求中检索的记录数量,配置fetch.min.bytesmax.poll.records。增加此值可以提高应用程序的吞吐量,同时减少CPU使用率并减少向代理程序发出的调用次数。

  • fetch.min.bytes – 每个单独的轮询请求从代理程序获取的最小字节数。设置一个较小的值以避免不必要的网络调用,但不要设置得太小以避免过多的轮询。通过防止频繁的小请求,有助于优化网络效率。
  • fetch.max.bytes 单个拉取请求从代理中拉取的最大字节数。 根据可用内存调整,以防止过载消费者工作。这可以减少 单次拉取的数据量,避免内存问题。
  • max.poll.interval.ms – 在超时之前等待拉取请求返回数据的最长时间。 设置一个合理的超时时间,以避免消费者挂起/延迟,如果数据不可用。它有助于防止 消费者等待消息时间过长而被卡住。(有时,如果活跃探针受影响,k8s pods可能会重新启动)。

分区分配

这是用于将分区(partition.assignment.strategy)分配给组内消费者的策略(例如,rangeroundrobin)。 对于大多数情况,请使用 range 以均匀分配分区给消费者。这可以实现 组内消费者之间负载均衡分布。

在使用Kafka之前的一些建议考虑事项:

  • 复杂性实施Kafka需要对分区和偏移管理等分布式系统概念有更深入的了解,因为它具有先进的功能和配置。
  • 监控和管理。实施监控和Kafka集群管理对于确保高可用性和性能至关重要。
  • 安全性实施强大的安全实践来保护通过Kafka主题传输的敏感数据也很重要。

实施这些最佳实践可以帮助您扩展基于Kafka的应用程序以处理数百万/数十亿个事件。然而,重要的是要记住,最佳配置可能因应用程序的具体要求而有所不同。

Source:
https://dzone.com/articles/best-practices-for-scaling-kafka-based-workloads