流批OLAP 一体的 Flink 引擎介绍(二) | 青训营笔记

99 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第6天

Flink作业示例——一个Flink作业在Flink中的处理流程、DataFlow Model设计思想

在 Flink 中,应用程序由流数据流组成,这些数据流可能由用户定义的运算符进行转换。这些数据流形成有向图,从一个或多个开始,以一个或多个接收器结束.

流式的WorkCount示例,从kafka中读取一个实时数据流,每10s统计一次单词出现次数

DataStream实现代码如下:

program_dataflow.svg

业务逻辑转换为一个Streaming DataFlow Graph.

通常,程序中的转换与数据流中的运算符之间存在一对一的对应关系。但是,有时一个转换可能由多个运算符组成。

应用程序可能会使用来自流源(如消息队列或分布式日志,如 Apache Kafka 或 Kinesis)的实时数据。但 flink 还可以使用来自各种数据源的有界历史数据。同样,Flink 应用程序产生的结果流可以发送到各种可以作为接收器连接的系统。

Flink Application Sources and Sinks

假设作业的sink算子的并发配置为1,其余算子并发为2

紧接着会将上面的Streaming DataFlow Graph 转化Parallel Dataflow(内部叫Execution Graph):

Parallel Dataflow

最后将上面的Task调度到具体的TaskManager中的slot中执行,一个slot只能运行同一个task的subTask

每个 worker(TaskManager)都是一个 JVM 进程,可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task,就有了所谓的 task slots(至少一个)。

每个 task slot 代表 TaskManager 中资源的固定子集。例如,具有 3 个 slot 的 TaskManager,会将其托管内存 1/3 用于每个 slot。分配资源意味着 subtask 不会与其他作业的 subtask 竞争托管内存,而是具有一定数量的保留托管内存。注意此处没有 CPU 隔离;当前 slot 仅分离 task 的托管内存。

通过调整 task slot 的数量,用户可以定义 subtask 如何互相隔离。每个 TaskManager 有一个 slot,这意味着每个 task 组都在单独的 JVM 中运行(例如,可以在单独的容器中启动)。具有多个 slot 意味着更多 subtask 共享同一 JVM。同一 JVM 中的 task 共享 TCP 连接(通过多路复用)和心跳信息。它们还可以共享数据集和数据结构,从而减少了每个 task 的开销。

A TaskManager with Task Slots and Tasks

默认情况下,Flink 允许 subtask 共享 slot,即便它们是不同的 task 的 subtask,只要是来自于同一作业即可。结果就是一个 slot 可以持有整个作业管道。允许 slot 共享有两个主要优点:

  • Flink 集群所需的 task slot 和作业中使用的最大并行度恰好一样。无需计算程序总共包含多少个 task(具有不同并行度)。
  • 容易获得更好的资源利用。如果没有 slot 共享,非密集 subtask(source/map() )将阻塞和密集型 subtask(window) 一样多的资源。通过 slot 共享,我们示例中的基本并行度从 2 增加到 6,可以充分利用分配的资源,同时确保繁重的 subtask 在 TaskManager 之间公平分配。

TaskManagers with shared Task Slots

Flink如何做到流批一体——流批一体的业务场景及挑战、Flink如何做到流批一体

为什么需要流批一体

实时数仓.png 上述架构有一些痛点:

1.人力成本比较高:批、流两套系统,相同逻辑需要开发两遍;

2.数据链路冗余:本身计算内容是一致的,由于是两套链路,相同逻辑需要运行两遍,产生一定的资源浪费;

3.数据口径不一致:两套系统、两套算子、两套UDF,通常会产生不同程度的误差,这些误差会给业务带来非常大的困扰。

流批一体的挑战

流和批业务场景的特点如下表:

流批一体的挑战.png 批式计算相比于流式计算核心的区别如下表:

区别.png