轻量级异步屏障快照(ABS)算法解析

2024-09-06 21:08

本文主要是介绍轻量级异步屏障快照(ABS)算法解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


大数据技术与架构

点击右侧关注,大数据开发领域最强公众号!

暴走大数据

点击右侧关注,暴走大数据!

在很久之前,笔者曾简单介绍了Chandy-Lamport分布式快照算法。而Flink的检查点过程正是依赖于Chandy-Lamport算法的“本地化”版本——异步屏障快照(asynchronous barrier snapshotting, ABS)算法。该算法由五位大佬(其中也包含Data Artisans的两位:Stephen Ewen与Kostas Tzoumas)通过论文《Lightweight Asynchronous Snapshots for Distributed Dataflows》提出。可以说,理解了ABS,就理解了Flink检查点背后的原理。本文来谈谈它。

Checkpoint & Snapshot

检查点是Flink为流计算过程提供的容错和故障恢复机制。当程序出错时,Flink会重启受到影响的那部分算子及计算逻辑,并将它们重置到最后一次成功checkpoint时的状态。每次成功的checkpoint产生的“状态数据”其实就是这个流式计算任务在那一时刻的快照。

Flink作业可以抽象成有向图表示,图的顶点是算子(operator),边是数据流(data stream),与C-L算法提出的“进程-链路”图模型恰好对应。直接套用C-L算法的思路,我们可以得出如下推论:

  • Flink作业的快照要包含两部分,即算子所处的状态以及数据流承载的数据。算子每收到/发出一条数据,以及数据流每流入/流出一条数据,都会造成全局状态改变。

  • 算子可以感知到自己的状态,但数据流的状态不容易记录,主要是因为承载的数据量太大。

  • 时间是无法静止的(即数据总是在流动的),并且快照不能stop-the-world,否则会造成延迟和数据堆积,降低吞吐量。

所以解决方案的要点有二:一是通过每个算子自己记录的状态合并出全局快照,二是引入一个标记把数据流从时域上切分成段。下面就可以了解ABS算法的基础——屏障。

Barrier

之前已经讲过,C-L算法引入了marker消息来作为快照的边界,即区分“当前快照的数据”和“下一个快照的数据”。ABS算法也有自己的marker消息,不过称为检查点屏障(checkpoint barrier),简称屏障。

屏障由Flink的JobManager周期性产生(周期长度由StreamExecutionEnvironment.enableCheckpointing()方法来指定),并广播给所有Source算子,沿着数据流流动下去。下图示出一条带有屏障的数据流。

可见,第n - 1个屏障之后、第n个屏障之前的所有数据都属于第n个检查点。下游算子如果检测到屏障的存在,就会触发快照动作,不必再关心时间无法静止的问题。下面继续了解快照阶段是如何执行的。

Snapshotting

仍然举例说明。下图是论文中给出的并行度为2的Word Count示例,注意该作业的执行计划为有向无环图(DAG)。

快照算法的步骤如下:

a) Source算子接收到JobManager产生的屏障,生成自己状态的快照(其中包含数据源对应的offset/position信息),并将屏障广播给下游所有数据流;

b)、c) 下游非Source的算子从它的某个输入数据流接收到屏障后,会阻塞这个输入流,继续接收其他输入流,直到所有输入流的屏障都到达(图中的count-2算子接收的两个屏障就不是同时到达的)。一旦算子收齐了所有屏障,它就会生成自己状态的快照,并继续将屏障广播给下游所有数据流;

d) 快照生成后,算子解除对输入流的阻塞,继续进行计算。Sink算子接收到屏障之后会向JobManager确认,所有Sink都确认收到屏障标记着这一周期checkpoint过程结束,快照成功。

可见,如果算子只有一个输入流的话,问题就比较简单,只需要在收到屏障之后立即做快照。但是如果有多个输入流,就必须要等待收到所有屏障才能做快照,以避免将检查点n与检查点n + 1的数据混淆。这个等待的过程就叫做对齐(alignment),图来自官方文档。注意算子内部有个输入缓冲区,用来在对齐期间缓存数据。


下图是从Flink系统的角度示出整个checkpoint流程里屏障的流动,以及快照数据向状态后端的写入。注意Source记录的offset值以及Sink收到所有屏障后的ack信号。

Exactly-Once vs At-Least-Once

上面讲到的屏障对齐过程是Flink Exactly-Once语义的基础,因为屏障对齐能够保证多输入流的算子正常处理不同checkpoint区间的数据,避免它们发生交叉,即不会有数据被处理两次。

但是对齐过程需要时间,有一些对延迟特别敏感的应用可能对准确性的要求没有那么高。所以Flink也允许在StreamExecutionEnvironment.enableCheckpointing()方法里指定At-Least-Once语义,会取消屏障对齐,即算子收到第一个输入的屏障之后不会阻塞。这样一来,部分属于检查点n + 1的数据也会包括进检查点n的数据里, 当恢复时,这部分数据就会被重复处理。

Asynchronous

“屏障”和“快照”都讲过了,“异步”呢?这个词实际上指的是快照数据写入的异步性:算子收齐屏障并触发快照之后,不会等待快照数据全部写入状态后端,而是一边后台写入,一边立刻继续处理数据流,并将屏障发送到下游,实现了最小化延迟。

当然,引入异步性之后,checkpoint成功的条件除了所有Sink都报告ack之外,还得加上一条:所有有状态的算子都报告ack,否则JobManager就无法确认异步写入到底完成没有。

DCG

ABS的精华讲完了。最后看论文中提到的特殊情况,即作业的执行计划是个有向有环图(DCG)。很显然这种情况会造成死锁,环内的算子就会无限等待收齐屏障。面对该问题,ABS算法会单独处理回边(back edge)——即从下游流回上游的数据流,因为回边的存在会导致我们无法单纯地通过每个算子的状态合并出全局快照。

思路如下图所示,重点在于回边终点的那个算子。当该算子的非回边输入流的屏障都到达之后,它会生成一个本地的快照备份,并于此同时开始记录回边流入的数据,直到再次从回边收到相同的屏障。这样就靠算子的状态记录了回边的状态,当从快照恢复时,能够将回边的数据重新放回数据流传输。

作者:LittleMagic
链接:https://www.jianshu.com/p/d5a452466375

欢迎点赞+收藏+转发朋友圈素质三连

文章不错?点个【在看】吧! ????

这篇关于轻量级异步屏障快照(ABS)算法解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143126

相关文章

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实