#博学谷IT学习技术支持#
01 概述
什么是流式计算
在日常生活中,我们通常会先把数据存储在一张表中,然后再进行加工、分析,这里就涉及到一个时效性的问题。如果我们处理以年、月为单位的级别的数据,那么多数据的实时性要求并不高;但如果我们处理的是以天、小时,甚至分钟为单位的数据,那么对数据的时效性要求就比较高。在第二种场景下,如果我们仍旧采用传统的数据处理方式,统一收集数据,存储到数据库中,之后在进行分析,就可能无法满足时效性的要求.
大数据的计算模式主要分为批量计算(batch computing)、流式计算(stream computing)、交互计算(interactive computing)、图计算(graph computing)等。其中,流式计算和批量计算是两种主要的大数据计算模式,分别适用于不同的大数据应用场景。
流数据(或数据流)是指在时间分布和数量上无限的一系列动态数据集合体,数据的价值随着时间的流逝而降低,因此必须实时计算给出秒级响应。流式计算,顾名思义,就是对数据流进行处理,是实时计算。批量计算则统一收集数据,存储到数据库中,然后对数据进行批量处理的数据计算方式。主要体现在以下几个方面:
-
- 数据时效性不同:流式计算实时、低延迟, 批量计算非实时、高延迟。
-
- 数据特征不同:流式计算的数据一般是动态的、没有边界的,而批处理的数据一般则是静态数据。
-
- 应用场景不同:流式计算应用在实时场景,时效性要求比较高的场景,如实时推荐、业务监控…批量计算一般说批处理,应用在实时性要求不高、离线计算的场景下,数据分析、离线报表等。
-
- 运行方式不同,流式计算的任务持续进行的,批量计算的任务则一次性完成。
总结来说,我们得到的会是一条条的,随着时间流逝不断增长的数据,我们需要进行实时的数据分析
02 Apache Flink 基本介绍
Flink核心是一个流式的数据流执行引擎,其针对数据流的分布式计算提供了数据分布、数据通信以及容错机制等功能。基于流执行引擎,Flink提供了诸多更高抽象层的API以便用户编写分布式任务:
-
DataSet API, 对静态数据进行批处理操作,将静态数据抽象成分布式的数据集,用户可以方便地使用Flink提供的各种操作符对分布式数据集进行处理,支持Java、Scala和Python。
-
DataStream API,对数据流进行流处理操作,将流式的数据抽象成分布式的数据流,用户可以方便地对分布式数据流进行各种操作,支持Java和Scala。
-
Table API,对结构化数据进行查询操作,将结构化数据抽象成关系表,并通过类SQL的DSL对关系表进行各种查询操作,支持Java和Scala。
此外,Flink还针对特定的应用领域提供了领域库,例如:
-
Flink ML: Flink的机器学习库,提供了机器学习Pipelines API并实现了多种机器学习算法。
-
Gelly: Flink的图计算库,提供了图计算的相关API及多种图计算算法实现。
下图为一个标准的实时处理的过程图:
03 Flink 中的 API
Flink 为流式/批式处理应用程序的开发提供了不同级别的抽象。
-
Flink API 最底层的抽象为有状态实时流处理。其抽象实现是 Process Function,并且 Process Function 被 Flink 框架集成到了 DataStream API 中来为我们使用。它允许用户在应用程序中自由地处理来自单流或多流的事件(数据),并提供具有全局一致性和容错保障的状态。此外,用户可以在此层抽象中注册事件时间(event time)和处理时间(processing time)回调方法,从而允许程序可以实现复杂计算。
-
Flink API 第二层抽象是 Core APIs。实际上,许多应用程序不需要使用到上述最底层抽象的 API,而是可以使用 Core APIs 进行编程:其中包含 DataStream API(应用于有界/无界数据流场景)和 DataSet API(应用于有界数据集场景)两部分。Core APIs 提供的流式 API(Fluent API)为数据处理提供了通用的模块组件,例如各种形式的用户自定义转换(transformations)、联接(joins)、聚合(aggregations)、窗口(windows)和状态(state)操作等。此层 API 中处理的数据类型在每种编程语言中都有其对应的类。
-
Process Function 这类底层抽象和 DataStream API 的相互集成使得用户可以选择使用更底层的抽象 API 来实现自己的需求。DataSet API 还额外提供了一些原语,比如循环/迭代(loop/iteration)操作。
-
Flink API 第三层抽象是 Table API。Table API 是以表(Table)为中心的声明式编程(DSL)API,例如在流式数据场景下,它可以表示一张正在动态改变的表。Table API 遵循(扩展)关系模型:即表拥有 schema(类似于关系型数据库中的 schema),并且 Table API 也提供了类似于关系模型中的操作,比如 select、project、join、group-by 和 aggregate 等。Table API 程序是以声明的方式定义应执行的逻辑操作,而不是确切地指定程序应该执行的代码。尽管 Table API 使用起来很简洁并且可以由各种类型的用户自定义函数扩展功能,但还是比 Core API 的表达能力差。此外,Table API 程序在执行之前还会使用优化器中的优化规则对用户编写的表达式进行优化。
-
表和 DataStream/DataSet 可以进行无缝切换,Flink 允许用户在编写应用程序时将 Table API 与 DataStream/DataSet API 混合使用。
-
Flink API 最顶层抽象是 SQL。这层抽象在语义和程序表达式上都类似于 Table API,但是其程序实现都是 SQL 查询表达式。SQL 抽象与 Table API 抽象之间的关联是非常紧密的,并且 SQL 查询语句可以在 Table API 中定义的表上执行。
04 Apache Flink 流式计算入门程序
需求说明: wordCount案例
通过监听某个socket网络流, 从网络数据流中获取单词数据, 进行统计操作, 完成实时统计wordCount案例
案例实现流程:
项目准备工作:
第一步: 创建maven项目, 并添加以下依赖
<repositories>
<repository>
< id >aliyun</ id >
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId> <version> 1.10.0 </version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2 .11 </artifactId>
<version> 1.10.0 </version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version> 3.1 </version>
<configuration>
<target> 1.8 </target>
<source> 1.8 </source>
</configuration>
</plugin>
</plugins>
</build>
第二步: 创建包结构 com.itheima.flink.wordCount
实现步骤:
-
创建flink流式处理的核心环境类: StreamExecutionEnvironment (静态方法构建)
-
组装flink的三大组件: source(数据源) translation(转换) sink(下沉地/目的地)
- 在flink核心类中构建source类:此处选择监听socket网络数据流
- 在source类中, 添加相关转换操作:处理数据
- 在转换类中, 设置sink输出:此处为直接打印
-
通过核心类, 启动flink
代码编写:
public class SocketWordCount {
public static void main(String[] args) throws Exception {
// 1. 创建一个flink的流式处理入门类
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 2. 组装 flink三大组件: source(数据源) translation(转换) sink(目的地)
// 2.1 构建source组件
DataStreamSource<String> source = env.socketTextStream( "node1" , 4444 );
// 2.2 进行数据转换操作
SingleOutputStreamOperator<Tuple2<String,Integer>> streamOperator = source.flatMap(new FlatMapFunction<String, Tuple2<String,Integer>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String,Integer>> collector) throws Exception {
// 2.1 对数据进行处理
String[] words = value.split( " " );
// 2.2 遍历
for (String word : words) {
collector.collect(Tuple2. of (word, 1 ));
}
}
}).keyBy( 0 ). sum ( 1 ); // 对key进行分组, 求个数即可
// 2.3 sink: 结果打印控制台 sink
streamOperator. print ();
// 3 启动即可
env.execute( "wordCount" );
}
}
测试程序
第一步: 在node1 开启 绑定监听 4444端口号, 并准备向4444端口号发送数据
说明: nc是netcat的简写, 是一款网络测速小工具, 可以方便建立任何连接,并向其发送数据
第二步: 在IDEA中启动flink入门程序
第三步: 开始在netcat窗口输入单词进行测试