前几篇博客给大家讲解了Flink的运行时架构与环境搭建等Flink专栏今天正式给大家讲解下代码入门的DataSource。
记得刚学Hadoop中的MapReduce的时候第一个编写的代码就是WordCount,但是使用MapReduce编写wordCount的时候代码大约有三四十行代码吧,后来又用Spark实现WordCount代码只有三四行代码。那为什么还要学习Flink那?Flink专栏
导入maven包
<properties>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<encoding>UTF-8encoding>
<scala.version>2.11.2scala.version>
<scala.compat.version>2.11scala.compat.version>
<hadoop.version>2.6.0hadoop.version>
<flink.version>1.7.2flink.version>
<scala.binary.version>2.11scala.binary.version>
<iheart.version>1.4.3iheart.version>
<fastjson.version>1.2.7fastjson.version>
properties>
<dependencies>
<dependency>
<groupId>org.scala-langgroupId>
<artifactId>scala-libraryartifactId>
<version>${scala.version}version>
dependency>
<dependency>
<groupId>org.apache.flinkgroupId>
<artifactId>flink-streaming-scala_2.11artifactId>
<version>${flink.version}version>
dependency>
<dependency>
<groupId>org.apache.flinkgroupId>
<artifactId>flink-scala_2.11artifactId>
<version>${flink.version}version>
dependency>
<dependency>
<groupId>org.apache.flinkgroupId>
<artifactId>flink-clients_2.11artifactId>
<version>${flink.version}version>
dependency>
<dependency>
<groupId>org.apache.flinkgroupId>
<artifactId>flink-table_2.11artifactId>
<version>${flink.version}version>
dependency>
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-clientartifactId>
<version>${hadoop.version}version>
<exclusions>
<exclusion>
<groupId>xml-apisgroupId>
<artifactId>xml-apisartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.38version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.60version>
dependency>
<dependency>
<groupId>com.jayway.jsonpathgroupId>
<artifactId>json-pathartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>org.apache.flinkgroupId>
<artifactId>flink-connector-kafka-0.11_2.11artifactId>
<version>${flink.version}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.9version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.9.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.modulegroupId>
<artifactId>jackson-module-scala_2.11artifactId>
<version>2.9.9version>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.7.1version>
dependency>
<dependency>
<groupId>org.apache.bahirgroupId>
<artifactId>flink-connector-redis_2.11artifactId>
<version>1.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>net.alchim31.mavengroupId>
<artifactId>scala-maven-pluginartifactId>
<version>3.2.2version>
<executions>
<execution>
<goals>
<goal>testCompilegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-assembly-pluginartifactId>
<version>3.0.0version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependenciesdescriptorRef>
descriptorRefs>
configuration>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
准备数据
hello word hello word
hello flink hello spark
hello kafka hello java
import org.apache.flink.api.scala._
/**
* @author 批处理wordCount
* @date 2020/8/23 23:03
* @version 1.0
*/
object WordCount {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env: ExecutionEnvironment = ExecutionEnvironment.getExecutionEnvironment
//2.从文件中读取数据
//2.1 设置读取文件的路劲
val inputPath: String ="./data/wordcount.txt"
val data: DataSet[String] = env.readTextFile(inputPath)
//3.根据单词进行分组,然后进行sum求和
//3.1使用FlatMap进行单词分词
val dataFlatMap = data.flatMap(_.split(" "))
//3.2将切分出来的单词进行添加1
val dataMap = dataFlatMap.map((_, 1))
//3.3 按照单词进行分组
val dataGrepBy = dataMap.groupBy(0)
//3.4 分组后求和
val dataSum = dataGrepBy.sum(1)
//4.打印输出
dataSum.print()
}
}
Data Sources 是什么呢?就字面意思其实就可以知道:数据来源。
Flink 做为一款流式计算框架,它可用来做批处理,即处理静态的数据集、历史的数据 集;也可以用来做流处理,即实时的处理些实时数据流,实时的产生数据流结果,只要数据 源源不断 的过来,Flink 就能够一直计算下去,这个 Data Sources 就是数据的来源地。 flink 在批处理中常见的 source 主要有两大类。
1、使用 env.fromElements(),这种方式也支持 Tuple,自定义对象等复合形式。
import org.apache.flink.api.scala._
import scala.collection.mutable
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
/**
* @author 使用FromElements来读取集合中的数据
* @date 2020/8/26 23:00
* @version 1.0
*/
object BachFromElements {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.使用FromElements构建数据流字符串
val strData: DataSet[String] = env.fromElements("1", "2", "3")
strData.print()
//3.使用FromElements构建数据流 tuple
val tupleData: DataSet[(String, Int)] = env.fromElements(("张三", 1), ("李四", 2))
tupleData.print()
//4.使用FromElements构建数据流 Array
val arrayData: DataSet[Array[String]] = env.fromElements(Array("张三", "李四", "王五", "赵刘"))
arrayData.print()
//5.使用FromElements构建数据流ArrayBuffer
val arrayBufferData = env.fromElements(ArrayBuffer("张三", "李四", "王五", "赵刘"))
arrayBufferData.print()
//6.使用FromElements构建数据流List
val listData = env.fromElements(List("张三", "李四", "王五", "赵刘"))
listData.print()
//7.使用FromElements构建数据流ListBuffer
val listBufferData = env.fromElements(ListBuffer("张三", "李四", "王五", "赵刘"))
listBufferData.print()
//8.使用FromElements构建数据流Vector
val vectorData = env.fromElements(Vector("张三", "李四", "王五", "赵刘"))
vectorData.print()
//9.使用FromElements构建数据流Queue
val queueData = env.fromElements(mutable.Queue("张三", "李四", "王五", "赵刘"))
queueData.print()
//10.使用FromElements构建数据流Stack
val stackData = env.fromElements(mutable.Stack("张三", "李四", "王五", "赵刘"))
stackData.print()
//11.使用FromElements构建数据流Stream
val StreamData = env.fromElements(Stream("张三", "李四", "王五", "赵刘"))
StreamData.print()
//12.使用FromElements构建数据流Seq
val seqData = env.fromElements(Seq("张三", "李四", "王五", "赵刘"))
seqData.print()
//13.使用FromElements构建数据流Set
val SetData = env.fromElements(Set("张三", "李四", "王五", "赵刘"))
SetData.print()
//14.使用FromElements构建数据流Iterable
val iterableData = env.fromElements(Iterable("张三", "李四", "王五", "赵刘"))
iterableData.print()
//15.使用FromElements构建数据流Iterable
val arraySeqData = env.fromElements(mutable.ArraySeq("张三", "李四", "王五", "赵刘"))
arraySeqData.print()
//16.使用FromElements构建数据流ArrayStack
val arrayStackData = env.fromElements(mutable.ArrayStack("张三", "李四", "王五", "赵刘"))
arrayStackData.print()
//17.使用FromElements构建数据流Map
val mapData = env.fromElements(Map("张三" -> 1, "李四" -> 2))
mapData.print()
//18.使用FromElements构建数据流range
val rangeData = env.fromElements(Range(1, 10))
rangeData.print()
}
}
2、使用 env.fromCollection(),这种方式支持多种 Collection 的具体类型
3、使用 env.generateSequence()方法创建基于 Sequence 的 DataSet
import org.apache.flink.api.scala._
/**
* @author 使用FromCollection与generateSequence 构建数据集
* @date 2020/8/27 22:24
* @version 1.0
*/
object BachFromCollectionASGenerateSequence {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.使用FromCollection构建Array数据集 设置并行度为1
val arrayData = env.fromCollection(Array("张三", 1, "李四", 2)).setParallelism(1)
arrayData.print()
//3.使用generateSequence构建数据集 类似于range(1,4)
val data = env.generateSequence(1, 4).setParallelism(1)
data.print()
}
}
2.2.1读取本地文件(txt)
import org.apache.flink.api.scala._
/**
* @author 读取本地文件
* @date 2020/8/27 22:31
* @version 1.0
*/
object BachSourceFromFileAsLocalText {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.读取本地文件
val data = env.readTextFile("./data/wordcount.txt")
//3.接结果输出
data.print()
}
}
2.2.2读取 HDFS 数据(txt)
import org.apache.flink.api.scala._
/**
* @author 读取HDFS 数据
* @date 2020/8/27 22:31
* @version 1.0
*/
object BachSourceFromFileAsLocalText {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.读取本地文件
val data = env.readTextFile("hdfs://node01:8020/wordCount.txt")
data.print()
}
}
2.2.3读取 CSV 数据
我们对csv文件操作的时候往往有时候需要表头的但是有时候也不需要表头的。所以我在这里给大家将2中方式第一种是带表头的,第二种是不带表头的。
根据源码显示:ignoreFirstLine 为true的时候是不带表头的,(默认是带表头的)所以我们可以根据实际情况来判断 ignoreFirstLine 为true还是为false
import org.apache.flink.api.scala._
/**
* @author 读取本地文件csv 第一个需要表头 第二种不需要表头
* @date 2020/8/27 22:33
* @version 1.0
*/
object BachSourceFileAsLocalCsv {
case class user(name:String,age:String)
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.读取数据本地csv文件带表头
// 注意:读取csv文件是必须定义一个对象来接收负责报错
val headData = env.readCsvFile[user]("./data/user.csv",fieldDelimiter = ",")
//3.读取数据本地csv文件不带表头 默认是带头部的
val notHeadData = env.readCsvFile[user]("./data/user.csv",fieldDelimiter = ",",ignoreFirstLine = true)
//4.分别输出
headData.print()
notHeadData.print()
}
}
2.2.4读取压缩文件
flink 支持对一个文件目录内的所有文件,包括所有子目录中的所有文件的遍历访问方 式。对于从文件中读取数据,当读取的数个文件夹的时候,嵌套的文件默认是不会被读取的, 只会读取第一个文件,其他的都会被忽略。所以我们需要使用 recursive.file.enumeration 进 行递归读取。
注意:上述讲解的都使用迭代的方式进行获取数据。
import org.apache.flink.api.scala._
import org.apache.flink.configuration.Configuration
/**
* @author 读取本地的zip文件
* @date 2020/8/27 22:57
* @version 1.0
*/
object BachSourceFromAsLocalZip {
def main(args: Array[String]): Unit = {
//1.构建运行环境
val env = ExecutionEnvironment.getExecutionEnvironment
//2.开启递归
val parameters = new Configuration()
parameters.setBoolean("recursive.file.enumeration",true)
//2.读取zip文件
val zipData = env.readTextFile("./data/wordcount.txt.gz").withParameters(parameters)
//3.结果输出
zipData.print()
}
}