这是我参与「第四届青训营 」笔记创作活动的第2天
1. 如何在数据流上执行SQL语句并说明流式处理中状态的概念
2. 发生故障时,Flink自身如何从故障中恢复并保证对数据消费不丢不重
3. Flink本身的checkpoint机制如何和外部存储结合,实现端到端的不丢不重
数据流和动态表
数据流→动态表→连续查询→动态表→数据流
1. 数据流转化为动态表
下图为事件流转化为动态表的示例:
Retract消息(回撤消息),先回撤记录再输入新信息,进行更新。(新的流)
2. 动态表经连续查询形成新的动态表
连续查询的工作不会停止,查询结果也会不断更新,并产生新的动态表
3. retract消息
上图的结果表的changelog流包含insert和delete操作。具体如下图:
其中的delete操作就被称为retract(回溯)消息。而这个changelog流就是retract流。
另:changel流指的是包含INSERT/UPDATE/DELETE等的数据流。
· Append-only 流(只有 INSERT 消息)
· Retract 流(同时包含 INSERT 消息和 DELETE 消息)
· Upsert 流(同时包含 UPSERT 消息和 DELETE 消息)
查询过程中的一个概念:状态,保证之前的数据在之前的基础(状态)上进行更新。
4.数据处理保证
At-most-once:出现超时和错误时不会重试(不纠错)。处理时延低。
At-least-once:出现超时和错误时进行重试(比如重新处理、再次产生结果)。可能由于反馈失效而导致多次输入。
Exactly-once:即使重试发送消息,消息也会保证最多一次地传递给最终consumer。该语义是最理想的,但也难以实现,因为它需要消息系统本身与生产和消费消息的应用程序进行协作。
Exactly-Once和checkpoint
快照:指的是某瞬间的状态记录。
一般最简单的快照制作和使用:暂停处理数据,但需要等待后续的算子处理已输入的数据,再把每个算子的状态保存到远端存储。完成后再恢复数据处理。
其中的缺点:1.在大数据场景下,暂停等待下游数据处理后再存储,代价是巨大的。
Chandy-Lamport算法
开始制作快照,checkpoint注入
每个source算子都接受到JM发送的Checkpoint Barrier,表示状态快照制作的开始。
checkpoint开始传递
Source保存自己状态(到远端)后,向所有连接的下游传递Checkpoint Brrier,并告知JM自己状态已经制作完成。
多个source的checkpoint传递
Source不止一个,因此同时输入的barrier经过source处理后进行传递会产生“副本barrier”,需要将“副本barrier”和实际流程中的barrier进行对齐,即“barrier alignment”。
算子会等待上游的barrier到达后才开始制造快照(对齐)。
已经制作完成的上游算子会继续处理数据,不会像“简单快照制作”那样因等待下游而阻塞。
实现了快照制作和处理数据的解耦。
当所有算子都告知JM状态制作(快照)完成后,checkpoint就结束了。
影响:
1.事实上实现了快照制作和处理数据的解耦。已经制作完成的上游算子会继续处理数据,不会像“简单快照制作”那样因等待下游而阻塞。
2.在快照制作和BarrierAlignment过程中会因对齐需要而暂停处理数据,依旧有一定延迟。
3.快照保存到远端也可能极为耗时。
端到端的Exactly-Once语义(与外部存储结合)
Checkpoint能保证每条数据都对个个有状态的算子更新一次,但sink输出算子仍然可能下发重复数据。(at least once)
因此需要特殊的sink算子实现端到端Exactly-once。
通过两阶段提交协议实现端到端Exactly-once。
两阶段提交协议,分为预提交阶段和提交阶段。在多个节点参与执行的分布式系统中,为了协调每个节点都能同时执行或回滚操作,引入了中心节点统一协调所有节点的执行逻辑。
此中心节点称为“协作者”,被中心点调度的其他节点称为“参与者”。
预提交阶段:
1. 协作者向所有参与者发送commit消息
2. 每个参与者收到消息后,执行事务,但不真正提交
3. 若事务执行完成,发送“vote yes”,执行失败,则发送”vote no”
提交阶段:
【若协作者成功接收到所有的vote yes】
1.协作者向所有参与者发送commit消息
2.每个收到commit的参与者释放执行事务所需的资源,并结束执行
3.参与者发送ack给协作者
4.协作者收到参与者的所有ack后,标识该事务执行完成。
【若协作者接收到有vote no的消息或超时】
1.协作者向所有参与者发送rollback消息
2.每个收到rollback的参与者回滚事务的执行操作,并释放执行事务所需的资源
3.参与者发送ack给协作者
4.协作者收到参与者的所有ack后,标识该事务完成回滚。
事物开启:在sink task向下游写数据前,开启一个事物,后续所有写数据的操作均在这个事务中执行,事物未提交前,事物写入的数据下游不可读。
预提交阶段:JM下发checkpoint barrier,当处理逻辑接收到barrier后停止处理后续数据,对当前状态制作快照,此时sink也不再当前事物下继续处理数据。状态(快照)制作成功则向JM发送成功的消息,失败则发送失败的消息。(即做备份)
提交阶段:若JM收到所有预提交成功的消息,则向所有处理逻辑发送可以提交此次事物的信息,sink接收到此消息后完成此次事物的提交,此时下游可以读到这次事物写入的数据;若JM有收到预提交失败的信息,则通知所有处理逻辑回滚这次的实务操作,此时sink丢弃提交的数据。(备份之后,可以继续往下运行,交与kafka(commit))
优势
1.严格意义上的端到端的Exactly-Once语义:下游读到的数据是不丢不重的。
2.增强的去重能力:可以在更长的时间维度对数据进行去重。