目录
一、Flink
1.1 基本概念
1.1.1 flink简介
1.2 flink编程模版
1.3 常用概念
1.2.1 datastream
1.2.2 算子、Task
1.2.3 多流操作
1.2.6 时间语义
二、Flink编程实战(Java)
2.1 wordcount
一、Flink
1.1 基本概念
1.1.1 flink简介
1.图片介绍
性能:
- 低延迟
- 高吞吐
- 内存计算
运维:
- 弹性实施部署机制
- 高可用配置
- 保存点恢复机制
准确性保证:
- exactly-once 状态一致性
- 事件时间处理
- 专业的迟到数据处理
2.对比mapreduce
相似性
数据处理框架:都是大数据处理框架,都提供了一套编程模型和API,使得开发人员能处理大规模数据集。
分布式处理:都支持分布式处理,即数据可以在多个节点上并行处理。在MapReduce中,作业被拆分成多个map任务和reduce任务,这些任务在集群的多个节点上并行执行。在Flink中,数据流也被分割成多个部分,并在不同的任务(Task)中并行处理。
数据分区和聚合:在MapReduce中,map阶段的数据通常会被分区(sharding),并在reduce阶段进行聚合(如求和、计数等)。在Flink中,也有类似的机制,比如使用
keyBy
算子对数据进行分区,然后使用聚合函数(如sum
、max
等)对分区内的数据进行处理。容错机制:都提供了容错机制,以确保在节点故障或数据丢失时能够恢复作业的执行。MapReduce通过检查点(checkpointing)和重试机制来实现容错,而Flink则提供了包括基于状态的容错和精确一次(exactly-once)语义的保证。
区别:
处理模式:MapReduce是批处理框架,处理的是静态数据集(即数据在作业开始之前就已经存在)。而Flink是流处理框架,它处理的是实时数据流(即数据是持续不断地产生的)。
实时性:Flink支持低延迟的实时数据处理,能够处理毫秒级甚至微秒级的数据。而MapReduce则更适合于离线批处理场景,其处理延迟通常较高。
状态管理:Flink提供了更强大的状态管理能力,它能够在任务之间或故障恢复后保持状态的一致性,且API更丰富。
1.2 flink编程模版
1.万卷不离其宗!!!运行模型通常包括三个部分:Source(数据源)、Transformation(转换操作)、Sink(输出)。
- 获取一个编程之行入口环境env
- 通过数据源组建,加载,创建datastream
- 对datastream调用各种处理算子表达计算逻辑
- 通过sink算子指定计算结果指定计算结果的输出方式
- 在env上触发程序提交执行
2.添加依赖
对于Maven项目,在pom.xml
文件中添加<dependency>
元素,代码举例:
<dependencies>
<!-- Flink核心库 -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>你的Flink版本号</version>
<!-- 通常这个依赖的作用域设置为provided,但根据你的项目需求可以调整 -->
<!-- <scope>provided</scope> -->
</dependency>
<!-- Flink流处理库(Java API) -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_你的Scala版本</artifactId>
<version>你的Flink版本号</version>
<!-- 如果在IDE中运行,可能需要将作用域设置为compile或runtime -->
<!-- <scope>compile</scope> -->
</dependency>
<!-- 如果你还需要使用Table API或SQL,则可以添加以下依赖 -->
<!-- Flink Table API和SQL的Java桥接库 -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-java-bridge_你的Scala版本</artifactId>
<version>你的Flink版本号</version>
<!-- 通常这个依赖的作用域也设置为provided -->
<!-- <scope>provided</scope> -->
</dependency>
<!-- 注意:上述示例中的“你的Flink版本号”和“你的Scala版本”需要替换为实际的版本号 -->
<!-- Flink的版本号可以从Apache Flink的官方网站或Maven中央仓库获取 -->
<!-- Scala的版本号取决于你使用的Flink版本和Scala兼容性 -->
</dependencies>
1.3 常用概念
1.2.1 datastream
- DataStream代表一个数据流,它可以是无界的,也可以是有界的;
- DataStream类似于spark的rdd,它是不可变的(immutable);
- 无法对一个datastream进行自由的添加或删除或修改元素;
- 只能通过算子对datastream中的数据进行转换,将一个datastream转成另一个datastream;
- datastream可以通过source算子加载、映射外部数据而来;或者从已存在的datastream转换而来
1.2.2 算子、Task
1.算子(Operator)可以被通俗地理解为一种可以调用的函数或操作,它们对数据进行处理或转换。不过,与传统的函数相比,Flink的算子是在分布式环境中执行的,它们能够处理无限的数据流或有限的数据集。
举例:
Window算子:Window算子就像是一个定时闹钟和一堆小盘子。你设置了时间间隔(比如每分钟、每小时),当时间到了,闹钟就会响,然后你把这段时间内收集到的所有食材(数据)放到一个小盘子里进行统一处理。这样可以让你看到数据随时间变化的趋势。
- Filter算子:Filter算子就像是一个筛子。你把食材(数据)倒进筛子里,只有满足特定条件(比如大小、颜色等)的食材才能通过筛子继续向下流动。这个过程中,不满足条件的食材就被淘汰了。
- Sink算子(Sink Operator):是数据流处理管道中的一个重要组成部分,它负责将处理后的数据输出到外部系统或存储中。Sink是数据流处理的终点,它接收来自上游算子的数据,并将其发送到目的地,如文件系统、数据库、消息队列等。
2.task,subtask
- flink程序中,每一个算子都可以成为一个独立任务(task);
- flink程序中,视上下游算子间数据分发规则、并行度、共享槽位设置,可组成算子链成为一个task
- 每个任务在运行时都可拥有多个并行的运行实例(subTask);
- 且每个算子任务的并行度都可以在代码中显式设置;
3. Task和算子的联系
- 共同作用于数据流处理:Task和算子都是处理数据流的关键组成部分。Task是执行单元,而算子定义了数据流上的具体操作。
- 优化与执行:为了提高处理效率和减少资源消耗,Flink会将多个算子链接(chain)成一个Task,在同一个线程中执行。
1.2.3 多流操作
多流操作指的是在数据流处理过程中,对两个或多个数据流进行各种转换和合并的操作。这些操作使得Flink能够处理复杂的数据流场景,如数据分流(将一条数据流拆分成多条)、数据合流(将多条数据流合并成一条)以及双流联结(基于特定条件将两条数据流联结起来)等。
1.2.6 时间语义
1. 事件时间(Event Time)
事件时间是指数据本身所携带的时间戳,即数据实际发生或产生的时间。你可以把它想象成每个数据项都自带了一个“出生证”,上面写着它是什么时候被创造出来的。在Flink中,事件时间允许我们按照数据实际发生的时间顺序来处理数据,即使这些数据在系统中是乱序到达的。
2. 处理时间(Processing Time)
处理时间是指数据在Flink系统中被处理时所在机器的系统时间。你可以把它想象成每个处理节点都有一个“本地时钟”,这个时钟告诉节点当前是什么时候,并且所有基于时间的操作都使用这个时钟的时间。
3. 摄入时间(Ingestion Time)
摄入时间是指数据进入Flink系统的时间戳,即数据被Flink Source算子接收的时间。你可以把它想象成Flink系统有一个“大门”,所有数据都要通过这个大门进入,而大门上有一个“计时器”,记录着每个数据项进门的时间。