Flink学习记录(一)

基本上来自官网的翻译

flink抽象层次

这里写图片描述
flink启动后,会启动一个 JobManger 和一个或多个的 TaskManager。由 Client 提交任务给 JobManager,JobManager 再调度任务到各个 TaskManager 去执行,然后 TaskManager 将心跳和统计信息汇报给 JobManager。TaskManager 之间以流的形式进行数据的传输。

取决于数据源的类型,静态或非静态的数据源,可以使用DataSet API做批处理操作或DataStream API做流处理操作
每一个程序包含一些同样的组成:1.执行环境 2.load/create 初始数据 3.指定数据的转换方式 4. 指定计算结果存放位置 5. 触发程序执行
DataSet API在包org.apache.flink.api.scala.中
DataStream API在org.apache.flink.streaming.api.scala.中

通过以下方式之一创建执行环境
getExecutionEnvironment()
createLocalEnvironment()
createRemoteEnvironment(host: String, port: Int, jarFiles: String*)

getExecutionEnvironment()会根据程序运行的状态自动选择创建合适的上下文,比如在IDE中调试将会创建local environment,如果通过命令调用Jar包方式,flink cluseter manager对执行jar包的main方法,调用getExecutionEnvironment()并且返回集群环境的运行环境。
运行环境有几个方法一个读取文件

val env = StreamExecutionEnvironment.getExecutionEnvironment()
val text: DataStream[String] = env.readTextFile(“file:///path/to/file”)

execute()方法返回JobExecutionResult,包好执行的次数和累计结果,

整个flink程序都是lazy的,只有当显示的调用execute()时才会真正的执行

指定Keys

一些转换(join, coGroup, keyBy, groupBy)需要给集合定义一个key,其他转换(Reduce, GroupReduce, Aggregate, Windows)可以在处理之前根据key来分组

使用字段表达数定义keys(POJO和Tuple类型)

case class WC(word: String, count: Int)
val words: DataStream[WC] = // […]
val wordCounts = words.keyBy(“word”).window(/window specification/)

也可以选择POJO和Tuple嵌套的字段,例如

class WC(var complex: ComplexNestedClass, var count: Int) {
def this() { this(null, 0) }
}
class ComplexNestedClass(
var someNumber: Int,
someFloat: Float,
word: (Long, Long, String),
hadoopCitizen: IntWritable) {
def this() { this(0, 0, (0, 0, “”), new IntWritable(0)) }
}
选择word的第一个字段作为key,可以用complex.word._1

使用key selector定义key

case class WC(word: String, count: Int)
val words: DataStream[WC] = // […]
val keyed = words.keyBy( _.word )

指定转换函数

lamabda函数

val data: DataSet[String] = // […]
data.filter { _.startsWith(“http://”) }
val data: DataSet[Int] = // […]
data.reduce { (i1,i2) => i1 + i2 }
// or
data.reduce { _ + _ }

Rich functions

data.map { x => x.toInt }
可以改写成
class MyMapFunction extends RichMapFunction[String, Int] {
def map(in: String):Int = { in.toInt }
})
data.map(new MyMapFunction())

提供Rich functions是为了可以使用用户自定义函数(map, reduce, etc)和四个方法(open, close, getRuntimeContext, and setRuntimeContext)。这对于参数化方法是很有用的,creating and finalizing local state,访问广播变量,访问运行时信息如accumulators and counters和information on iterations

支持的数据类型

六种不同的数据类型:

  • Java Tuples and Scala Case Classes
  • Java POJOs
  • Primitive Types
  • Regular Classes
  • Values
  • Hadoop Writables
  • Special Types
Tuples and Case Classes

case class WordCount(word: String, count: Int)
val input = env.fromElements(
WordCount(“hello”, 1),
WordCount(“world”, 2)) // Case Class Data Set
input.keyBy(“word”)// key by field expression “word”
val input2 = env.fromElements((“hello”, 1), (“world”, 2)) // Tuple2 Data Set
input2.keyBy(0, 1) // key by field positions 0 and 1

POJOs

class WordWithCount(var word: String, var count: Int) {
def this() {
this(null, -1)
}
}
val input = env.fromElements(
new WordWithCount(“hello”, 1),
new WordWithCount(“world”, 2)) // Case Class Data Set
input.keyBy(“word”)// key by field expression “word”

Primitive Types

例如Integer, String, and Double.

General Class Types

所有没有被定义为POJO类型的类都被作为通用类型(可序列化),flink把它看作黑盒,并且不能访问其中的内容。使用Kryo序列化

Values
Hadoop Writables

可以使用实现 org.apache.hadoop.Writable的类型,序列化的逻辑在write()和readFields() 方法中

Special Types

可以使用Scala的Either, Option和Try。Either 对于错误处理或操作时需要输出到两种不同记录类型的情况很有用

Accumulators 和 Counters

private IntCounter numLines = new IntCounter();
getRuntimeContext().addAccumulator(“num-lines”, this.numLines);
this.numLines.add(1);//可以在任何操作中使用,包括open()和close()

广播变量

让一个数据集对所有并行操作的示例可见
注册withBroadcastSet(DataSet, String)
访问getRuntimeContext().getBroadcastVariable(String)

// 1. The DataSet to be broadcasted
val toBroadcast = env.fromElements(1, 2, 3)
val data = env.fromElements(“a”, “b”)
data.map(new RichMapFunctionString, String {
var broadcastSet: Traversable[String] = null

override def open(config: Configuration): Unit = {
  // 3. Access the broadcasted DataSet as a Collection
  broadcastSet = getRuntimeContext().getBroadcastVariable[String]("broadcastSetName").asScala
}

def map(in: String): String = {
    ...
}}).withBroadcastSet(toBroadcast, "broadcastSetName") // 2. Broadcast the DataSet

分布式缓存

flink执行时会自动拷贝文件到所有worker节点的本地文件系统

val env = ExecutionEnvironment.getExecutionEnvironment
// register a file from HDFS
env.registerCachedFile(“hdfs:///path/to/your/file”, “hdfsFile”)
// register a local executable file (script, executable, …)
env.registerCachedFile(“file:///path/to/exec/file”, “localExecFile”, true)
// define your program and execute

val input: DataSet[String] = …
val result: DataSet[Integer] = input.map(new MyMapper())

env.execute()

// extend a RichFunction to have access to the RuntimeContext
class MyMapper extends RichMapFunction[String, Int] {
override def open(config: Configuration): Unit = {
// access cached file via RuntimeContext and DistributedCache
val myFile: File = getRuntimeContext.getDistributedCache.getFile(“hdfsFile”)
// read the file (or navigate the directory)

}
override def map(value: String): Int = {
// use content of cached file

}
}

参考:http://www.open-open.com/lib/view/open1462323115590.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值