轻量级异步屏障快照(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

相关文章

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?