文章目录
介绍
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
流计算与批计算
特性
-
延迟性很低,且能够保证消息不重不丢。
-
具有非常高的吞吐
-
支持流,批,图计算处理
-
基于轻量级分布式快照(Snapshot)实现的容错
-
支持有状态计算
-
支持各种时间概念。处理时间就是Flink 运行时的本地机器时间。
-
高度灵活的窗口操作
-
反压操作
适用场景
- 实时监控,报表
- 流数据分析
- 实时数仓
基本流程与程序写法
DataStream 的主要转换操作
KeyedStream 的理解
根据不同的 key,划分到不同的分区上,用以并发计算。
stream 类型流转全图
WaterMark 概念
主要用来标记 event-time 的前进过程,会跟随 DataStream. Event-time 变动。
在数据有序的情况下,会达到最佳的 WaterMark。
有界乱序事件下的 Watermark
观察下图,就是说:在 W(20) 之前数据会被认为是在W(20)水位之内,后面的19就不在W(20)的水位之内了。会被标记为迟到事件。
waterMark 可以用来实现延迟计算操作。
窗口计算
滚动窗口: 每隔5min统计前10min的总数
滑动窗口:每5分钟统计一次用户总的成交额
多流合并操作
一般是两种类型:
- window join
- interval join (只支持事件时间)
Flink 类型系统
下述的一些数据类型都能够进行序列化与反序列化转换。
理解 Flink 中的计算资源(task,jobmanage,job)
JobManager
JobManager:JobManager 具有许多与协调 Flink 应用程序的分布式执行有关的职责
:它决定何时调度下一个 task(或一组 task)、对完成的 task 或执行失败做出反应
、协调 checkpoint、并且协调从失败中恢复等等。这个进程由三个不同的组件组成:ResourceManager(管理 task slots),Dispatcher(用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。),JobMaster(JobMaster 负责管理单个JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster)
Tasks 和算子链
对于分布式执行,Flink 将算子的 subtasks 链接成 tasks。每个 task 由一个线程执行
。将算子链接成 task 是个有用的优化:它减少线程间切换、缓冲的开销,并且减少延迟的同时增加整体吞吐量。链行为是可以配置的;请参考链文档以获取详细信息。
下图中样例数据流用 5 个 subtask 执行,因此有 5 个并行线程。
算子的合并条件
1.上下游的并行度一致
2.下游节点的入度为1 (也就是说下游节点没有来自其他节点的输入)
3.上下游节点都在同一个 slot group 中(下面会解释 slot group)
4.下游节点的 chain 策略为 ALWAYS(可以与上下游链接,map、flatmap、filter等默认是ALWAYS)
5.上游节点的 chain 策略为 ALWAYS 或 HEAD(只能与下游链接,不能与上游链接,Source默认是HEAD)
6.两个节点间数据分区方式是 forward(参考理解数据流的分区)
7.用户没有禁用 chain
TaskManagers 和 task slot
每个 worker(TaskManager)都是一个 JVM 进程
,可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task,就有了所谓的 task slots(至少一个)
,但是需要注意的是:一个 task slot 中可以执行多个算子
每个 task slot 代表 TaskManager 中资源的固定子集。例如,具有 3 个 slot 的 TaskManager,会将其托管内存 1/3 用于每个 slot。分配资源意味着 subtask 不会与其他作业的 subtask 竞争托管内存,而是具有一定数量的保留托管内存。
默认情况下,Flink 允许 subtask 共享 slot,即便它们是不同的 task 的 subtask,只要是来自于同一作业即可。结果就是一个 slot 可以持有整个作业管道。允许 slot 共享有两个主要优点:
-
Flink 集群所需的 task slot 和作业中使用的最大并行度恰好一样。无需计算程序总共包含多少个 task(具有不同并行度)。
-
容易获得更好的资源利用。如果没有 slot 共享,非密集 subtask(source/map())将阻塞和密集型 subtask(window) 一样多的资源。通过 slot 共享,我们示例中的基本并行度从 2 增加到 6,可以充分利用分配的资源,同时确保繁重的 subtask 在 TaskManager 之间公平分配。
-
并发度:【并发度】 = Flink启动后的slot数 = vcore数(并发度与tm数成倍时)
-
TM数:TaskManager数量】 = Flink中taskManager数 = 物理进程数
-
numSlotsOfTaskManager:每个TM中的slot数, 【并发度】/ 【TaskManager数量】
-
单节点vcore数:(【并发度】/ 【TaskManager数量】)向上取整 ----保证一个tm中的slot在相同机器节点上
-
申请的 vcore总数: 单节点vcore数 *【TaskManager数量】
keyBy 的使用
一些注意事项
- 大作业如果没状态的话 也可以把 overhead 和 managed 都减小,把内存留给 用户代码 当堆内存用
小作业也一样 ,都是都是对内存分配做调整 完整的可以参考
https://ci.apache.org/projects/flink/flink-docs-release-1.12/deployment/memory/mem_setup_tm.html