我的编程空间,编程开发者的网络收藏夹
学习永远不晚

解析Flink内核原理与实现核心抽象

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

解析Flink内核原理与实现核心抽象

Flink中设计了用户自定义函数体系(User Defined Function,UDF),开发人员实现业务逻辑就是开发UDF。

一、环境对象

StreamExecutionEnvironment是Flink应用开发时的概念,表示流计算作业的执行环境,是作业开发的入口、数据源接口、生成和转换DataStream的接口、数据Sink的接口、作业配置接口、作业启动执行的入口。

Environment是运行时作业级别的概念,从StreamExecutionEnvironment中的配置信息衍生而来。进入到Flink作业执行的时刻,作业需要的是相关的配置信息,如作业的名称、并行度、作业编号JobID、监控的Metric、容错的配置信息、IO等,用StreamExecutionRuntime对象就不适合了,很多API是不需要的,所以在Flink中抽象出了Environment作为运行时刻的上下文信息。

RuntimeContext是运行时Task实例级别的概念。Environment本身仍然是比较粗粒度作业级别的配置,对于每一个Task而言,其本身有更细节的配置信息,所以Flink又抽象了RuntimeContext,每一个Task实例有自己的RuntimeContext。

环境对象关系如下:

1.1 执行环境

StreamExecutionEnvironment

Flink流计算应用的执行环境,是Flink作业开发和启动执行的入口

开发者对StreamExecutionEnvironment的实现是无感知的。

LocalStreamEnvironment

本地执行环境,在单个JVM中使用多线程模拟Flink集群。

其基本的工作流程如下:

1) 执行Flink作业的Main函数生成Streamgraph,转化为JobGraph。

2) 设置任务运行的配置信息。

3) 根据配置信息启动对应的LocalFlinkMiniCluster。

4) 根据配置信息和miniCluster生成对应的MiniClusterClient。

5) 通过MiniClusterClient提交JobGraph 到MiniCluster。

RemoteStreamEnvironment

在大规模数据中心中部署的Flink生产集群的执行环境。

当将作业发布到Flink集群的时候,使用RemoteStreamEnvironment。

其基本的工作流程如下:

1) 执行Flink作业的Main函数生成Streamgraph,转化为JobGraph。

2) 设置任务运行的配置信息。

3) 提交JobGraph到远程的Flink集群。

StreamContextEnvironment

在Cli命令行或者单元测试时候会被使用,执行步骤同上。

StreamPlanEnvironment

在Flink Web UI管理界面中可视化展现Job的时候,专门用来生成执行计划(实际上就是StreamGraph)

ScalaShellStreamEnvironment

这是Scala Shell执行环境,可以在命令行中交互式开发Flink作业。

其基本工作流程如下:

  • 校验部署模式,目前Scala Shell仅支持attached模式。
  • 上传每个作业需要的Jar文件。

其余步骤与RemoteStreamEnvironment类似。

1.2 运行时环境

RuntimeEnvironment

在Task开始执行时进行初始化,把Task运行相关的信息都封装到该对象中,其中不光包含了配置信息,运行时的各种服务也会被包装到其中。

SavepointEnvironment

SavepointEnvironment是Environment的最小化实现,在状态处理器的API中使用。

1.3 运行时上下文

RuntimeContext是Function运行时的上下文,封装了Function运行时可能需要的所有信息,让Function在运行时能够获取到作业级别的信息,如并行度相关信息、Task名称、执行配置信息(ExecutionConfig)、State等。

Function的每个实例都有一个RuntimeContext对象,在RichFunction中通过getRunctionContext()可以访问该对象。

RuntimeContext的类体系图如下:

StreamingRuntimeContext:

在流计算UDF中使用的上下文,用来访问作业信息、状态等。

DistributedRuntimeUDFContext:

由运行时UDF所在的批处理算子创建,在DataSet批处理中使用。

RuntimeUDFContext:                                                          

在批处理应用的UDF中使用。

SavepointRuntimeContext:

支持对检查点和保存点进行操作,包括读取、变更、写入等。

CepRuntimeContext:

CEP复杂事件处理中使用的上下文。

二、数据流元素

数据流元素在Flink中叫做StreamElement

  • 有数据记录StreamRecord,
  • 延迟标记LatencyMarker、Watermark、
  • 流状态标记StreamStatus这四种。

在执行层面,4种数据流元素都被序列化成二进制数据,形成混合的数据流,在算子中将混合数据流中的数据流元素反序列化出来。

StreamRecord

StreamRecord表示数据流中的一条记录(或者叫做一个事件),也叫数据记录。

包含以下内容:

1)数据的值本身

2)时间戳(可选)

LatencyMarker

用来近似评估延迟,LatencyMarker在Source中创建,并向下游发送,绕过业务处理逻辑,在Sink节点中使用LatencyMarker估计数据在整个DAG图中的流转花费的时间。

LatencyMarker包含信息如下:

1)周期性的在数据源算子中创造出来的时间戳。

2)算子编号

3)数据源算子所在的Task编号

Watermark

是一个时间戳,用来告诉算子所有时间早于等于Watermark的事件或记录都已经达到,不会再有比Watermark更早的记录。

StreamStatus

用来通知Task是否会继续接收到上游的记录或者Watermark。在数据源算子中生成,向下游沿着DataFlow传递。

有两种表示状态:

1)空闲状态(IDLE)

2)活动状态(ACTIVE)

三、数据转换

数据转换在Flink中叫做Transformation,是衔接DataStream Api和Flink内核的逻辑结构。

Transformation有两大类:

1)物理Transformation: 会转换成算子,继承了PhysicalTransformation。

2)虚拟Transformation: 不会转换成具体算子。

Tranformation包含了Flink的运行时关键参数:

1)name:转换器名称,主要用于可视化。

2)uid:用户指定的uid,该uid的主要目的是在job重启时再次分配跟之前相同的uid,可以持久保存状态。

3)bufferTimeout:buffer超时时间。

4)parallelism:并行度。

5)id:跟属性uid无关,生成方式是基于一个静态累加器。

6)outputType:输出类型,用来进行序列化数据。

7)slotSharingGroup:给当前的Transformation设置Slot共享组。

3.1 物理Transformation SourceTransformation

从数据源读取数据的Transformation,是Flink作业的起点。

只有下游Transformation,没有上游输入。

SinkTransformation

将数据写到外部存储的Transformation,是Flink作业的终点。

OneInputTransformation

单流输入的Transformation(只接收一个输入流),跟上面的SinkTransformation构造器类似,同样需要input和operator参数。

TwoInputTransformation

双输入的Transformation(接收两种流作为输入),分别叫做第一输入和第二输入。

3.2 虚拟Transformation SideOutputTransformation

在旁路输出中转换而来,表示上游Transformation的一个分流。

每个sideoutput通过OutputTag标识。

SplitTransformation

用来按条件切分数据流,该转换用于将一个流拆分成多个流。

SelectTransformation

与SplitTransformation配合使用,用来在下游选择SplitTransformation切分的数据流。

PartitionTransformation

该转换器用于改变输入元素的分区,其名称为Partition。工作时除了提供一个StreamTransformation作为输入外,还需要提供一个StreamPartitionor的实例来进行分区。

UnionTransformation

合并转换器,该转换器用于将多个输入StreamTransformation进行合并,因此该转换器接收StreamTransformation的集合。Union要求上游输入的数据的结构必须是完全相同的。

FeedbackTransformation

表示FlinkDAG中的一个反馈点。简单来说,就是把符合条件的数据发回上游Transformation处理,一个反馈点可以连接一个或多个上游的Transformation,这些连接关系叫反馈边。符合反馈条件并交给上游的Transformation的数据流叫做反馈流。

FeedbackTransformation的固定名称为Feedback

有两个重要参数:

  • input:上游输入StreamTransformation
  • waitTime:默认为0,即永远等待,如果设置了等待时间,一旦超过该等待时间,则计算结束并且不再接收数据。

实例化FeedbackTransformation时,会自动创建一个用于存储反馈边的集合feedbackEdges。

FeedbackTransformation通过定义一个实力方法addFeedbackEdge来收集,

在加入的StreamTransformation的实例有一个要求,

当前FeedbackTransformation跟待加入的StreamTransformation并行度一致。

CoFeedbackTransformation

与FeedbackTransformation类似,也是FlinkDAG中的一个反馈点。

  • 不同之处在于,CoFeedbackTransformation反馈给上游的数据流与上游Transformation的输入类型不同
  • 所以要求上游的Transformation必须是TwoInputTransformation。

四、算子行为

 4.1 生命周期管理

1)setup:初始化环境、时间服务、注册监控等。

2)open:该行为由各个具体的算子负责实现,包含了算子的初始化逻辑。

3)close:所有的数据处理完毕之后关闭算子,此时需要去报将所有的缓存数据向下游发送。

4)dispose:该方法在算子生命周期的最后执行阶段,此时算子已经关闭,停止处理数据,进行资源的释放。

StreamTask作为算子的容器,负责管理算子的生命周期。

4.2 异步算子

异步算子的目的是解决与外部系统交互时网络延迟所导致的系统瓶颈问题。

异步算子的两种输出模式

1)顺序输出

先收到的数据先输出,后续数据元素的异步函数调用无论是否先完成,都需要等待,顺序模式可以保证消息不乱序,但是可能增加延迟,降低算子的吞吐量。

2)无序输出

先处理完的数据元素先输出,不保证消息顺序,相比于顺序模式,无序输出模式算子延迟低、吞吐量高。无序输出模式并不是完全无序的,仍然要保持Watermark不能超越其前面数据元素的原则。等待完成队列将按照Watermakr切分成组,组内可以无序输出,组之间必须严格保证顺序。

五、处理函数

5.1 双流Join 即时Join

逻辑如下:

1) 创建一个State对象

2)接收到输入流 1事件后更新Sate。

3)接收到输出流 2的事件后遍历State,根据Join条件进行匹配,将匹配结果发送到下游。

5.2延迟双流Join

在流式数据里,数据可能是乱序的,数据会延迟到达,并且为了提供处理效率,使用小批量模式计算,而不是每个事件触发一次Join计算。

逻辑如下:

1)创建2个state对象,分别缓存输入流1和输入流2的事件。

2)创建一个定时器,等待数据的到达,定时延迟触发Join计算。

3)接收到输入流1事件后更新State。

4)接收到输入流2事件后更新State。

5)定时器遍历State1和State2,根据Join条件进行匹配,将匹配结果发送到下游。

六、数据分区

数据分区在Flink中叫做Partition。

本质上说,分布式计算就是把一个作业切分成子任务Task,将不同的数据交给不同的Task计算。

StreamParitioner

是Flink中的数据流分区抽象接口,决定了在实际运行中的数据流分发模式。

自定义分区

使用用户自定义分区函数,为每一个元组选择目标分区。

ForwardParitioner

用于在同一个OperatorChain中上下游算子之间的数据转发, 实际上数据是直接传递给下游的。

ShufflePartitioner

随机将元素进行分区,可以确保下游的Task能够均匀的获取数据。

ReblancePartitioner

以Round-robin的方式为每个元素分配分区,确保下游的Task可以均匀的获取数据,以免数据倾斜。

RescalingPartitioner

根据上下游Task的数据进行分区。

使用Round-robin选择下游的一个Task进行数据分区,

如上游有2个Source,下游有6个Map,那么每个Source会分配3个固定下游的map,

不会向未分配给自己的分区写入数据。

BroadcastPartitioner

将该记录广播给所有分区,即有N个分区,就把数据复制N份,每个分区1分

KeyGroupStreamPartitioner

keyedStream根据KeyGroup索引编号进行分区,该分区器不是提供给用户来用。

KeyedStream在构造Transformation的时候默认使用KeyedGroup分区形式,从而在底层上支持作业Rescale功能。

七、分布式ID

到此这篇关于解析Flink内核原理与实现核心抽象的文章就介绍到这了,更多相关Flink内核原理核心抽象内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

解析Flink内核原理与实现核心抽象

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

PHP核心的运行机制与实现原理详解

PHP是一种流行的开源服务器端脚本语言,大量被用于Web开发。它能够处理动态数据以及控制HTML的输出,但是,如何实现这一切?那么,本文将会介绍PHP的核心运行机制和实现原理,并利用具体的代码示例,进一步说明其运行过程。PHP源码解读PHP
PHP核心的运行机制与实现原理详解
2023-11-08

深入理解PHP trait DTO的实现原理与核心逻辑

引言:在PHP编程中,对象的数据传输对象(Data Transfer Object)在实际开发中起到了非常重要的作用。特别是在复杂的应用中,数据传输对象可以简化代码结构、提高代码可读性和可维护性。本文将深入探讨PHP中使用trait来实现数
2023-10-21

简易vuex4核心原理及实现源码分析

这篇文章主要为大家介绍了简易vuex4核心原理及实现源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-12

如何理解golang里面的读写锁实现与核心原理

如何理解golang里面的读写锁实现与核心原理,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。基础筑基读写锁的特点读写锁区别与互斥锁的主要区别就是读锁之间是共享的
2023-06-19

理解Go语言内存优化的核心原则与方法

Go语言内存优化的核心原则是尽量减少内存的分配和释放操作,以减少垃圾回收的压力和提高程序性能。以下是一些常见的方法和技巧:1. 使用指针和引用:Go语言中,使用指针可以减少内存的复制操作,使用引用可以减少内存的分配操作。尽量使用指针传递参数
2023-10-08

C++多态的实现与原理及抽象类实例分析

这篇文章主要讲解了“C++多态的实现与原理及抽象类实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++多态的实现与原理及抽象类实例分析”吧!多态的概念多态: 从字面意思来看,就是事物
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录