端到端exactly-once(翻译官方)

1 概述

在Flink1.4.0中,发布了一个叫做TwoPhaseCommitSinkFunction的特性,该逻辑抽取两阶段提交协议常规逻辑,使得可以构建端到端的exactly-once语义,需要Kafka0.11以上。 本文余下部分主要讲述:

  • 描述Flink的checkpoint机制如何保证只处理一次语义

  • 描述Flink如何通过两阶段提交协议来达到端到端只处理一次语义

  • 通过一个简单例子来描述如何使用TwoPhaseCommitSinkFunction来完成到文件的只处理一次语义

2 端到端只处理一次实现

当我们说只处理一次语义时,意味着每个记录只影响结果一次,即使在发现机器或者软件故障是,都不会出现丢失以及重复处理。

实现该语义需要以flink本身的checkpoint机制为基础,这里简要进行下总结,一个应用的checkpoint由如下快照信息组成:

  • 当前应用的状态

  • 输入流的位置

Flink定时生成checkpoint,同时将checkpoint写入到持久化系统中。在写入过程中是异步的,意味着Flink在这个阶段继续处理数据。

为了提供端到端只处理一次语义,外部系统必须要提供方法来与flink本身的checkpoints机制结合,一种常用的协调提交以及回滚的方式是两阶段提交协议,接下来将具体分析下内部实现逻辑来达到端到端只处理一次语义。

由于在kafka0.11以上提供了事务处理,所以使得flink可以提供该机制,当前支持所有支持事务的源,本例中使用从kafka读取数据然后集合再输出到kafka中,如下图。

image

为了保证只处理一次,需要在一个事务中完成数据写入kafka中,这样才能在失败时进行回滚。

然而,在分布式系统中,存在多个并行运行的sink task,一个简单的提交或者回滚是不行的,因为需要所有模块都一起提高或者回滚才能保证结果一致性,flink中使用两阶段提交协议中的预提交(pre-commit)来实现该功能。

在checkpoint启动时是两阶段提交协议的预提交阶段,当checkpoint启动,flink的jobmanager会注入一个栏栅消息(用于分隔当次checkpoint以及下一次checkpoint)。

栏栅消息在各个操作中传输,对于每一个操作,它都会出发操作进行状态快照。

image

data source存储了kafka的offsets,当其完成后,将栏栅消息传给下一个操作。该情况下每个操作都是存储内部状态,不需要进行额外的操作,本身的checkpoint机制就可以满足。

image

当有外部一些操作时,在pre-commit时就需要外部来保证状态的存储。

image

当在预提交阶段完成了所有操作的snapshot(栏栅消息从source传到了sink),这时候状态包括了完成的状态,接下来时两阶段的提交阶段,jobmanager会通知各个操作快照结束并进行提交,由于除sink是存在外部状态的,其他都是内部状态,故而只需要提交sink的事务。

image
  • 通过上图可以看出在所有操作完成了预提交时,才会进行提交

  • 在预提交阶段只要有一个失败,则回滚到上一次完成的checkpont

  • 在提交阶段的成功与否由外部系统来保证

3 checkpoint

进行快照后包含如下内容:

  • 对于每一个并行的source,快照存储的是offset、position等信息

  • 对于每一个操作,有一个指针指向快照存储

References

1.http://flink.apache.org/features/2018/03/01/end-to-end-exactly-once-apache-flink.html

你可能感兴趣的:(端到端exactly-once(翻译官方))