大数据技术之flink(1)

前言

你们好我是啊晨
今儿更新flink 技术
废话不多说,内容很多选择阅读,详细。
请:

第一章 flink简介

在这里插入图片描述

1.1大数据4代计算引擎

第1代——Hadoop MapReduce
批处理
Mapper、Reducer
流处理
Strom
第2代——DAG框架(Tez) + MapReduce
批处理
1个Tez = MR(1) + MR(2) + … + MR(n)
相比MR效率有所提升
3. 第3代——Spark
批处理、流处理、SQL高层API支持
自带DAG
内存迭代计算、性能较之前大幅提升
4. 第4代——Flink
批处理、流处理、SQL高层API支持
自带DAG
流式计算性能更高、可靠性更高

1.2 flink起源

熟知略过即可

许多系统都会产生连续的事件流,如行驶中的汽车发射出 GPS 信号,金融交易,移动通信基站与繁忙的智能手机进行信号交换,网络流量,机器日志,工业传感器和可穿戴设备的测量结果,等等。如果能够高效地分析大规模流数据,我们对上述系统的理解将会更清楚、更快速。简而言之,流数据更真实地反映了我们的生活方式。

因此,我们自然希望将数据用事件流的方式收集起来并加以处理。但直到目前,这并不是整个行业的标准做法。流处理并非全新的概念,但它确实是一项专业性强且极具挑战性的技术。实际上,企业常见的数据架构仍旧假设数据是有头有尾的有限集。这个假设存在的大部分原因在于,有限集匹配的数据存储及处理系统建起来比较简单。但是,这样做无疑给那些天然的流式场景人为地加了限制。

我们渴望按照流的方式处理数据,但要做好很困难;随着大规模数据在各行各业中出现,难度越来越大。这是一个属于物理学范畴的难题:在大型分布式系统中,数据一致性和对事件发生顺序的理解必然都是有限的。伴随着方法和技术的演化,我们尽可能使这种局限性不危及商业目标和运营目标。

在这样的背景下,Apache Flink(以下简称 Flink)应运而生。Flink 起源于Stratosphere项目,Stratosphere 是在 2010~2014 年由 3 所地处柏林的大学和欧洲的一些其他的大学共同进行的研究项目,2014年4月Stratosphere 的代码被复制并捐赠给Apache软件基金会,参加这个孵化项目的初始成员是Stratosphere 系统的核心开发人员,2014年12月,Flink一跃成为 Apache软件基金会的顶级项目。

作为在公共社区中诞生的开源软件,Flink 为大容量数据提供流处理,并用同一种技术实现批处理(批处理是流处理的一种特殊的形式)。

在 Flink 的开发过程中,开发人员着眼于避免其他流处理方法不得不在高效性或者易用性方面所做的妥协。
在这里插入图片描述在这里插入图片描述
Flink 项目的理念是:“Apache Flink 是为分布式、高性能、随时可用以及准确的流处理应用程序打造的开源流处理框架”。

Apache Flink 是一个框架和分布式处理引擎,用于对无界有界数据流进行有状态计算。Flink 被设计在所有常见的集群环境中运行,以内存执行速度和任意规模来执行计算。
在这里插入图片描述

1.3初探flink

1.3.1事件驱动型应用(Event-driven)

事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。比较典型的就是以 kafka 为代表的消息队列几乎都是事件驱动型应用。下图描述了传统应用和事件驱动型应用架构的区别。
在这里插入图片描述

1.3.2有界流和无界流

面试常问:flink 是如何同时实现批处理与流处理的呢?
答案是,Flink 将批处理(即处理有限的静态数据)视作一种特殊的流处理

Flink 的核心计算构造是一个分布式系统,能够接受数据流程序并在一台或多台机器上以容错方式执行。Flink 执行引擎可以作为 YARN(Yet Another Resource Negotiator)的应用程序在集群上运行,也可以在 Mesos 集群上运行,还可以在单机上运行(这对于调试 Flink 应用程序来说非常有用)。

任何类型的数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。数据可以被作为无界或者有界流来处理。

无界数据流:无界数据流有一个开始但是没有结束,它们不会在生成时终止并
提供数据,必须连续处理无界流,也就是说必须在获取后立即处理 event。对于无界
数据流我们无法等待所有数据都到达,因为输入是无界的,并且在任何时间点都不
会完成。处理无界数据通常要求以特定顺序(例如事件发生的顺序)获取 event,以
便能够推断结果完整性。

有界数据流:有界数据流有明确定义的开始和结束,可以在执行任何计算之前
通过获取所有数据来处理有界流,处理有界流不需要有序获取,因为可以始终对有
界数据集进行排序,有界流的处理也称为批处理
在这里插入图片描述
这种以流为世界观的架构,获得的最大好处就是具有极低的延迟。

1.3.3分层 api

Flink 根据抽象程度分层,提供了三种不同的 API。每一种 API 在简洁性和表达力上有着不同的侧重,并且针对不同的应用场景。
在这里插入图片描述

先看详细介绍,没耐心下面有大概的总结,如有出路,请评论指正

ProcessFunction 是 Flink 所提供的最具表达力的接口。ProcessFunction 可以处理一或两条输入数据流中的单个事件或者归入一个特定窗口内的多个事件。它提供了对于时间和状态的细粒度控制。开发者可以在其中任意地修改状态,也能够注册定时器用以在未来的某一时刻触发回调函数。因此,你可以利用 ProcessFunction 实现许多有状态的事件驱动应用所需要的基于单个事件的复杂业务逻辑。

实际上,大多数应用并不需要上述的底层抽象,而是针对核心 API(Core APIs)进行编程。DataStream API 为许多通用的流处理操作提供了处理原语。这些操作包括窗口、逐条记录的转换操作,在处理事件时进行外部数据库查询等。DataStream API 支持 Java 和 Scala 语言,预先定义了例如map()、reduce()、aggregate() 等函数。你可以通过扩展实现预定义接口或使用 Java、Scala 的 lambda 表达式实现自定义的函数。

Flink 支持两种关系型的 API,Table API 和 SQL。这两个 API 都是批处理和流处理统一的 API,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型 API 会以相同的语义执行查询,并产生相同的结果。Table API 和 SQL 借助了 Apache Calcite 来进行查询的解析,校验以及优化。它们可以与 DataStream 和 DataSet API 无缝集成,并支持用户自定义的标量函数,聚合函数以及表值函数。Table API 是以表为中心的声明式编程,其中表可能会动态变化(在表达流数据时)。Table API 遵循(扩展的)关系模型:表有二维数据结构(schema)(类似于关系数据库中的表),同时 API 提供可比较的操作,例如 select、project、join、group-by、aggregate 等。Table API 程序声明式地定义了什么逻辑操作应该执行,而不是准确地确定这些操作代码的看上去如何。

尽管 Table API 可以通过多种类型的用户自定义函数(UDF)进行扩展,其仍不如核心 API 更具表达能力,但是使用起来却更加简洁(代码量更少)。除此之外,Table API 程序在执行之前会经过内置优化器进行优化。Flink 提供的最高层级的抽象是 SQL 。这一层抽象在语法与表达能力上与Table API 类似,但是是以 SQL 查询表达式的形式表现程序。SQL 抽象与 Table API交互密切,同时 SQL 查询可以直接在 Table API 定义的表上执行。

目前 Flink 作为批处理还不是主流,不如 Spark 成熟,所以 DataSet 使用的并不是很多。Flink Table API 和 Flink SQL 也并不完善,大多都由各大厂商自己定制。所以我们主要学习 DataStream API 的使用。实际上 Flink 作为最接近 Google DataFlow模型的实现,是流批统一的观点,所以基本上使用 DataStream 就可以了。

库:Flink 具有数个适用于常见数据处理应用场景的扩展库。这些库通常嵌入在 API 中,且并不完全独立于其它 API。它们也因此可以受益于 API 的所有特性,并与其他库集成。

复杂事件处理(CEP):模式检测是事件流处理中的一个非常常见的用例。Flink 的 CEP 库提供了 API,使用户能够以例如正则表达式或状态机的方式指定事件模式。CEP 库与 Flink 的 DataStream API 集成,以便在 DataStream 上评估模式。CEP 库的应用包括网络入侵检测,业务流程监控和欺诈检测。

DataSet API:DataSet API 是 Flink 用于批处理应用程序的核心 API。DataSet API 所提供的基础算子包括map、reduce、(outer) join、co-group、iterate等。所有算子都有相应的算法和数据结构支持,对内存中的序列化数据进行操作。如果数据大小超过预留内存,则过量数据将存储到磁盘。Flink 的 DataSet API 的数据处理算法借鉴了传统数据库算法的实现,例如混合散列连接(hybrid hash-join)和外部归并排序(external merge-sort)。

Gelly: Gelly 是一个可扩展的图形处理和分析库。Gelly 是在 DataSet API 之上实现的,并与 DataSet API 集成。因此,它能够受益于其可扩展且健壮的操作符。Gelly 提供了内置算法,如 label propagation、triangle enumeration 和 page rank 算法,也提供了一个简化自定义图算法实现的 Graph API。

这么多字能看下来真是辛苦了,简单总结:
Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。
并且
Flink提供了数据分布、容错机制以及资源管理等核心功能。
提供了诸多高抽象层的
API以便用户编写分布式任务:
【DataSetAPI,对静态数据进行批处理操作,支持Java、Scala和Python】。
【DataStreamAPI,对数据流进行流处理操作,支持Java和Scala。】
【TableAPI,对结构化数据进行查询操作,将结构化数据抽象成关系表,并通过类SQL的DSL对关系表进行各种查询操作,支持Java和Scala。】
此外,Flink还针对特定的应用领域提供了领域库,例如:FlinkML,Flink的机器学习
【库,提供了机器学习PipelinesAPI并实现了多种机器学习算法。】
【Gelly,Flink的图计算库,提供了图计算的相关API及多种图计算算法实现。】

1.3.4 flink应用案例

布衣格电信:法国第三大移动通信运营商,使用 Flink 来进行实时事件处理,每天不间断地分析数十亿条消息。布衣格电信利用 Flink 的流处理能力完成了数据处理和数据迁移,它既满足了低延迟的要求,又具有很高的可靠性、可用性,以及易用性。Flink 为调试工作提供了极大的便利,甚至支持切换到本地进行调试。

阿里巴巴:阿里巴巴这个庞大的电子商务集团为买方和卖方提供平台。其在线推荐功能是通过基于 Flink 的系统 Blink 实现的。用户当天所购买的商品可以被用作在线推荐的依据,这是使用像 Flink 这样真正意义上的流处理引擎能够带来的好处之一。并且,这在那些用户活跃度异常高的特殊日期(节假日)尤其重要,也是高效的流处理相较于批处理的优势之一。

King 公司的游戏非常流行,全世界几乎每时每刻都有人在玩它的在线游戏。作为在线娱乐行业的佼佼者,该公司称自己已经开发了 200 多款游戏,市场覆盖 200 多个国家和地区。用 Flink 构建的系统让其数据分析师得以实时地获取大量的流数据。

第二章 案例介绍

2.1 搭建 maven 工程 FlinkDeno

2.1.1 pom 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.offcn</groupId>
    <artifactId>FlinkDeno</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-scala_2.11</artifactId>
            <version>1.7.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.flink/flink-streaming-scala -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-scala_2.11</artifactId>
            <version>1.7.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 该插件用于将 Scala 代码编译成 class 文件 -->
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.4.6</version>
                <executions>
                    <execution>
                        <!-- 声明绑定到 maven 的 compile 阶段 -->
                        <goals>
                            <goal>testCompile</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

2.2 批处理 wordcount

2.2.1 wordcount数据

workcount.txt

spark	hadoop	hive	hive
hive	spark	hbase
mysql	mysql

2.2.2 scala实现

package com.offcn.wordCount

import javax.sql.DataSource
import org.apache.flink.api.scala.{DataSet, ExecutionEnvironment}
import org.apache.flink.api.scala._

object worCountScala {
  def main(args: Array[String]): Unit = {
    //创建执行环境上下文
    val env = ExecutionEnvironment.getExecutionEnvironment
    //读取外部数据
val dataSource: DataSet[String] = 
env.readTextFile("C:\\Users\\thinkpad\\Desktop\\workcount.txt")
    //对数据进行预处理切分
    val wordData: DataSet[String] = dataSource.flatMap(_.split("\t"))
    //对数据进行聚合
    val wordAndCount: AggregateDataSet[(String,Int)] = wordData.map((_,1)).groupBy(0).sum(1)
    //打印
    wordAndCount.print()
  }
}

2.2.3 java实现

package com.offcn.wordCount;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.operators.AggregateOperator;
import org.apache.flink.api.java.operators.DataSource;
import org.apache.flink.api.java.operators.FlatMapOperator;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;

public class wordCountJava {
    public static void main(String[] args) throws Exception {
        //创建执行环境上下文
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        //读取外部数据
        DataSource<String> dataSource = 
env.readTextFile("C:\\Users\\thinkpad\\Desktop\\workcount.txt");
        //对数据进行预处理切分
        FlatMapOperator<String, Tuple2<String, Integer>> wordAndOne = dataSource.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
            public void flatMap(String words, Collector<Tuple2<String, Integer>> collector) throws Exception {
                String[] wordArr = words.split("\t", -1);
                for (String word : wordArr) {
                    collector.collect(new Tuple2<String, Integer>(word, 1));
                }
            }
        });
        //对数据进行聚合
        AggregateOperator<Tuple2<String, Integer>> wordAndCount = wordAndOne.groupBy(0).sum(1);
        //打印
        wordAndCount.print();
    }
}

2.3 流处理 wordcount

2.3.1 scala实现

package com.offcn.wordCount

import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
import org.apache.flink.api.scala._

object wordCountScalaStream {
  def main(args: Array[String]): Unit = {
    //创建运行环境上下文
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    //读取数据源数据
    val sourceData: DataStream[String] = env.socketTextStream("linux01",9999)
    //对数据进行预处理切分
    val words: DataStream[String] = sourceData.flatMap(_.split("\t",-1))
    //进行聚合
    val wordAndCount: DataStream[(String, Int)] = words.map((_,1)).keyBy(0).sum(1)
    //打印
    wordAndCount.print()
    //提交程序运行
    env.execute("wordCountScalaStream")
  }
}
测试——在 linux 系统中用 netcat 命令进行发送测试。
nc -lk 9999

netcat 安装教程以及地址点击获取

2.3.2 java实现

package com.offcn.wordCount;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;

public class wordCountJavaStream {
    public static void main(String[] args) throws Exception {
        //创建运行环境上下文
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //读取数据源数据
        DataStreamSource<String> sourceData = env.socketTextStream("linux01", 9999);
        //对数据进行预处理切分
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordAndOne = sourceData.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
            public void flatMap(String words, Collector<Tuple2<String, Integer>> collector) throws Exception {
                String[] wordArr = words.split("\t", -1);
                for (String word : wordArr) {
                    collector.collect(new Tuple2<String, Integer>(word, 1));
                }
            }
        });
        //进行聚合
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordAndCount = wordAndOne.keyBy(0).sum(1);
        //打印
        wordAndCount.print();
        //提交程序运行
        env.execute("wordCountJavaStream");
    }
}

第三章Flink 部署

Flink支持多种安装模式:
local(本地)——单机模式,一般不使用
standalone——独立模式,Flink自带集群,开发测试环境使用
yarn——计算资源统一由Hadoop YARN管理,生产环境测试
Kubernetes——容器化部署时目前业界很流行的一项技术,基于Docker镜像运行能够让用户更加方便地对应用进行管理和运维。

3.1 Standalone 模式

3.1.1 安装

下载网址:https://archive.apache.org/dist/flink/flink-1.7.0/
上传flink包到/opt/software目录下
解压缩 flink-1.7.0-bin-hadoop27-scala_2.11.tgz

tar -xvzf flink-1.7.0-bin-hadoop27-scala_2.11.tgz -C /opt/module

进入 conf 目录中。

cd /opt/module/

1)修改 flink/conf/flink-conf.yaml 文件:(修改自己的哈)

jobmanager.rpc.address: linux01

在这里插入图片描述
2)修改 /conf/slave 文件:
在这里插入图片描述
3)分发给另外两台机子:

scp -r flink-1.7.0 linux02:$PWD
scp -r flink-1.7.0 linux03:$PWD

4)启动:

./start-cluster.sh 

访问 http://linux01:8081 可以对 flink 集群和任务进行监控管理。
在这里插入图片描述

3.1.2 提交任务

  1. 准备数据文件
    词频统计数据.txt
hadoop	spark	spark
mapreduce	mapreduce
hadoop

2)把含数据文件的文件夹,分发到 taskmanage 机器中
由于读取数据是从本地磁盘读取,实际任务会被分发到 taskmanage 的机器中,
所以要把目标文件分发。
3)执行程序

./flink run -c com.offcn.wordCount.wordCountJava 
/root/flinkJar/FlinkDeno-1.0-SNAPSHOT-jar-with-dependencies.jar 	/opt/module/flink-1.7.0/flink/data/wordcount.txt /opt/module/flink-1.7.0/flink/wordcount

在这里插入图片描述

4)到目标文件夹中查看计算结果
注意:计算结果根据会保存到 taskmanage 的机器下,不会在 jobmanage 下。
5)在 webui 控制台查看计算过程
在这里插入图片描述
6)集群架构
在这里插入图片描述
client客户端提交任务给JobManager hadoop fs -mkdir -p /test/input
JobManager负责Flink集群计算资源管理,并分发任务给TaskManager执行
TaskManager定期向JobManager汇报状态

查看当前运行的任务

bin/flink list

停止当前任务

bin/flink cancel 471ede242bd2fa22d32ed147a025e5d2

查看所有的任务包括取消的

bin/flink list --all

3.1.3 高可用HA模式

JobManager单节点存在单点故障 ,一旦JobManager出现意外,整个集群无法工作。所以,为了确保集群的高可用,需要搭建Flink的HA。(如果是部署在YARN上,部署YARN的HA),我们这里演示如何搭建Standalone 模式HA。
1)架构图如下:
在这里插入图片描述
2)在flink-conf.yaml中添加zookeeper配置

#开启HA,使用文件系统作为快照存储 
state.backend: filesystem 
#启用检查点,可以将快照保存到HDFS 
state.backend.fs.checkpointdir: hdfs://linux01:9000/flink-checkpoints 
#使用zookeeper搭建高可用 
high-availability: zookeeper 
# 存储JobManager的元数据到HDFS 
high-availability.storageDir: hdfs://linux01:9000/flink/ha/ 
high-availability.zookeeper.quorum: linux01:2181,linux02:2181,linux03:2181 

3)将配置过的HA的 flink-conf.yaml 分发到另外两个节点

scp -r /opt/module/flink-1.7.0/conf/flink-conf.yaml linux02:$PWD
scp -r /opt/module/flink-1.7.0/conf/flink-conf.yaml linux03:$PWD

4)到linux02中修改flink-conf.yaml中的配置,将JobManager设置为自己节点的名称

jobmanager.rpc.address: linux02

5)在 masters 配置文件中添加多个节点

linux01:8081
linux02:8082

6)分发masters配置文件到另外两个节点

scp /opt/module/flink-1.7.0/conf/masters linux02:$PWD
scp /opt/module/flink-1.7.0/conf/masters linux03:$PWD

7)启动 zookeeper 集群
8)启动 HDFS 集群
9)启动 flink 集群
10)分别查看两个节点的Flink Web UI
11)kill掉一个节点,查看另外的一个节点的Web UI

中间有出现什么问题请带上答案留言指正,哈。

❤ღ( ´・ᴗ・` )比心

未完,一定敲敲敲着去理解,下篇继续更新大数据其他内容,谢谢观看

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值