Exactly Once语义在Flink中的实现 | 青训营笔记

89 阅读4分钟

这是我参与【第四届青训营】笔记创作活动的第2天

一、数据流和动态表

1.1 传统SQL和流处理对比:

image.png

1.2 数据流和动态表转换

image.png

1.3 动态表

定义:与表示批处理数据的静态表不同,其是随时间变化的,可以像查询静态批处理一样查询,数据库表是INSERT、UPDATE和DELETE DML语句的stream的结果,通常称为changelog stream

1.4 连续查询

特征:(1)查询从不终止 (2)查询结果会不断更新,产生一个新的动态表 (3)任何时刻结果在语义上与以批处理模式在输入表快照上执行的相同查询的结果相同

1.5 Retract消息的产生

代码:SELECT user, COUNT(ur1) as cnt FROM clicks GROUP BY user

状态:需要存储每个用户的URL计数,以便能够增加该计数并在输入表接收新行时发送新结果

1.6 不同数据处理保证的语义

(1)At-most-once:出现故障时数据处理不保证任何语义,处理时延低

(2)At-least-once:保证每条数据均至少被处理一次,一条数据可能存在重复消费

(3)Exactly-once:最严格的处理语义,每条数据均被消费且仅消费一次

image.png

二、Exactly-Once 和 Checkpoint

2.1 状态恢复的时间点

需要等待所有处理逻辑消费完成source保留状态及以前的数据

2.2 快照制作算法

(1)暂停处理输入的数据

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

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

(4)恢复对输入数据的处理

2.3 Checkpoint对作业性能的影响

(1)解耦了快照制作和数据处理过程,各个算子制作完成状态快照后就可以正常处理数据,不用等下游算子制作完成快照 (2)在快照制作和Barrier Alignment过程中需要暂停处理数据,仍然会增加数据处理延迟 (3)快照保存到远端也有可能极为耗时。

三、Flink端到端的Exactly-once的语义

3.1 预提交阶段

1.协作组向所有参与者发送一个commit消息

2.每个参与的协作者收到消息后,执行事务,但是不真正提交

3.若事务成功执行完成,发送一个成功的消息(vote yes);执行失败,则发送一个失败的消息(vote no)

3.2 提交阶段

(1)若协作者成功接收到所有的参与者vote yes的消息:

步骤:1.协作者向所有参与者发送一个commit消息

     2.每个收到commit消息的参与者释放执行事务所需的资源,并介绍这次事务的执行
     
     3.完成步骤2后,参与者发送一个ack消息给协作组
     
     4.协作者收到所有参与者的ack消息后,标识该事务执行完成

(2)若协作者有收到参与者vote no的消息(或者生等待超时):

步骤:1.协作者向所有参与者发送一个rollback消息;
     2.每个收到rollback消息的参与者回滚事务的执行操作,并释放事务所占资源;
     3.完成步骤2后,参与者发送一个ack消息给协作者;
     4.协作者收到所有参与者的ack消息后,标识该事务成功完成回滚
     

四、个人总结和思考

总结:·数据流可以转换为动态表,动态表也能重新转换为数据流
     ·Flink两阶段提交的事务开启均在sink task 向下游写数据之前,会开启一个事务,后续所有写数据的操作均在这个事务中执行,事务未提交前事务写入的数据下游不可读
     ·Flink通过Checkpoint机制实现故障前后的状态快照制作和恢复
     
思考:Exactly Once语义是分布式系统中重要知识点,其中涉及到的技术点和设计思想值得我们投入更多时间去深入探究,结合所学的Flink引擎知识点进行对比和学习