这是我参与「第四届青训营 」笔记创作活动的的第3天
一、数据流和动态表
-
如何在实时数据流中定义 SQL 语义中的表?
- 动态表 : 随时间不断变化的表,在任意时刻,可以像查询静态批处理表一样查询它们
-
实时流的查询特点----连续查询
- 查询从不终止
- 查询结果会不断更新,并且会产生一个新的动态表
- 结果的动态表也可转换成输出的实时流
-
动态表到实时流的转换
- Append-only Stream: Append-only 流(只有 INSERT 消息)
- Retract Stream: Retract 流(同时包含 INSERT 消息和 DELETE 消息)
- Upsert Stream:: Upsert 流(同时包含 UPSERT 消息和 DELETE 消息)
-
算子状态
- 在流式计算中,会存在有状态的计算逻辑(算子),有状态的算子典型处理逻辑如下图所示:
比如,需要计算某个用户在网上的点击量,该用户在网站当前的总点击次数就是算子状态,对于新的输入数据,先判断是否是该用户的点击行为,如果是,则将保留的点击次数(状态)增加一,并将当前累加结果输出。
- 数据流和动态表的转换关系图
二、Exactly-Once 和 Checkpoint
一致性保证语义保证的语义
- At-most-once:出现故障时,啥也不做。每条数据至多处理一次,处理延迟低。
- At-least-once:每条数据均至少被处理一次,一条数据可能存在重复消费。
- Exactly-once:最严格的语义,每条数据均被消费且仅消费一次,仿佛故障从未发生。
Checkpoint
-
相关概念
- Checkpoint barrier: 用于标识状态快照的制作,也将数据划分成不同的消费区间
- Checkpoint Alignment: 等待多个上游的Checkpoint barrier到达的现象
- Job Manager -- 负责协调和管理 Checkpoint
-
状态恢复的时间点:需要等待所有处理逻辑消费完成source保存状态之前的数据
-
Chandy-Lamport算法 -- 可以实现快照制作和处理数据的解耦
- 快照制作的开始-------Checkpoint barrier 的下发
- 算子状态制作 和 barrier 传递
- 算子本身状态制作完成存储到远端,然后恢复数据处理
- Barrier Alignment --- 多个上游的等待 barrier 对齐现象
- 算子会等待所有上游的barrier到达后才开始快照的制作
- 已经制作完成的上游算子会继续处理数据,并不会被下游算子制作快照过程阻塞
- Checkpoint 并不阻塞算子数据处
- Checkpoint ACK和制作完成
- 所有算子告知JM状态制作完成后,整个Checkpoint制作完成
三、Flink端到端的 Exactly-once语义
两阶段提交协议
- Two-phase commit protocol(2PC)
- Coordinator:协作者:同步和协调所有节点的处理逻辑的中心节点
- Participant: 参与者:被中心节点调度的其他执行处理逻辑的业务节点
-
预提交阶段
- 1、协作者向所有参与者发送commit消息
- 2、参与者收到消息后,执行事务,但不真正提交。向协作者返回vote yes/vote no消息
-
提交阶段
-
若协作者有收到参与者vote no的消息(或发生等待超时)
- 1、协作者向所有参与者发送commit消息
- 2、每个收到rollback消息的参与者回滚事务的执行操作,并释放事务所占资源,完成后发送ack消息给协作者
- 协作者收到所有参与者ack消息后,标记该事务完成回滚
-
若协作者成功收到所有所有参与者vote yes消息
- 1、协作者向所有参与者发送commit消息
- 2、每个收到commit消息的参与者释放执行事务所需的资源,并结束这次事务的执行,完成后发送ack消息给协作者
- 3、协作者收到所有参与者的ack消息后,标记该事务执行完成
-
-
Checkpoint对作业性能的影响
- 解耦快照和数据处理过程,各算子制作完成状态快照后就可以正常处理数据,不用等下游算子制作完成快照
- 在快照制作和Barrier Alignment过程需要暂时处理数据,仍然会增加数据处理延迟
- 快照保存到远端也有可能极为耗时
两阶段提交协议在 Flink 中的应用
参与者:Job Manager
协作者:Data Source、 Window、 Data Sink
State Backend: 用于管理和保存状态到远端可靠存储(快照)
-
JM发起阶段及 各算子 Checkpoint 的制作
-
提交阶段及 Checkpoint 的制作完成
-
1、事务开启:
- 在sink task向下游写数据之前,均会开启一个事务,后续写数据的操作均在这个事务中执行,事务未提交前,事务写**入的数据下游不可读
-
2、预提交阶段:
- JobManager 开始下发Checkpoint Barrier,当各个处理逻辑收到barrier后停止处理后续数据,对当前状态制作快照,此时sink也不在当前事务下机务处理数据。(处理后续事务需要新打开下一个事务)。状态制作成功则向JM成功的消息,失败则发送失败的消息
-
3、提交阶段:
- 若JM收到所有预提交成功的消息,则向所有处理逻辑(包括sink)发送可以提交此次事务的消息,sink接受到此次消息后,则完成此次事务的提交,此时下游(图中为kafka)可以读到这次事务写入的数据
- 若JM有收到预提交失败的消息,则通知所有处理逻辑回滚这次事务操作,则通知所有处理逻辑回滚这次事务的操作,此时sink则丢弃这次事务提交的数据。
可适用于离线式处理或银行交易等计算量较小的业务
四、Flink案例讲解--- 账单计算服务
- 从Kafka中读取账单数据,然后写入到Kafka中
- 原始业务处理逻辑
- 存在的问题:
-
- 非严格意义上的端到端的Exactly-Once语义
- 若该批数据处理完成后,在写入MySQL中发生异常,则存在部分写入的情况,下次业务启动后,这部分数据仍然会重复写入
- 2.去重能力有限
- 只能在当前处理的一批数据内进行去重,无法在批于批之间进行去重
-
- 迁移到Flink后