2 Flink1.11.0 原理及编程模型介绍

你将在本章学习到以下内容:
- 具体方法是什么用于构建流数据处理管道(pipelines)
- Flink 主要采用何种机制来管理状态及其必要性
- 具体措施是什么用于利用事件时间以一致性和精确性进行计算分析
- 在持续的数据流量中如何设计和构建基于事件驱动的应用程序
- Flink 提供了哪些独特的功能和机制以实现精确一次计算语义的容错和带状态的流处理
本章教程将重点讲解四个核心知识点:持续不断的数据流处理机制、事件发生的时间属性、带有状态管理的流处理模式以及精确的状态捕获快照机制。下面将从基础概念入手进行详细讲解。
1 流处理
在自然环境中产生出的数据本来就是一种流动形式。无论是来自Web服务器产生的事件数据、证券交易所产生的交易数据还是通过社会sensors收集的各种信息
从工厂车间机器上的传感器获取的数据均为流式数据。然而,在数据分析过程中,我们可以以 有界流 ( bounded )或 无界流 为基础进行分析。
( unbounded )两种管理方案用于处理数据流程;相应地,在采用不同的方案时系统的响应能力和资源分配策略也会发生变化

批量处理 是有界数据流处理的一个典型实例。在采用该模式时,你可以选择地进行批量加载全部数据集;从而使得你能够提前获得计算结果。
对整个数据集的数据 进行排序、统计或汇总 计算后再输出结果。
流处理恰恰相反,它专门处理无界数据流.从理论上讲,它的数据输入将无限延续下去,因此程序必须持续不断地处理不断到达的数据.
据进行处理。
在Flink环境中,应用程序由用户定制化的算子生成的数据流数据集构成。这些数据流数据集构建了有向图
或多个源 (source)开始,并以一个或多个汇 (sink)结束。

一般情况下,在程序代码中,transformation与dataflow中的算子(operator)之间是一一相对应的关系。偶尔会遇到单独存在的算子(operator)。
transformation 包含多个算子的情况,如上图所示。
Flink应用程序 能够高效地接收并处理来自消息队列系统或其他分布式日志流中获取的实时数据(例如 Apache Kafka 或 Kinesis)。
也可以从不同来源的数据中利用有限的历史数据。类似地,Flink应用程序生成的数据流也可以传输到多个汇总系统。

2 并行 Dataflows
该框架主要基于分布式并行计算模式设计,在系统运行过程中,每个输入流可能包含一个或多个分片(Streaming Partitions),其中每个处理单元都有相应的算子支持
一个或多个操作子(Operator Subtask)。各个操作子相互独立,并各自在独立的线程上运行。或者在不同的计算机上运行并占用内存空间。
器中运行。
对于每个运算符,在其对应的运算体中进行分解得到的并行深度即为该运算符的计算粒度。值得注意的是,在同一个系统或程序设计中,并非所有的运算符都具有相同的计算粒度;不同的运算符可能会根据具体需求或数据特征表现出不同的计算粒度水平。

Flink 算子之间可以通过 一对一 ( 直传 )模式或 重新分发 模式传输数据:
一对一 模式(例如上图中的 Source 和 map() 算子之间)可以保留元素的分区和顺序信息。这意味着 map() 算子的
subtask[1] 输入的数据以及其顺序与 Source 算子的 subtask[1] 输出的数据和顺序完全相同,即同一分区的数据只会
进入到下游算子的同一分区。
重新分发 模式(例如上图中的 map() 和 keyBy/window 之间,以及 keyBy/window 和 Sink 之间)则会更改数据所在
的流分区。当你在程序中选择使用不同的 transformation ,每个 算子子任务 也会根据不同的 transformation 将数据发
送到不同的目标子任务。例如以下这几种 transformation 和其对应分发数据的模式:
keyBy() (通过散列键重新分区)、
broadcast() (广播)或 rebalance() (随机重新分发)。
在 重新分发 数据的过程中,元素只有在每对输出和输入子任务之间才能保留其之间的顺序信息
(例如, keyBy/window 的 subtask[2] 接收到的 map() 的 subtask[1] 中的元素都是有序的)。
因此,上图所示的 keyBy/window 和 Sink 算子之间数据的重新分发时,不同键(key)的聚合结果到达 Sink 的顺序是不确定的。
3 Task和算子链

clients、JobManager、TaskManager


每个 Flink 应用都需要有执行环境,在该示例中为 env。
流式应用依赖于 StreamExecutionEnvironment 的配置参数设置。批处理任务需要在 ExecutionEnvironment 环境变量下进行相应的初始化操作。
任务执行原理:
注
Flink运行时包含两种类型的进程:
- JobManger: 也被称作masters,在Flink系统中负责管理分布式任务的执行,并协调各子任务之间的同步与检查点的建立。此外,在高可用架构下可部署多个JobManger实例,其中主实例为Leader角色,其余为备用状态。
- TaskManager: 也被称作workers,在处理Flink定义的数据流时负责运行生成的任务,并将处理后的数据暂时存储在缓冲区中。此外,在系统架构中还负责实现不同TaskManager之间的数据交换机制。作为关键组件,在任何Flink程序运行时都需要确保至少一个有效的TaskManager实例存在。
Flink程序可以运行在standalone集群,Yarn或者Mesos资源调度框架中。
clients并非Flink程序运行时的一个组成部分,在功能上负责生成并传输dataflow至JobManage系统中。完成数据流传输后, clients能够选择性地断开连接或持续保留连接状态进行后续操作。
4 TaskSlots 任务槽

每一个TaskManager属于JVM进程,并且能够承担一个或多个tasks;这些tasks在其任务槽上运行。
每个worker上至少有一个任务槽。 每个任务槽都有固定的资源。
举例来说, TaskManager有三个任务槽,则每个任务槽会均匀分配内存给TaskManager
内存占总内存的三分之一。任务槽的主要作用是将任务托管到专用内存空间,并确保不发生CPU隔离现象。
用户可以通过合理配置任务槽的数量来确定每个TaskManager可容纳的任务数量。增加任务槽的数量将使系统能够支持更多的task运行。
基于同一JVM环境,在该JVM下的task实例能够实现对TCP通信机制的同步使用以及心跳数据的同步传输。此外,在同步使用相同的训练数据集以及保持一致的数据结构方面也达到了良好的协同效果。这些机制的实现有助于降低TaskManager的管理负担。
总结: task slot的个数代表 TaskManager可以并行执行的 task****数。
5 自定义时间流处理
在大多数流数据处理的应用程序中,通过利用实时数据分析的代码对历史数据进行重新分析,从而确保结果的一致性和确定性
常有价值。
在处理流式数据时,我们通常会更重视事件本身的顺序而非它们被传输和处理的顺序(原因在于此),以便支持系统的稳定性得到实现。
我们推断出一组特定的事件(称为事件集合)在其发生时间和持续时间上具有明确的信息特征。例如,在电子商务和金融交易领域中所涉及的事件集合。
为了应对一系列实时流处理场景的需求,在分析这些场景时我们通常会基于数据流中事件时间标记的时间戳进行分析 ,而无需直接处理原始数据。
时钟的时间戳。
6 有状态流处理
Flink中的算子具备有状态的能力。这表明处理每个事件的方式可能会根据其之前的全部事件数据的综合结果来进行调整。
Flink中的状态信息不仅可以用于基本的应用场景(例如实时数据监控系统),同样也能应用于复杂的应用环境
(例如训练作弊检测模型)。
Flink应用能够在分布式群集上实现完全可扩展的任务处理能力,并且其每个算子的所有并行实例均能在各自独立的线程中正常运行
并且通常情况下是会在不同的机器上运行。
有状态算子的并行实例组在存储其对应状态时一般会按照键(key)来进行分片存储。每个并行实例中的算子负责处理相应的操作。
一组特定键的事件数据,并且这组键对应的状态会保存在本地。
如图所示的Flink作业中,其前三个运算元具有并行度2,最后一个是sink运算元,其并行度为1,其中第三个运算元具有状态特征
此外,在第二个运算器与第三个运算器之间实现了完全互联(fully-connected),它们经由网络实现数据的分布。
一般而言,在开发这种类型的Flink程序时,主要目的是依据特定键值对对数据流进行划分,并以整合相关事件为目标。
然后做统一计算处理。

Flink应用程序对状态的读取全部在本地完成这一机制有助于提升系统的吞吐能力并减少响应时间
通常情况下 Flink 应用程序一般都会将状态存储在 JVM 堆上,
如果遇到状态过大的情况,则可以选择采用结构化数据格式来进行处理。
存储在高速磁盘中 。

7 通过状态快照实现的容错
借助状态快照和流重放这两种技术手段的结合应用,在Flink中实现了更加精准的一次性计算结果。
这些状态快照在运行时将收集并保存分布式pipeline的整体状态信息,并追踪被消费的数据偏移量(offsets)。
在捕获该数据所对应的偏移量信息后进行状态的采集和存储。当出现故障情况时
Flink 作业负责将状态重置为上次存储的状态,并将数据源从记录中获取上次消费的偏移量后重新启动消费处理。
此外,在执行过程中,state snapshot将通过异步机制获取当前的状态信息,并进行存储操作;这一过程不会干扰正在处理的数据流。
