这是我参与「第四届青训营 」笔记创作活动的第4天
结束 《Exactly Once 语义在 Flink 中的实现》课程后对实现Exactly Once的思考,第一次写这么长的文章
数据流和动态表的转换
首先动态表是随时间不断变化的表,在任意时刻,可以像查询静态批处理表一样查询它们
实时流查询特点是: 查询从不终止; 查询结果会不断更新,并且会产生一个新的动态表; 结果的动态表也可转换成输出的实时流
所以流数据先转换成动态表,然后进行连续查询在查询完成后在由动态变转换成流数据输出
Exactly-Once 和 Checkpoint
Exactly-once:每条数据都被消费且仅被消费一次,仿佛故障从未发生
Checkpoint 实现 Exactly-once:状态的快照备份与恢复
这是一个流数据,有三个算子,Source是读,另外2个 sum-even是计算偶数和,sum-odd是式计算奇数和。
此时我们在读到5时进行快照,对三个算子进行远端存储这样在我们遇到故障恢复时比如我们在读到7时遇到故障了我们进行恢复,从最近的备份时间点恢复,source依然然是5,sum-even是6,sum-odd是9,来达到快照恢复继续开始算子的工作。
但是有一点值得提到,我们是任意时间都可以进行快照备份吗?
显然不是的,因为如果我们在读到5的时候,但是sum-odd还没有进行计算,此时是 1+3 = 4,那么我们在状态恢复时sum-odd是4.但是我们读到5时认为已经计算过来这样就直接读6了,这显然是不对的。
所以这样就有一个方案就是我们在进行快照时暂停处理输入的数据,等待后续所有处理算子消费当前已经输入的数据,待2处理完后,作业所有算子复制自己的状态并保存到远端可靠存储,恢复对输入数据的处理。但是这样也有一个缺点就是需要等待后续所有处理算子消费当前已经输入的数据才能继续工作,这样效率就降低了。 Checkpoint能保证每条数据都对各个有状态的算子更新一次,sink输出算子仍然可能下发重复的数据。
Chandy - Lamport算法解决
每一个 source算子都接收到JM发送的 Checkpoint Barrier标识状态快照制作的开始,各个source保存自己状态后,向所有连接的下游继续发送Checkpoint Barrier,同时告知JM自己状态已经制作完成。
算子会等待所有上游的barrier到达后才开始快照的制作;已经制作完成的上游算子会继续处理数据,并不会被下游算子制作快照的过程阻塞。
优点就是解耦了快照制作和数据处理过程,各个算子制作完成状态快照后就可以正常处理数据,不用等下游算子制作制作完成快照。
端到端的Exactly-once
两阶段提交协议
在多个节点参与执行的分布式系统中,为了协调每个节点都能同时执行或者回滚某个事务性的操作,引入了一个中心节点来统一处理所有节点的执行逻辑,这个中心节点叫做协作者(coordinator) ,被中心节点调度的其他业务节点叫做参与者(oarticinant )
协作者向所有参与者发送一个 commit消息,每个参与的协作者收到消息后,执行事务,但是不真正提交, 若事务成功执行完成,发送一个成功的消息(vote yes) ,执行失败,则发送一个失败的消息(vote no)。
2个场景
场景一 若协作者成功接收到所有的参与者vote yes的消息:
协作者向所有参与者发送一个commit消息;每个收到commit消息的参与者释放执行事务所需的资源,并结束这次事务的执行;完成步骤2后,参与者发送一个ack消息给协作者;协作者收到所有参与者的ack消息后,标识该事务执行完成。
场景二 若协作者有收到参与者vote no的消息(或者发生等待超时):
协作者向所有参与者发送一个rollback 消息;每个收到rollback消息的参与者回滚事务的执行操作,并释放事务所占资源;完成步骤2后,参与者发送一个ack 消息给协作者;协作者收到所有参与者的ack消息后,标识该事务成功完成回滚。
提交总结
事务开启:在sink task向下游写数据之前,均会开启一个事务,后续所有写数据的操作均在这个事务中执行,事务未提交前,事务写入的数据下游不可读;
预提交阶段:JobManager开始下发Checkpoint Barrier,当各个处理逻辑接收到barrier后停止处理后续数据,对当前状态制作快照,此时sink 也不在当前事务下继续处理数据(处理后续的数据需要新打开下一个事务)。状态制作成功则向JM成功的消息,失败则发送失败的消息;
提交阶段:若JM收到所有预提交成功的消息,则向所有处理逻辑(包括sink)发送可以提交此次事务的消息,sink接收到此消息后,则完成此次事务的提交,此时下游可以读到这次事务写入的数据;若JM有收到预提交失败的消息,则通知所有处理逻辑回滚这次事务的操作,此时sink 则丢弃这次事务提交的数据下。