流处理之基础算子
实验介绍
上一节实验中我们学习了 Flink 的集群部署,从本节开始我们将正式进入 Flink API 的学习。本节的主要内容是 Flink 流处理的基本流程和三个基础算子。
知识点
- 流处理流程
- 基础算子
- map
- filter
- flatMap
流处理流程
不仅仅是 Flink,其实不论是流处理还是批处理框架,总的来说都有以下这么⼏个流程:获取数据、对数据进行 ETL 转换,输出转换之后的结果。如果再细分的话,结合我们在第一个实验中的 WordCount 代码,可以将 Flink 流处理分为以下几个过程:
- 设置执行环境(Environment)
- 获取输入流(Source)
- 转换操作(Transform)
- 输出结果(Sink)
- 执行(Execute)
设置输入环境和执行是比较简单的,重点是 Source、Transform 和 Sink。在 Source 阶段,我们可以从内存对象中创建,也可以从文件以及 Kafka 等外部数据源中获取,还可以根据 Flink 提供的 API 自定义 Source。在 Sink 阶段,我们可以将计算的结果输出到控制台、文件、数据库或者下游的 Kafka,也可以根据 Flink 提供的 API 自定义 Sink。我们本节以及接下来的两个实验介绍的内容都是属于 Transform 阶段的,关于 Source 和 Sink 我们会在后面专门的实验中进行介绍。
基础算子
Flink 中的三个基础算子 map、filter、flatMap 是必须要掌握的,在企业开发中的使用频率相当高。当然如果之前有学习过 Scala 或者 Spark 的话,你会发现⾮常简单。
在我们 FlinkLearning 工程里创建 com.vlab.operator
包,然后创建一个名为 BaseOperator
的 Scala object,本节实验的示例代码都在此文件中执行。
map
map 算子的作用是将原数据集中的每个元素通过传入的转换函数 F 映射为一个新元素,返回由所有新元素组成的集合。
示例如下:
package com.vlab.operator
import org.apache.flink.api.scala._
/**
* @projectName FlinkLearning
* @package com.vlab.operator
* @className com.vlab.operator.BaseOperator
* @description ${description}
* @author pblh123
* @date 2025/2/7 22:45
* @version 1.0
*
*/
object BaseOperator {
def main(args: Array[String]): Unit = {
// 获取当前执行环境
val env = ExecutionEnvironment.getExecutionEnvironment
// 设置执行环境的并行度为1,以确保在所有操作中只使用一个并行任务
env.setParallelism(1)
// 从集合中创建数据集
val data = env.fromCollection(List(1, 2, 3, 4, 5))
// map算子
// 对data中的每个元素乘以10
val result = data.map(x => x * 10)
println("map算子")
result.print()
// filter 算子
val result2 = data.filter(x => x % 2 == 0)
println("filter算子")
result2.print()
// flatMap算子
val data2 = env.fromCollection(List("hello world", "hello flink"))
val result3 = data2.flatMap(_.split(" "))
println("flatMap算子")
result3.print()
}
}
上面的代码中,我们创建了一个包含 1、2、3、4、5 的一个数据集 data,然后通过 map 算子对 data 中的每个元素乘以 10,最后打印输出的结果为:
10
20
30
40
50
filter
filter 算子顾名思义就是过滤,将原数据集中的每个元素,经过传入的函数 F 计算之后返回一个布尔值,过滤出计算结果全部为 True 的元素。
在上面的代码中,我们创建了一个包含 1、2、3、4、5 的一个数据集 data,然后过滤出 data 中的偶数元素,最后打印的结果为:
2
4
flatMap
flatMap 算子和 Scala 语言中的 flatMap 函数类似,可以理解为拉平操作。将深度大于 1 的嵌套序列压缩到深度为 1。
在上面的代码中,我们创建了一个 data 对象,其中的每个元素都是一个字符串,在 flatMap 算子中,我们对每个元素使用空格进行了分隔,最后打印输出。data 本身就是一个 List,使用空格针对里面的每个元素分隔后,每个元素会返回一个数组,也就是说最后返回的结构应该是 List("hello world", "hello flink")
,很明显是一个深度为 2 的序列,但是经过 flatMap 之后,输出的是一个如下所示的深度为 1 的序列:
hello
world
hello
flink
最后,附上本次实验代码的工程结构:
实验总结
本节实验中,我们介绍了流处理的基本流程以及三个最基础的算子,也是日常工作中使用相当频繁的三个算子。相信对于有 Spark 使用经验的同学来说并没有什么难度,对于刚入行学习的新同学来说,flatMap 算子可能会比较烧脑,但是不要气馁,所谓熟能生巧。