KafkaStream时间窗口

相关概念:

流处理拓扑

流是 Kafka Streams 提供的最重要的抽象:它表示一个无限的、不断更新的数据集。流是不可变数据记录的有序、可重放和容错序列,其中数据记录定义为键值对。
流处理应用程序是使用 Kafka 流库的任何程序。它通过一个或多个处理器拓扑定义其计算逻辑,其中处理器拓扑是通过流(边)连接的流处理器(节点)的图形。
流处理器是处理器拓扑中的一个节点;它表示一个处理步骤,通过一次从拓扑中的上游处理器接收一条输入记录来转换流中的数据,将其操作应用于它,并可能随后向其下游处理器生成一个或多个输出记录。
拓扑中有两个特殊的处理器:
源处理器(source processor):源处理器是一种特殊类型的流处理器,没有任何上游处理器。它通过使用来自这些主题的记录并将其转发到其下游处理器,从一个或多个 Kafka 主题生成到其拓扑的输入流。
接收器处理器(sink processor):接收器处理器是一种特殊类型的流处理器,没有下游处理器。它将从其上游处理器接收的任何记录发送到指定的 Kafka 主题。
在这里插入图片描述

时间

流处理的一个关键方面是时间的概念,以及如何对其进行建模和集成。 例如,某些操作(如窗口)是基于时间边界定义的。

流中常见的时间概念是:

事件时间 - 事件或数据记录发生的时间点,即最初是在“源头”创建的。例:如果事件是汽车中的 GPS 传感器报告的地理位置更改,则关联的事件时间将是 GPS 传感器捕获位置更改的时间。
处理时间 - 事件或数据记录碰巧由流处理应用程序处理的时间点,即记录被使用的时间点。处理时间可以是毫秒、几小时或几天等。晚于原始事件时间。例:想象一下,一个分析应用程序读取和处理从汽车传感器报告的地理位置数据,并将其呈现给车队管理仪表板。在这里,分析应用程序中的处理时间可能是毫秒或秒(例如,对于基于 Apache Kafka 和 Kafka Streams 的实时管道)或事件时间后的几小时(例如,对于基于 Apache Hadoop 或 Apache Spark 的批处理管道)。
摄取时间 - Kafka 代理将事件或数据记录存储在主题分区中的时间点。与事件时间的区别在于,此摄取时间戳是在 Kafka 代理将记录追加到目标主题时生成的,而不是在“源”创建记录时生成的。与处理时间的不同之处在于,处理时间是流处理应用程序处理记录的时间。例如,如果从未处理过记录,则没有处理时间的概念,但它仍然具有引入时间。
事件时间和摄取时间之间的选择实际上是通过 Kafka(而不是 Kafka Streams)的配置完成的:从 Kafka 0.10.x 开始,时间戳会自动嵌入到 Kafka 消息中。根据 Kafka 的配置,这些时间戳表示事件时间或摄取时间。可以在代理级别或每个主题指定相应的 Kafka 配置设置。Kafka Streams 中的默认时间戳提取器将按原样检索这些嵌入的时间戳。因此,应用程序的有效时间语义取决于这些嵌入式时间戳的有效 Kafka 配置。

Kafka Streams通过接口为每个数据记录分配一个时间戳。 这些每条记录的时间戳描述了流相对于时间的进度,并由与时间相关的操作(如窗口操作)利用。 因此,只有当新记录到达处理器时,此时间才会前进。 我们将此数据驱动时间称为应用程序的流时间,以与此应用程序实际执行时的挂钟时间区分开来。 然后,接口的具体实现将为流时间定义提供不同的语义。 例如,根据数据记录的实际内容检索或计算时间戳,例如嵌入的时间戳字段以提供事件时间语义, 并返回当前挂钟时间,从而产生流时间的处理时间语义。 因此,开发人员可以根据其业务需求强制执行不同的时间概念。

最后,每当 Kafka Streams 应用程序将记录写入 Kafka 时,它还将为这些新记录分配时间戳。时间戳的分配方式取决于上下文:

当通过处理某些输入记录生成新的输出记录时,例如在函数调用中触发,输出记录时间戳直接从输入记录时间戳继承。
当通过周期函数(如 )生成新的输出记录时,输出记录时间戳定义为流任务的当前内部时间(通过 获得)。
对于聚合,结果更新记录的时间戳将是导致结果的所有输入记录的最大时间戳。
您可以通过分配来更改处理器 API 中的默认行为 用于在调用 时显式输出记录的时间戳。

对于聚合和联接,时间戳是使用 遵循规则。

对于具有左和右的联接(流-流、表-表) 输入记录,则分配输出记录的时间戳。max(left.ts, right.ts)
对于流表联接,为输出记录分配时间戳 从流记录。
对于聚合,Kafka Streams 还会按键计算所有记录的时间戳,无论是全局(对于非窗口) 或按窗口。
对于无状态操作,将传递输入记录时间戳。 对于发出多条记录的同级和同级,所有 输出记录从相应的输入记录继承时间戳。

聚合

聚合操作采用一个输入流或表,并通过将多个输入记录合并为单个输出记录来生成一个新表。聚合的示例包括计算计数或总和。

输入流可以是 KStream 或 KTable,但输出流将始终是 KTable。这允许 Kafka Streams 在生成和发出聚合值后,在进一步记录无序到达时更新聚合值。当发生这种无序到达时,聚合的 KStream 或 KTable 会发出新的聚合值。由于输出是 KTable,因此在后续处理步骤中,新值被视为使用相同的键覆盖旧值。

窗口

窗口化允许您控制如何将具有相同键的记录分组到有状态操作(如或所谓的窗口)中。窗口按记录键进行跟踪。

使用窗口时,可以为窗口指定宽限期。此宽限期控制 Kafka 流在给定窗口中等待无序数据记录的时间。如果记录在窗口的宽限期过后到达,则该记录将被丢弃,并且不会在该窗口中处理。具体而言,如果记录的时间戳指示它属于窗口,但当前流时间大于窗口结束加上宽限期,则会丢弃该记录。

无序记录在现实世界中总是可能的,应该在您的应用程序中正确考虑。这取决于无序记录的有效处理方式。在处理时间的情况下,语义是“正在处理记录时”,这意味着无序记录的概念不适用,因为根据定义,任何记录都不能是无序的。因此,无序记录只能被视为事件时间。在这两种情况下,Kafka Streams 都能够正确处理无序记录。

接入kafkaStream

导入依赖

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-streams</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>3.4.0</version>
</dependency>
<!-- Optionally include Kafka Streams DSL for Scala for Scala 2.13 -->
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-streams-scala_2.13</artifactId>
    <version>3.4.0</version>
</dependency>

在代码中实现

首先,创建实例。KafkaStreams
构造函数的第一个参数采用用于定义拓扑的拓扑(用于 DSL 或处理器 API)。Topology
第二个参数是 的实例,它定义此特定拓扑的配置。java.util.Properties

import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.kstream.StreamsBuilder;
import org.apache.kafka.streams.processor.Topology;

// Use the builders to define the actual processing topology, e.g. to specify
// from which input topics to read, which stream operations (filter, map, etc.)
// should be called, and so on.  We will cover this in detail in the subsequent
// sections of this Developer Guide.

StreamsBuilder builder = ...;  // when using the DSL
Topology topology = builder.build();
//
// OR
//
Topology topology = ...; // when using the Processor API

// Use the configuration to tell your application where the Kafka cluster is,
// which Serializers/Deserializers to use by default, to specify security settings,
// and so on.
Properties props = ...;

KafkaStreams streams = new KafkaStreams(topology, props);

此时,内部结构已初始化,但处理尚未开始。 您必须通过调用该方法显式启动 Kafka Streams 线程:KafkaStreams#start()

// Start the Kafka Streams threads
streams.start();

要捕获任何意外异常,可以在开始之前设置 应用。每当流线程因意外异常终止时,都会调用此处理程序:java.lang.Thread.UncaughtExceptionHandler

// Java 8+, using lambda expressions
streams.setUncaughtExceptionHandler((Thread thread, Throwable throwable) -> {
  // here you should examine the throwable/exception and perform an appropriate action!
});

若要停止应用程序实例,请调用该方法:KafkaStreams#close()

// Stop the Kafka Streams threads
streams.close();

要允许应用程序正常关闭以响应 SIGTERM,建议您添加一个关闭挂钩并调用 .KafkaStreams#close

Java 8+ 中的关闭钩子示例:

// Add shutdown hook to stop the Kafka Streams threads.
// You can optionally provide a timeout to `close`.
Runtime.getRuntime().addShutdownHook(new Thread(streams::close));

应用程序停止后,Kafka Streams 会将此实例中运行的任何任务迁移到剩余的可用任务 实例。

参考网站

KafkaStreams官方文档

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Kafka Stream是一个用于处理实时数据流的库。它可以从Kafka数据源中读取数据,并进行流式计算和处理。 Kafka Stream的架构包括以下几个部分:整体架构、Processor Topology、并行模型、KTable和KStream、以及状态存储。整体架构描述了Kafka Stream的工作原理和组件之间的关系。Processor Topology定义了数据流的处理逻辑和操作流程。并行模型允许Kafka Stream根据需要调整并行度,以适应不同的处理需求。KTable和KStreamKafka Stream中两个重要的数据结构,分别用于表示实时数据流和实时表。状态存储用于存储和管理处理过程中产生的中间状态和结果。 Kafka Stream解决了流式系统中的几个关键问题:时间窗口、Join、聚合与乱序处理以及容错。通过对时间的处理,Kafka Stream可以支持实时数据处理和窗口计算。窗口可以用来对数据进行分组和聚合。Kafka Stream还支持对不同数据流进行Join操作,并处理数据流中的乱序问题。同时,Kafka Stream具备容错能力,可以在发生故障时进行恢复和重试。 总体来说,Kafka Stream是一个强大的工具,可以实现实时数据流处理和计算。它的灵活架构、丰富的功能和可靠的容错机制使得它在流式系统中广泛应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Kafka Stream](https://blog.csdn.net/zmzdmx/article/details/111301707)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值