Exactly Once | 青训营笔记

87 阅读3分钟

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

本节介绍了Exactly Once 语义在Flink中的实现,从数据流和动态表引入,介绍Exactly Once在特定场景下的必要性。对比其他算法,给出Flink Exactly-once的处理逻辑

一、数据流和动态表

stream->Dynamic Table->Continuous Query->Dynamic Table->stream

流和表可以相互转换。

流转换为动态表,动态表通过连续查询变为动态表。

不同数据处理的语义:

At-most-once:出现故障不做反应,处理时延低。

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

Exactly-once:最严格的语义,每条数据均被消费且仅消费一次。

二、Exactly-once和Checkpoint

处理无限数据流的算子可以是有状态的。

简单的快照制作:

暂停数据,需要等待Source进入算子消费的所有已输入的数据,否则恢复的时候该数据会丢失。

Chandy-Lamport算法:

每个source算子收到JM发送的Checkpoint Barrier表示状态快照的开始。source保存自己的状态后,向所有连接的下游发送Checkpoint Barrier,告知JM自己的状态制作完成,继续处理自己的数据。算子会等待所有上游barrier达到开始制作快照。

缺点:快照制作和Barrier Alignment过程需要暂停处理数据,会增加延迟;快照保存到远端有可能极为耗时。

三、端到端的Exactly-once语义

Checkpoint保证每条数据都对各个有状态的算子更新一次,sink输出算子可能下发重复数据。

两阶段提交协议:

分布式协议,引入一个中心节点统一处理所有节点的执行逻辑,为了每个节点能同时执行或回滚某个事务性操作,中心节点为协作者,被调度的其他业务节点叫参与者。

1.事务开启:

在sink task向下游写数据之前,均会开启一个事务,后续所有写操作均在这个事务中执行,事务未提交前,事务写入的数据下游不可读。

2.预提交阶段:

协作者向所有参与者发送一个commit消息,参与者收到消息,执行事务但不真正提交。事务执行成功与否需要发送消息。

3.提交阶段:

协作者向所有参与者发送一个commit消息,收到commit消息的参与者释放执行事务的所有资源,并向协作者发送ACK。

协作者收到vote no或等待超时时,协作者向所有参与者发送一个rollback消息,sink丢弃这次事务提交的数据。

Flink中JM为协作者,其他节点为参与者。

四、总结

1.在银行等对数据准确性要求高的领域,Exactly Once能保持数据的一致性和完整性。

2.Flink中的Exactly Once还有进一步完善的空间。