大数据开发:Flink如何设计容错

基于分布式构建的大数据系统平台,容错性是一个重要的指标,尤其是在数据规模越来越大,数据格式也越来越复杂的背景下,容错机制的设计,是非常关键的。前面我们讲了Hadoop和spark的容错设计,今天的大数据开发学习分享,我们继续来讲Flink又是如何设计容错的?

Flink的容错机制——通过Barrier实现一致性语义

官方文档是这样描述Flink的:

Stateful Computations over Data Streams

即,在数据流上的状态计算。可以说,状态计算(包括状态管理、检查点机制等)是它最大的特点之一。

Flink状态容错机制的设计原理

从单机程序开始

现在跳出Flink框架,设想一个运行在单个节点的进程,该如何设计容错机制。

比较容易想到的一个思路是,在主线程外另开启一个线程执行定时任务,定期地将状态数据刷写到磁盘。当作业停止后重启,则可以直接从之前刷写到磁盘的数据恢复。如下图所示:

分布式容错

延续这个思路,是否可以设计一个分布式的容错机制呢?下图是一个多节点的分布式任务,数据流从左至右。

如果给这些Task分别开启一个线程运行定时任务,这些分布在不同物理机上的任务的确也可以做到状态的存储和恢复。然而,这种粗暴的处理方式极容易发生业务上的异常。比如,当最左边的Task处理完了a、b、c这三条数据后,将数据发送至网络,在这三条数据还未到达中间的Task时,三个线程同时(假设时间同步非常理想)触发了状态存储的动作。这时左边的Task保存的状态是处理完a、b、c后的状态,而后两个Task保存的是未处理这三条数据时的状态。此时整个集群宕机,三个Task恢复后,左边的Task将从a、b、c这三条数据后的数据开始读取和处理,而后面的Task将永远无法接收到这三条数据。这就造成了数据的丢失。如果三个机器线程的触发时间不同步,也可能会造成数据重复处理。

这个问题在流处理中被称为“一致性语义”问题。当一条数据在计算引擎中被处理“至少一次”、“恰好一次”、“最多一次”时,一致性语义分别是“at least once”、“exactly once”、“at most once”。

不同的业务场景对于一致性语义有着不同的要求。举例来说,一个广告投放平台按照用户对广告的点击量进行收费,如果点击量被少算,则对平台方不利,如果点击量被多算,则对广告商不利,无论哪种情况都不利于长期合作。在这种情况下,“exactly once”语义就显得尤为重要。

基于Flink的计算模型与数据传输方式的设计,容错机制由Barrier来实现。Barrier可以理解为一条数据,被周期性地插入到数据流当中,跟随数据一起被传输到下游。

此时,每个任务将不再需要另启一个线程完成定时任务,只需要在接收到Barrier时触发存储状态的动作即可。由于数据传输的有序性,这样的机制可以保证“exactly once”语义。

为什么这里说“可以”保证“exactly once”语义,而没有说“必然”保证该语义呢?这是因为作业的拓扑图可能更加复杂,如下图所示:

如果一个进程的上游有多条数据流,那么它应该在接受到哪个Barrier时触发状态存储操作呢?

以上图为例,当最右边的进程接收到下面的数据流传来的Barrier时,它可以先不触发任何操作,该数据流后面的数据也暂时不做处理,而是将这些数据接收到缓存中。上面的数据流照常处理。当接收到了上面的数据流传来的Barrier时,再触发状态存储操作。这样仍可以保证“exactly once”语义。

很显然,在了解了这个原理后,就可以在这个过程中可以添加任何自己业务需要的策略。如可以不让Barrier对齐就触发操作,或是每条Barrier都触发一次操作,甚至可以将部分数据丢弃,等待最后一个Barrier到来时触发操作……这些不同的策略对应了不同的一致性语义。Flink实现了“exactly once”语义和“at least once”语义。

关于大数据开发,Flink如何设计容错,以上就为大家做了基本的介绍了。在大数据技术生态当中,Flink在流处理场景下,越来越受到重视,而流处理场景下的容错机制,也值得去深入理解。

你可能感兴趣的:(大数据开发:Flink如何设计容错)