大数据初识------Flink如何实现Exactly once计算不重不丢

Flink是使用Kafka链接计算任务,利用kafka的exactly once实现流计算的不重不丢,而Kafka 的 Exactly Once 语义是通过它的事务和生产幂等两个特性来共同实现的

1.流计算框架的架构及其计算原理

Flink是实时流计算框架,实时”,一个是说,数据是“实时”产生的,另一个是说,统计分析这个过程是“实时”进行的

无论是使用 Flink、Spark 还是其他的流计算框架,定义一个流计算的任务基本上都可以分为:定义输入、定义计算逻辑和定义输出三部分,通俗地说,也就是:数据从哪儿来,怎么计算,结果写到哪儿去,这三件事儿。

计算任务是如何在 Flink 中执行的呢?总体图如下:

这张图稍微有点儿复杂,我们先忽略细节看整体。Flink 的集群和其他分布式系统都是类似的,集群的大部分节点都是 TaskManager 节点,每个节点就是一个 Java 进程,负责执行计算任务。另外一种节点是 JobManager 节点,它负责管理和协调所有的计算节点和计算任务,同时,客户端和 Web 控制台也是通过 JobManager 来提交和管理每个计算任务的。

我们编写好计算任务的代码后,打包成 JAR 文件,然后通过 Flink 的客户端提交到 JobManager 上。计算任务被 Flink 解析后,会生成一个 Dataflow Graph,也叫 JobGraph,简称 DAG,这是一个有向无环图(DAG)

JobGraph 中的每个节点是一个 Task,Task 是可以并行执行的,每个线程就是一个 SubTask。SubTask 被 JobManager 分配给某个 TaskManager,在 TaskManager 进程中的一个线程中执行

2.实践:利用kafka实现内存计算和存储分离(HDF分布式文件系统)

流计算框架本身是个分布式系统,一般由多个节点组成一个集群。我们的计算任务在计算集群中运行的时候,会被拆分成多个子任务,这些子任务也是分布在集群的多个计算节点上的。

大部分流计算平台都会采用存储计算分离的设计,将计算任务的状态保存在 HDFS 等分布式存储系统中。每个子任务将状态分离出去之后,就变成了无状态的节点,如果某一个计算节点发生宕机,使用集群中任意一个节点都可以替代故障节点。

但是,对流计算来说,这里面还有一个问题没解决,就是在集群中流动的数据并没有被持久化,所以它们就有可能由于节点故障而丢失,怎么解决这个问题呢?办法也比较简单粗暴,就是直接重启整个计算任务,并且从数据源头向前回溯一些数据。计算任务重启之后,会重新分配计算节点,顺便就完成了故障迁移。

回溯数据源,可以保证数据不丢失,这和消息队列中,通过重发未成功的消息来保证数据不丢的方法是类似的。

Flink 集群本身也是一个分布式系统,它首先需要保证数据在 Flink 集群内部只被计算一次,只有在这个基础上,才谈得到端到端的 Exactly Once。

Flink 通过 CheckPoint 机制来定期保存计算任务的快照,这个快照中主要包含两个重要的数据:

整个计算任务的状态。这个状态主要是计算任务中,每个子任务在计算过程中需要保存的临时状态数据。比如,上节课例子中汇总了一半的数据。

数据源的位置信息。这个信息记录了在数据源的这个流中已经计算了哪些数据。如果数据源是 Kafka 的主题,这个位置信息就是 Kafka 主题中的消费位置。

Flink 通过在数据流中插入一个 Barrier(屏障)来确保 CheckPoint 中的位置和状态完全对应

小结

端到端 Exactly Once 语义,可以保证在分布式系统中,每条数据不多不少只被处理一次。在流计算中,因为数据重复会导致计算结果错误,所以 Exactly Once 在流计算场景中尤其重要。Kafka 和 Flink 都提供了保证 Exactly Once 的特性,配合使用可以实现端到端的 Exactly Once 语义。

在 Flink 中,如果节点出现故障,可以自动重启计算任务,重新分配计算节点来保证系统的可用性。配合 CheckPoint 机制,可以保证重启后任务的状态恢复到最后一次 CheckPoint,然后从 CheckPoint 中记录的恢复位置继续读取数据进行计算。Flink 通过一个巧妙的 Barrier 使 CheckPoint 中恢复位置和各节点状态完全对应。

Kafka 的 Exactly Once 语义是通过它的事务和生产幂等两个特性来共同实现的。在配合 Flink 的时候,每个 Flink 的 CheckPoint 对应一个 Kafka 事务,只要保证 CheckPoint 和 Kafka 事务同步提交就可以实现端到端的 Exactly Once,Flink 通过“二阶段提交”这个分布式事务的经典算法来保证 CheckPoint 和 Kafka 事务状态的一致性。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!