流计算中的Windows计算|青训营笔记

69 阅读5分钟

这是我参与「第四届青训营 」笔记创作活动的的第5天

  1. 概念

    1. 流式计算与批式计算的对比

      特性批式计算流式计算
      数据存储HDFS,HiveKafka,Pulsar
      数据时效性天级别分钟级别
      准确性精准精准和时效性之间取舍
      典型计算引擎Hive,Spark,FlinkFlink
      计算模型Exactly-OnceAt Least Once/Exactly Once
      资源模型定时调度长期持有
      主要场景离线天级别数据报表实时数仓,实时营销,实时风控
    2. 批处理

      对于批处理的典型数仓架构为T+1架构,即数据计算时天级别,当天只能看到前一天的计算结果,因为数据是固定的,所以输入输出都是固定的。

    3. 处理时间 VS 事件时间

      处理时间:数据在流式计算系统中真正处理时所在机器的当前时间。

      事件时间:数据产生的时间,比如客户端、传感器、后端代码等上报数据时的时间。

    4. 处理时间窗口

      实时计算:处理时间窗口

      数据实时流动,实时计算,窗口结束直接发送结果,不需要周期调度任务

      Snipaste_2022-07-30_08-37-56.png

      实时计算:事件时间窗口

      数据实时进入到真实事件发生的窗口中进行计算,可以有效的处理数据延迟和乱序。

    5. Watermark

      对于时间窗口,我们知道了他的开启,但是在什么时候窗口才算结束,这就需要我们使用watermark来进行计时,即在数据中插入一些watermark,来表示当前的真实时间。

      更是在数据存在乱序的时候,watermark就比较重要了,它可以用来在乱序容忍和实时性之间做一个平衡。

  2. Watermark

    1. 概念:Watermark表示系统公认为的当前真实的事件时间

    2. Watermark的产生

      Snipaste_2022-07-30_10-41-45.png

      同时可以通过Flink UI观察Watermark

    3. 典型问题

      1. Per-partition VS per-subtask watermark 生成

        1. Per-subtask watermark生成

          典型的问题是如果一个source subtask消费多个partition,那么多个partition之间的数据读取可能会加剧乱序程度

        2. Per-partition watermark生成

          新版本引入了基于每个partition单独的watermark生成机制,这种机制可以有效避免上面的问题

      2. 部分partition/subtask 断流

        根据上面的watermark传递机制,下游subtask会将上游所有subtask的watermark值的最小值作为自身的watermark值,如果上游有一个subtask的watermark不更新了,则下游的watermark都不更新

        解决方案:Idle source

        当某个subtask断流超过配置的idle超时时间时,将当前subtask置为idle,并下发一个idle的状态给下游。下游在计算自身watermark的时候,可以忽略当前时idle 的那些subtask。

      3. 迟到数据处理

        因为watermark标识当前事件发生的真实时间,那当晚于watermark的数据到来时,系统会认为这种数据是迟到的数据

        算子自身来决定如何处理迟到数据:

        ​ Window聚合,默认会丢弃迟到数据

        ​ 双流join,如果是outer join,则可以认为它不能join到任何数据

        ​ CEP,默认丢弃

  3. Window

    1. Window基本功能

      1. 分类

        典型的Window

        1. Tumble Window(滚动窗口)
        2. Sliding Window(滑动窗口)
        3. Session Window(会话窗口)

        其他Window

        1. 全局Window
        2. Count Window
        3. 累计窗口
        4. ...........
      2. 滚动窗口

        1. 窗口划分:

          1. 每个key单独划分
          2. 每条数据只会属于一个窗口
        2. 窗口触发:

          Window结束时间到达的时候一次性触发

      3. 滑动窗口

        1. 窗口划分:

          1. 每个key单独划分
          2. 每条数据可能会属于多个窗口
        2. 窗口触发:

          Window结束时间到达的时候一次性触发

      4. 会话窗口

        1. 窗口划分:

          1. 每个key单独划分
          2. 每条数据会单独划分为一个窗口,如果window之间有交集,则会对窗口进行merge
        2. 窗口触发

          Window结束是按到达的时候一次性触发

      5. 迟到数据处理

        1. 迟到定义:一条数据到来后,会用WindowAssigner给它划分一个window,一般时间窗口是一个时间区间,如果划分出来的window end 比当前的watermark值还小,说明这个窗口已经触发了计算,这条数据就会被认为是迟到数据
        2. 只有事件时间下才会有迟到的数据
        3. 处理:默认丢弃
      6. 增量计算 Vs 全量计算

        1. 增量计算:

          每条数据到来,直接进行计算,window值存储计算结果,不保存每条数据。典型的reduce,aggregate等函数都是增量计算

        2. 全量计算:

          每条数据到来,会存储到window的state中。等到window触发计算的时候,会将所有数据拿出来一起计算。典型的process函数就是全量计算

      7. EMIT

        1. EMIT指的是,在window没有结束的时候,提前把window计算的部分结果输出出来
    2. 高级优化

      1. Mini-batch优化解决频繁访问状态的问题
      2. local-global优化解决倾斜问题
      3. Distinct状态复用降低状态量
      4. Pane优化降低滑动窗口的状态存储量