flink教程


1 flink简介

    1.1 什么是Flink?

2 flink原理与架构

    2.1 流处理的应用场景

    2.2 流处理的原理

    2.3 Flink架构分析

    2.4 Flink重要语义

Flink重要语义:Streams、State、Time

创建时间:2022-04-20 | 更新时间:2022-04-20 | 阅读次数:1131 次

本节将介绍几个Flink核心语义,包括Streams、State、Time、API等。

1 Streams流

Streams,即流,它可以分为无界流(unbounded Streams)和有界流(bounded Streams)。Flink是一个流批一体化处理框架,不但可以处理无界流数据,也可以处理有界流数据。

所谓的有界流一般指有固定大小,有明确的开始边界,且有明确结束边界的数据,比如保存在职工表中的职工数据。而无界流是指数据是持续产生的,只有明确的开始边界,但是没有明确结束边界的数据,比如传感器数据,数据会持续产生,其中的计算也会持续进行。官方网站给出的关于流的示意图非常形象。

通常情况下,Flink应用程序是由流和转换构成,每一个数据流图有一个或多个Source算子开始,并以一个或多个Sink算子结束。Stream连接在不同的算子之间,算子和Stream共同构成一个有向无环图(DAG)。下图给出了Flink应用程序代码如何映射到一个非并行的数据流示意图。

从图可以看到,Source算子和map算子之间是Stream,apply算子和Sink算子之间也是Stream。

2 State状态

一般来说,状态(State)可以看作是在流计算过程中,缓存在内存或者存储系统上的中间数据,比如累加的值。有状态的流计算,代表具有一定的容错恢复能力,并支持持久化。

流计算从本质上来说,是一种增量计算,它需要按需查询过去的状态信息,以进行后续的计算,最简单的比喻,状态就相当于一个应用程序当中的本地变量,对应的计算任务可以存取中间数据,并在重启情况下不丢失。

因此,状态具有非常重要的价值,它是实现Exactly-once语义的前提,状态会将中间数据写到状态中,并可以根据需要从状态中恢复中间数据。

注意,状态的持久化也是Flink集群在异常情况下可自动重启进行计算的前提条件。

从图可以看出,任务第一步接收到输入的数据,第二步从本地的状态中获取到对应的状态值,并进行数据处理,第三步将更新的状态值写回到本地状态中,第四步输出结果。总的说来,有两种类型的状态:

(1)算子状态(Operator State)。

(2)键控状态(Keyed State)。

由于状态只能在本地维护,而本地存储是不稳定的。因此状态检查点(CheckPoint)的写入就非常重要。

状态后端(State Backend)负责将任务的状态检查点写入远程的持久存储。写入检查点的远程存储可以是分布式文件系统,也可以是数据库。启用检查点的所有Flink应用程序,都可以从保存点恢复数据进行执行。

Flink内置了如下几种状态后端:

(1)MemoryStateBackend

这是默认的一种状态后端,状态数据以Java对象的形式存储在堆中。它支持异步快照,这样可以防止数据流阻塞。

注意,MemoryStateBackend异步快照默认是开启的。默认情况下,每个独立的状态大小限制是5MB。因此只适合本地开发和调试。

(2)FsStateBackend

这种状态后端将状态数据保存在TaskManager节点的内存中。当开启检查点机制时,状态快照也会写入到配置的文件系统目录中。

注意,FsStateBackend异步快照默认是开启的。它适合状态数据比较大或窗口比较长的计算作业场景。

(3)RocksDBStateBackend

这种状态后端将状态数据保存在数据库RocksDB中,它默认将数据存储在TaskManager节点的数据目录中,且只支持异步快照。目前也是唯一支持增量检查点的状态后端。

注意,RocksDBStateBackend允许存储状态非常大的或窗口非常长的数据,大小仅受磁盘空间的限制。

3 Time时间

前面提到,流处理应用中对数据进行计算会涉及时间(Time)这个语义。Flink支持多种时间语义:

(1)事件时间(Event Time)

事件时间是每个事件在其生产设备上产生的时间。一般来说,事件时间在传入Source算子之前就已经存在。

(2)处理时间(Processing time)

处理时间就是Flink算子处理数据的机器时间,它无须提取特定时间属性,因此从计算效率上最高。

(3)摄入时间(Ingestion time)

摄入时间是数据流进入Flink应用程序的时间,介于事件时间和处理时间之间。官方网站给出了Flink关于时间语义的示意图。

4 API接口

所谓的API,即应用程序接口。Flink为了让开发人员更好地进行分布式流处理,通过对外暴露不同层级的API来掩藏内部实现的复杂性。下图给出了Flink分层API示意图,自上而下分别提供了SQL API 、Table API 、DataStream API/DataSet API 和Stateful Streaming Processing四层API。

(1)SQL API

SQL是一种非常实用的语言,基本语法非常简单,因此不少业务人员也可以直接使用SQL进行数据的处理。标准化的SQL还具有很强的兼容性。

Flink社区目前一直在大力发展Flink SQL API,借助SQL API可以用一套API实现流批一体化处理,同时由于SQL是文本,而无须编译,因此可以通过封装来实现灵活的数据处理,即通过动态传入SQL文本就可以处理不同的流批数据处理。

(2)Table API

Table API是一种以Table为中心的声明式编程API,通过TableAPI可以将数据流或者数据集合转换成一张虚拟的表,并可以指定表结构,如字段名、字段类型等。

Table API提供多种关系模型中的操作,如select、where、join和group-by等。一般来说,Table API可以让程序可读性更强且使用起来更加简洁。

(3)DataStream/DataSet API

DataStream/DataSet API是核心API层,Flink框架提供了大量开箱即用的API,可以非常方便地进行数据处理。

其中DataStream API主要用于无界数据流场景,而DataSetAPI主要用于有界数据集场景。目前唯一不方便的是,流批API是两套API。

(4)Stateful Streaming Processing API

Flink Stateful Streaming Processing API是一种有状态的实时流处理API,它也是最底层的API。通过Process Function允许开发人员实现更加复杂的数据底层处理。