“前一篇文章中<一文了解Flink数据-有界数据与无界数据>大致讲解了Apache Flink数据的形态问题。Apache Flink实现分布式集合数据集转换、抽取、分组、统计等。根据数据源的类型,即为有界数据与无界数据,提供了DataSet与DataStream的基础API。”
DataSet与DataStream
根据数据源的类型,即为有界数据与无界数据。Apache Flink提供可以编写流处理与批处理的程序。其中DataSet API用于批处理,DataStream API用于流式处理。对于DataSet来说可以认为其中存储的是可重复有界的数据集合。而DataStream中存储的可以认为是重复的无界的数据集合。
Flink提供了不同级别的抽象来实现批处理或流处理任务的开发。
Flink的基本构建就是数据流与转换,(Flink 中DataSet API中使用的也是内部流)。从整体概念上来讲,流是持续的不会产生中断的数据记录流。而转换则是讲一个或多个流的进行转换、计算、聚合等产生一个或多个流。
程序在执行时会映射出一个或者多个数据流,每个数据流都以一个或者多个源为开头,例如Kakfa、File等或者是通过与计算得来。数据流之间类似于一个有向无环图DAG。
通过两个例子来看DataSet和DataStream。
- 批处理
val env = ExecutionEnvironment.getExecutionEnvironment
// 创建DataSource
val text = env.fromElements(
"Best Data Processing Engine")
//flatMap : 把字符串转换为小写,并且按照空白分割为一个个的单词.
//filter: 过滤非空结果
//map: 把切割的单词转换为 单词,1
//groupBy:按照下标位0进行分组
//sum: 计算 下标位1的结果
val counts = text.flatMap { _.toLowerCase.split("\W ")
.filter { _.nonEmpty } }
.map { (_, 1) }
.groupBy(0)
.sum(1)
//打印结果到控制台
counts.print()
- 流式处理
val env = StreamExecutionEnvironment.getExecutionEnvironment
val text = env.socketTextStream("localhost",9999)
//flatMap : 把字符串转换为小写,并且按照空白分割为一个个的单词.
//filter: 过滤非空结果
//map: 把切割的单词转换为 单词,1
//timeWindow: 按照时间,每5s获取进行一次计算
//sum: 计算 下标位1的结果
val counts = text.flatMap { _.toLowerCase.split("\W ")
.filter { _.nonEmpty } }
.map { (_, 1) }
.keyBy(0)
.timeWindow(Time.seconds(5))
.sum(1)
//打印结果到控制台
counts.print()
从上面看,流式处理与批处理的代码实现基本上是一样的,流式处理的数据在通过 nc -lk 9999
开启一个socket。Flink连接socket之后就可以进行执行。数据相对与批处理来说是无界的持续数据集。而代码上增加了一个Window。
Windows 窗口
窗口是批处理上不存在的一个过程。流处理与批处理的工作方式不同,例如流处理无法聚合计算元素总数,因为流数据通常都是无界的。所以流上的聚合是由窗口来界定的。(5s,100条)。
Apache Flink中窗口有翻滚窗口,滑动窗口与会话窗口。基于对数据集的切割能够实现基于时间的窗口(TimeWindow)、基于数据驱动的窗口(CountWindow)等。
时间(Event Time,Processing Time,Ingestion Time)
既然存在时间窗口,那么就会对时间做一个基本的定义。一般来讲,时间基本上存在与事件处理的当前时间。也就是处理引擎当前的时间。 Apache Flink对于提供了不同的时间概念:
- 事件时间(创建时间的时间):类似于我们使用log输出日志的时候所打印的时间。
- 摄取时间:是指事件源输入到Flink的时间。
- 处理时间:基于时间的操作,每次操作的时间。
常规情况下对时间进行区分可以理解为
- log4j输出一条日志的头带有的时间为 事件时间
- 采集程序把数据写入到kafka,Apache Flink实时读取Kafka中的数据,读取到该条数据的时间为摄取时间。
- ApacheFlink进行翻滚窗口处理,翻滚时间为5分钟,那么处理到该条数据的时间则为处理时间。
有状态的计算
虽然数据流是无界的数据流,持续产生。但是Apache Flink会记录基于窗口的多个事件的结果。批处理时不需要把数据的当前状态进行存储。而流式计算需要持久的执行,基本上都是以月为单位的执行。那么就需要保存把计算过程持久的存储起来,下次计算的结果直接进行累加。
容错
Apache Flink提供了容错的机制,基于状态与检查点进行执行。该机制确保了当出现故障时系统可以退回到检查点。Apache Flink从容错可处理上可以实现(at least once, exactly once)