Flink
- 一、介绍
- 二、安装部署
- 三、运行架构
- 1. 运行时的组件
- 2. Flink任务提交流程
- 3. 任务调度原理
- 4. TaskManager(TM)和Slots
- 5. DataFlow
- 6. ExecutionGraph
- 7. Parallelism(数据并行范围)
- 8. Operator Chains(任务链)
一、介绍
Apache Flink(德语:快速灵巧,原德国柏林大学基金会项目)是一个框架和分布式处理引擎,用于对无界和有界数据流进行状态计算。ms级别水平。data flow event sequence。
流数据更真实地反映了我们的生活方式,传统数据架构是基于有限数据集的离线处理。
- 目标: 低延迟、高吞吐、结果的准确顶和良好的容错性。
- 应用场景: 电商和市场营销,数据报表、广告投放、业务流程需要; 物联网(everything has id and creates data),传感器实时数据采集和显示、实时报警、交通运输业; 电信业,基站流量调配; 银行和金融业,实时结算和通知推送、实时监测异常行为。
- 数据架构 (1)传统架构 联机事务处理过程(OLTP)
联机分析处理过程(OLAP):将数据从业务数据ETL(Extract-Transform-Load,抽取-转换-加载)到数仓,再进行分析和查询。
(2)流式处理 有状态的流式处理 data pipe line,借鉴了事务处理模式,本地状态提速(周期性检查表存储至远程)。 缺点:分布式延迟会导致乱序问题。
Lambda架构 用两套系统(批处理,保证结果正确性 流处理,实时计算结果),同时保证延迟和结果准确(校验结果)。 缺点:重复造轮子,维护。
Flink架构 Spark Streaming将批处理的批次分的足够小,基于批处理引擎的流计算(micro-batching)。
- 主要特点 1.事件驱动(Event-driven):data pipe的一部分,根据本地状态快速响应
2.基于流:离线数据是有界的流,实时数据是无界流 3.分层API:SQL/Table API(dynamic tables)、DataStream API(streams、windows)、ProcessFunction API(events、state、time) 4.支持事件时间(event-time)和处理时间(processing-time)语义;精确一次(exactly-one)的状态一致性保证;低延迟,ms级,每秒处理百万个事件;存储系统连接广;高可用,动态扩展,实现7*24小时。
二、安装部署
三种方式:Standalone模式、Yarn模式(必须hadoop支持版本且有HDFS)、Kubernetes部署(容器化部署) 下载地址
master配置jobmanager,slaves配置taskmanager(干活的)。配置的rest.port: 8081
为可视化UI端口。H
每个算子都可以单独设置并行度setParallelism(),默认并行度自行设置。
taskmanager.numberOfTaskSlots: 1 为每个Flink TaskManager在集群中提供处理槽, 插槽的数量通常与每个TaskManager的可用CPU内核数成比例
命令行提交job:
代码语言:javascript复制./bin/start-cluster.sh
./bin/flink run -c ${class-path} -p ${parallelism-number} ${jar-path} ${parameters}
./bin/flink list # 可以加--all
./bin/flink cancel ${job-id}
./bin/stop-cluster.sh
三、运行架构
1. 运行时的组件
组件:作业管理器(Job Manager)、任务管理器(Task Manager)、资源管理器(Resource Manager)、分发器(Dispacher)
(1)Job Manager 控制一个应用程序执行的主进程,即一个应用程序对应一个Job Manager。 Job Manager会接受的应用程序包括:作业图(Job Graph)、逻辑数据流图、打包了所有的类/库/其他资源的JAR包。Job Manager会把Job Graph转换成一个物理层面的数据流图,称为执行图(Execution Graph),包含所有可以并发执行的任务。 Job Manager会向Resource Manager请求执行任务必要的资源(Task Manager上的Slot),将Execution Graph分发到真正运行它们的Task Manager上。 运行过程中Job Manager会负责所有需要中央协调的操作,如检查点(Check Points)的协调。
(2)Task Manager Flink中的工作进程,每个Task Manager包含一定数量的插槽(Slots,线程运行的资源),插槽限制了Task Manager能够执行的任务数量。 启动后,Task Manager会向Resource Manager注册它的插槽。收到Resource Manager的指令后,Task Manager会将一个或多个插槽提供给Job Manager分配任务来执行调用。 执行过程中,一个Task Manager可以喝其他运行同一应用程序的Task Manager交换数据(分布式集群)。
(3)Resource Manager 主要负责管理Task Manager的Slot,Slot是Flink中定义的处理资源单元。Flink为不同的环境和资源管理器工具提供了不同的Resource Manager(Yarn、k8s)。
(4)Dispacher 非必需,可跨作业运行,为应用提供了REST接口。当一个应用被提交执行时,Dispacher会启动并将应用交给一个Job Manager。Dispatcher也会启动一个Web UI。
2. Flink任务提交流程
YARN和K8S有所不同。
3. 任务调度原理
执行:Flink程序首先生产一个Dataflow Graph(DG),通过Client将Task(DG和Code)提交到JM(通过Dispatcher)。JM接收到Task之后,将DG转换成Execution Graph发送给TM,对应的Task就可以在每个Slot上执行了。
4. TaskManager(TM)和Slots
Flink中每一个TM都是一个JVM进程,会在独立的线程上执行一个或多个subtask。为了控制一个TM能接收多个task,TM通过task slot来进行控制。
Slots是静态的概念,指TM具有的并发执行的能力。用来隔离内存,一般根据CPU核心数量来设定。 默认情况下,Flink允许子任务共享Slot,即使是不同任务的子任务,即一个Slot可以保存作业的整个管道。
5. DataFlow
Flink程序都是由三部分组成:Source(读取数据源)、Transformation(数据处理转换)、Sink(数据输出)。 运行时,Flink上运行的程序会被映射成DataFlow(逻辑数据流),一个DataFlow以一个或多个Source开始,以一个或多个Sink结束,程序中的转换运算(Transformations)跟DataFlow中的算子(operator)一一对应,类似于任意的有向无环图(DAG)。
6. ExecutionGraph
Flink中的执行图可以分成四层:StreamGraph->JobGraph->ExecutionGraph->物理执行图。 StreamGraph:根据用户通过Stream API编写的代码在Client生成的最初的图,表示程序的拓扑结构。(多少个Operator对应多少个Task) JobGraph:StreamGraph经过优化后生成的提交给JM的数据结构,主要讲多个符合条件的节点chain在一起作为一个节点。(符合条件的Operator合并为一个Task) ExecutionGraph:JM根据JobGraph生成的并行化版本,是调度层最核心的数据结构。(根据并行度做出并行版本) 物理执行图:JM根据ExecutionGraph对Job进行调度后,在各个TM上部署Task后形成的图,并非一个具体的数据结构。(TM上执行的物理含义)
7. Parallelism(数据并行范围)
一个特定Operator的Subtask的个数被称为Parallelism(并行度),一般地,一个Stream的并行度可被认为是其所有Operator中最大的Parallelism。 一个程序中,不同Operator可以有不同的并行度,之间传输数据的形式可以是one-to-one(forwarding)模式也可以是redistributing模式,取决于Operator的种类。
One-to-One:(窄依赖)Stream维护者分区以及元素的顺序,如map算子的子任务看到的元素个数及顺序跟source算子的子任务产生的元素个数、顺序相同。map、filter、flatMap等算子均为此模式。 Redistributing:(宽依赖)Stream分区会发生改变,每个Operator的Subtask依据所选择的transformation发送数据到不同的目标任务。如keyBy基于hashCode重分区,broadcast和rebalance会随机重新分区。
8. Operator Chains(任务链)
要求:并行度相同的one-to-one操作,会合成为一个任务链。 Flink采用任务链的优化技术,可以在特定条件下减少本地通信的开销,不需要任务间数据通信的传输(变为同一个线程内方法调用)。 若某个算子复杂,可以通过API取消任务链合并、开启新链,提升性能。