三、【计算】Exactly Once 语义在Flink中的实现(上) | 青训营笔记

114 阅读5分钟

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

  👉引言💎

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 热爱写作,愿意让自己成为更好的人...... ......

铭记于心
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉

一、数据流和动态表

1 名词解析

  • Stream: 数据流

  • Dynamic Table: 动态表

  • Continuous Queries: 连续查询

  • Append-only Stream: Append-only 流(只有 INSERT 消息)

  • Retract Stream: Retract 流(同时包含 INSERT 消息和 DELETE 消息)

  • Upsert Stream:: Upsert 流(同时包含 UPSERT 消息和 DELETE 消息)

  • Changelog: 包含 INSERT/UPDATE/DELETE 等的数据流

  • State: 计算处理逻辑的状态

2 动态表

  • 概念与作用

    动态表随时间不断变化,可以处理流数据,同时任一时刻又是一个静态表,满足表的查询功能

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXgwhU0j-1661356520181)(image/image_add8GAEBIP.png)]

    通过sql查询表的动态化 解决流式数据处理的问题,这就涉及到数据流与动态表的转换

  • 连续查询

    1. 查询从不终止

    2. 查询结果会不断更新,产生一个新的动态表

    在任何时候,连续查询的结果在语义上与以批处理模式在输入表快照上执行的相同查询的结果相同

3 动态表与数据流的相互转换

  • Append-only Stream: Append-only 流(只有 INSERT 消息)

  • Retract Stream: Retract 流(同时包含 INSERT 消息和 DELETE 消息)

  • 1 eg:

    连续查询 一段时间内的用户访问url信息,存入结果表中

    1. 第一个查询:更新历史结果,包括insert与update操作

    2. 第二个查询:只附加到结果表,只包含insert操作

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vi49fTc0-1661356520182)(image/image_qhsY5C8fm-.png)]

  • 2 动态表到实时流的转换 (Retract消息产生):

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eRv1Ccr0-1661356520183)(image/image_T_sYyHSozN.png)]

    • Upsert Stream::Upsert 流(同时包含 UPSERT 消息和 DELETE 消息)

  • 3 状态:

    存储历史记录,更新新数据;查询可能会有状态,用来不断更新查询的结果

    • 算子状态

      • 在流式计算中,会存在有状态的计算逻辑(算子),算子状态可以通过快照保存,利于数据恢复,有状态的算子典型处理逻辑如下图所示: 在这里插入图片描述

      比如,需要计算某个用户在网上的点击量,该用户在网站当前的总点击次数就是算子状态,对于新的输入数据,先判断是否是该用户的点击行为,如果是,则将保留的点击次数(状态)增加一,并将当前累加结果输出。

  • 4 数据流和动态表的转换关系图

二、Exactly-Once 和 Checkpoint

1 名词解析

  • Application Consistency Guarantees: 作业一致性保证

    • At-most-once:每条数据消费至多一次

    • At-least-once:每条数据消费至少一次

    • Exactly-once: 每条数据都被消费且仅被消费一次

  • Checkpoint: Flink 实现各个计算逻辑状态快照算法,也可指一次状态快照

  • Checkpoint barrier: 用于标识状态快照的制作,也将数据划分成不同的消费区间

  • Checkpoint Alignment: 等待多个上游的Checkpoint barrier到达的现象

  • JobManager: 负责协调和管理 Checkpoint


在上述数据流与动态表相互转换过程中,即对流式数据进行处理时不可避免的会遇到数据故障,此时基于不同的语义规则,会有不同的处理方式:

2 一致性保证语义:

  • At-most-once:每条数据消费至多一次,处理延迟低

  • At-least-once:每条数据消费至少一次,一条数据可能存在重复消费

  • Exactly-once:每条数据都被消费且仅被消费一次,仿佛故障从未发生

3 Exactly-once:

  • 状态快照与恢复:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BvtB4Isk-1661356520186)(image/image_C7-HHDnMi7.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fcQCJdiY-1661356520186)(image/image_RSIBYtL5ns.png)]

    根据上面 奇偶累加和 的快照处理与恢复流程 可以看出 快照处理的大致流程

    • 快照制作需要一个时间点,需要等待所有处理逻辑消费完成,source才可以保留算子状态及历史数据

    • 一个相对来说比较简单的快照制作算法举例:

      1. 暂停处理输入的数据

      2. 等待后续所有处理算子消费当前已经输入的数据;

      3. 待2处理完后,作业所有算子复制自己的状态并保存到远端可靠存储;

      4. 恢复对输入数据的处理

    显而易见的是,该算法中快照制作与数据处理高度耦合,也就是说快照制作时会将整个数据处理流程暂停中断,等待制作完成后继续进行,可想而知这种算法在 实际生产场景中太过低效,是无法进行落地实现的

    于是,就有了Chandy-Lamport 算法

  • Chandy-Lamport 算法

    • 对于下述数据流处理场景

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRX8G9eA-1661356520187)(image/image_ZVJw4YpNpf.png)]

    • 快照制作的开始

      • 算子状态制作和 barrier 传递

        每一个source 算子都接收到JM发送的Checkpoint Barrier标识状态快照制作的开始

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nTWjYjZ-1661356520188)(image/image_5N-RA5_Ik-.png)]

        各个source保存自己状态后,向所有连接的下游继续发送Checkpoint Barrier,同时告知JM自己状态已经制作完成。

      • 多个上游的等待 barrier 对齐现象

        已经制作完成的上游算子会继续处理数据,并不会被下游算子制作快照的过程阻塞

        实现了 快照制作与数据处理的 解耦

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQbtlhEO-1661356520189)(image/image_Iembs1zt-W.png)]

      • Checkpoint ACK和制作完成

      缺点: Checkpoint 对作业性能的影响

      • 在快照制作和Barrier Alignment过程中需要暂停处理数据,仍然会增加数据处理延迟;

      • 快照保存到远端也有可能极为耗时。

🌹写在最后💖: 路漫漫其修远兮,吾将上下而求索!伙伴们,再见!🌹🌹🌹在这里插入图片描述