这是我参与「第四届青训营」笔记创作活动的第4天。
数据流和动态表
传统SQL与流处理
动态表 : 随时间不断变化的表,在任意时刻,可以像查询静态批处理表一样查询它们。
实时流的查询特点:
- 查询从不终止
- 查询结果会不断更新,并且会产生一个新的动态表
- 结果的动态表也可转换成输出的实时流
动态表到实时流的转换
- Append-only Stream: Append-only 流(只有 INSERT 消息)
- Retract Stream: Retract 流(同时包含 INSERT 消息和 DELETE 消息)
- Upsert Stream:: Upsert 流(同时包含 UPSERT 消息和 DELETE 消息)
一致性保证语义
- At-most-once:每条数据消费至多一次,处理延迟低
- At-least-once:每条数据消费至少一次,一条数据可能存在重复消费
- Exactly-once:每条数据都被消费且仅被消费一次,仿佛故障从未发生
Exactly-Once 和 Checkpoint
快照与恢复
状态恢复的时间点:
所有处理逻辑完成,source保存状态和先前数据。
快照制作:
Source算子接收到JM发送的Barrier,开始制作->
source保存自身状态后,向下游发送barrier,告知JM完成->
所有算子都告知JM制作完成后,checkpoint结束。
(算子会等待所有上游barrier到达后才会开始快照制作。
上游算子制作完直接继续处理数据,与下游算子制作快照无关系)
Checkpoint 对作业性能影响
- 解耦了快照制作与数据处理过程,算子在处理完状态快照就可以正常处理数据。
- 制造快照和Barrier Alignment 过程中可能需要暂停,数据处理延迟可能增加。
- 快照保存到远端可能极为耗时。
端到端 Exactly-Once 实现
Checkpoint可以保证每条数据对各个有状态的算子更新一次,但sink输出仍然可能下发重复的数据。端到端 Exactly-Once还需要特殊的sink算子。
两阶段提交协议(2PC)
多个节点参与执行的分布式系统中,为协调各个节点同时执行或者回滚事务性的操作,引入了一中心节点来统一处理其他节点的执行逻辑,中心节点叫协作者,其余被调度的叫参与者。
-
预提交阶段
协作者发送commit消息;
参与者收到消息后,执行事务,但是不提交;
若成功执行,则发送成功的消息,否则则发送失败的消息。 -
提交阶段
(若协作者成功收到所有参与者的yes)
协作者发送commit消息;
参与者收到消息后,释放资源,结束事务执行;
之后参与者发送ack消息给协作者;
协作者收到所有ack消息后,标识事务完成。\(若协作者收到参与者的no或超时)
协作者发送rollback消息;
参与者收到消息后,回滚事务执行操作,释放资源;
之后参与者发送ack消息给协作者;
协作者收到所有ack消息后,标识事务完成回滚。
Flink两阶段提交总结
-
事务开启:
在sink task向下游写数据之前,均会开启一个事务,后续所有写数据的操作均在这个事务中执行,事务未提交前,事务写入的数据下游不可读; -
预提交阶段:
JM下发Barrier,当各个处理逻辑接收到barrier后停止处理后续数据,对当前状态制作快照,此时sink也不再当前事务下继续处理数据(处理后续的数据需要新打开下一个事务)。状态制作成功则向JM发送成功的消息,失败则发送失败的消息; -
提交阶段:
若JM收到所有预提交成功的消息,则向所有处理逻辑(包括sink)发送可以提交此次事务的消息,sink接收到此消息后,则完成此次事务的提交。若JM有收到预提交失败的消息,则通知所有处理逻辑回滚这次事务的操作,sink丢弃这次事务提交的数据。
总结
本次课程更深一步对Flink执行方式进行了探讨,了解了Exactly-Once的实现方式和原理,以及Checkpoint的对作业性能的影响。