Spark Streaming 计算窗口的理解

Spark Streaming Window

1.创建一个流

       // 创建一个 SparkConf 对象,并设置应用的名字
        SparkConf conf = new SparkConf().setAppName("JavaSparkStreamingExample").setMaster("local[*]");

        // 创建一个 JavaStreamingContext 对象,它是所有 Spark Streaming 功能的入口点。
		JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds(10);
        // 创建一个 DStream,它会连接到 hostname:port 的服务器
        JavaReceiverInputDStream<String> lines = jssc.socketTextStream("localhost", 9999);

2.窗口操作的工作原理

在Apache Spark Streaming中,窗口操作不是在第一次触发时仅创建一次,而是根据定义的滑动间隔定期创建和触发。每个窗口操作都会根据其配置的窗口长度和滑动间隔周期性地处理数据。这个过程是持续的,直到StreamingContext停止。

  • 窗口长度(Window Duration):这是窗口覆盖的时间范围,即在每次窗口操作中会处理多长时间内的数据。

  • 滑动间隔(Sliding Interval):这是窗口操作触发的频率。每隔一定的滑动间隔时间,窗口会向前“滑动”,并且处理在新窗口长度内的数据。

窗口的周期性创建和触发

每次窗口操作触发时,都会基于当前的时间点向前回溯窗口长度的时间范围,收集那段时间内的数据进行处理。这意味着:

  • 窗口是周期性创建的,每个滑动间隔结束时,都会基于那个时间点创建一个新的窗口。
  • 窗口操作是周期性触发的,每次窗口滑动时,都会对最近的窗口长度时间内的数据进行处理。

示例

假设有一个窗口长度为15分钟,滑动间隔为5分钟的窗口操作。这意味着:

  • 每5分钟,窗口操作会触发一次。
  • 每次触发时,它会处理过去15分钟内的数据。
  • 这个过程从StreamingContext启动开始,每隔5分钟重复一次,直到StreamingContext停止。

注意:

1.虽然定义的窗口大小为15分钟,但是在程序启动达到第一个滑动间隔(5分钟)时,会创建第一个窗口(0-5分钟)并处理窗口内的数据,此时窗口大小仅为5分钟,在达到第二个滑动间隔时,创建第二个窗口(0-10分钟),此时窗口大小为10分钟,第三个窗口(0-15)的大小才为15分钟。可以理解为前三次并不是滑动,而是拓展窗口,第四次才会滑动并创建第四个窗口(5-20分钟),然后第五个窗口(10-25......
2.即达到窗口大小后才会开始滑动。第一个窗口可以理解为-10到5,只有0-5分钟有数据,第二个窗口可以理解为-5到10,只有0-10分钟的数据,第三个窗口为0-15,此时达到了窗口大小,在到达下一个间隔时会滑动创建第四个窗口处理5-20分钟的数据.

结论

当定义一个窗口操作时,Spark会根据指定的窗口长度和滑动间隔来安排这个操作。从流处理作业开始的那一刻起,Spark就会开始跟踪时间,以决定何时触发窗口操作。这个过程可以分为以下几个步骤:

  1. 定义窗口操作:当您定义一个窗口操作时,指定窗口长度和滑动间隔。窗口长度决定了要处理的数据的时间范围,而滑动间隔决定了窗口操作触发的频率。

  2. 启动流处理作业:一旦流处理作业(StreamingContext)启动,Spark Streaming就会开始监控时间,并根据定义的窗口操作来安排数据处理。

  3. 触发窗口操作:在第一次达到滑动间隔时间后,Spark会触发窗口操作,处理过去窗口长度时间内的数据。例如,如果窗口长度为15分钟,滑动间隔为5分钟,则每隔5分钟,Spark会处理最近15分钟内的数据。

  4. 周期性触发:在第一次触发之后,Spark会继续每隔定义的滑动间隔时间触发窗口操作。每次触发时,它都会处理当前窗口长度内的数据。

  5. 计时和状态维护:Spark内部会维护一个计时器和状态信息,以确保每个窗口操作都能在正确的时间触发。这意味着Spark会在第一次触发窗口操作后“记录下有这么一个窗口操作”,并根据滑动间隔来“计时等待”直到下一次触发。

这种机制确保了窗口操作可以按照预定的频率周期性地处理数据,无论数据是连续到达还是有间断。这对于处理实时数据流非常重要,因为它允许开发者基于时间窗口来分析数据,无论数据的到达模式如何。

3.流式窗口计算示例

// 创建一个 SparkConf 对象,并设置应用的名字
SparkConf conf = new SparkConf().setAppName("JavaSparkStreamingExample").setMaster("local[*]");

// 创建一个 JavaStreamingContext 对象,它是所有 Spark Streaming 功能的入口点。
JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds(10);

// 创建一个 DStream,它会连接到 hostname:port 的服务器
JavaReceiverInputDStream<String> lines = jssc.socketTextStream("localhost", 9999);

cacheRdd.window(Durations.seconds(60), Durations.seconds(20))
参数说明
  • 流处理批次长度:new JavaStreamingContext(conf, Durations.seconds(10); Spark Streaming实际为微批处理,按照指定时间间隔生成一个rdd进行处理,此处为10s,即每批次接收10s的数据构成一个rdd

  • 窗口长度: 60 秒,意味着窗口将包含最近 60 秒的数据。

  • 滑动间隔:20 秒,意味着每20 秒执行一次窗口操作。

三个参数的关系:
  • 滑动间隔 必须是 流处理批次长度的整数倍

  • 窗口长度 必须是 流处理批次长度的整数倍

  • 如果窗口长度=滑动间隔则该窗口为滚动窗口没有元素重叠;

  • 如果窗口长度>滑动间隔则该窗口为滑动窗口存在元素交叠;

  • 一般情况下所有的流的窗口长度 >= 滑动间隔,因为如果小于滑动间隔,会有数据的遗漏。

  • 在 Spark Streaming 中,滑动间隔必须是批处理间隔的整数倍,但窗口长度并不需要是滑动间隔的整数倍。为了避免可能的问题,通常建议将窗口长度设为滑动间隔的整数倍,这样可以确保每个窗口都有相同的数据点数。

  • Storage中会保留最近两个窗口的微批rdd,如窗口大小为40,批次间隔20,那么会缓存(40/20)* 2=4个rdd

在这里插入图片描述

当如果窗口大小不是滑动间隔的整数倍时:

JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds(10);
cacheRdd.window(Durations.seconds(300 + 10), Durations.seconds(300))

窗口大小为310秒,滑动间隔为300秒。这意味着每5分钟执行一次窗口操作,但每次处理的数据覆盖的时间范围是5分钟零10秒。这里给出一个具体的时间节点示例来解释这个过程。

示例

假设数据流开始时间是00:00(午夜)

  1. 第一个窗口:00:00 - 00:05:00

    • 到达第一个滑动间隔,处理当前时间(00:05:00)往前310s内的rdd数据
    • 窗口开始时间:00:00(可以变相理解为-10s 即23:59:50 不过没有收到23:59:50-00:00:00 这个微批rdd)
    • 窗口结束时间:00:05:00
    • 在00:05时刻,窗口操作执行,处理的是从00:00到00:05:00的数据。
  2. 第二个窗口:00:04:50 - 00:10:00

    • 到达第二个滑动间隔,处理当前时间(00:10:00)往前310s内的rdd数据
    • 窗口开始时间:00:04:50
    • 窗口结束时间:00:10:00
    • 在00:10时刻,窗口操作执行,处理的是从00:04:50到00:10:00 共310s的数据。
  3. 第三个窗口:00:09:50 - 00:15:00

    • 窗口开始时间:00:09:50
    • 窗口结束时间:00:15:00
    • 在00:15时刻,窗口操作执行,处理的是从00:09:50到00:15:00工310s的数据。

以此类推,每个后续窗口都会向前滑动300秒(5分钟),但每次都处理310秒的数据。

关键点

  • 数据重叠:由于窗口大小(310秒)比滑动间隔(300秒)大,所以每个窗口与前一个窗口有10秒的数据重叠。这意味着某些数据会被重复处理,这在某些情况下是有意义的,比如确保数据处理的完整性和连续性。

4.Spark Streaming window的缺陷

时间概念

  • 1)、事件时间【EventTime】,表示数据本身产生的时间,该字段在【数据本身】中;

  • 2)、注入时间【IngestionTime】,表示数据到达流式系统时间,简而言之就是流式处理系统接收到数据的时间;

  • 3)、处理时间【ProcessingTime】,表示数据被流式系统真正开始计算操作的时间。

Spark Streaming只能基于注入时间, 当数据延迟到达时计算结果可能存在偏差

  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值