支持的數據類型
Flink流應用程序處理的是以數據對象表示的事件流。所以在Flink內部,我們需要能夠處理這些對象。它們需要被序列化和反序列化,以便通過網絡傳送它們;或者從狀態後端、檢查點和保存點讀取它們。爲了有效地做到這一點,Flink需要明確知道應用程序所處理的數據類型。Flink使用類型信息的概念來表示數據類型,併爲每個數據類型生成特定的序列化器、反序列化器和比較器。
Flink還具有一個類型提取系統,該系統分析函數的輸入和返回類型,以自動獲取類型信息,從而獲得序列化器和反序列化器。但是,在某些情況下,例如lambda函數或泛型類型,需要顯式地提供類型信息,才能使應用程序正常工作或提高其性能。
Flink支持Java和Scala中所有常見數據類型。使用最廣泛的類型有以下幾種。
基礎數據類型
Flink支持所有的Java和Scala基礎數據類型,Int, Double, Long, String。。。
val numbers: DataStream[Long] = env.fromElements(1L, 2L, 3L, 4L)
numbers.map( n => n + 1 )
Java和Scala元組(Tuples)
val persons: DataStream[(String, Integer)] = env.fromElements(
("Adam", 17),
("Sarah", 23) )
persons.filter(p => p._2 > 18)
Scala樣例類(case classes)
case class Person(name: String, age: Int)
val persons: DataStream[Person] = env.fromElements(
Person("Adam", 17),
Person("Sarah", 23) )
persons.filter(p => p.age > 18)
Java簡單對象(POJOs)
public class Person {
public String name;
public int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
DataStream<Person> persons = env.fromElements(
new Person("Alex", 42),
new Person("Wendy", 23));
其它(Arrays, Lists, Maps, Enums, 等等)
Flink對Java和Scala中的一些特殊目的的類型也都是支持的,比如Java的ArrayList,HashMap,Enum等等。
函數類(Function Classes)
Flink暴露了所有udf函數的接口(實現方式爲接口或者抽象類)。例如MapFunction, FilterFunction, ProcessFunction等等。
class FilterFilter extends FilterFunction[String] {
override def filter(value: String): Boolean = {
value.contains("flink")
}
}
val flinkTweets = tweets.filter(new FlinkFilter)
還可以將函數實現成匿名類
val flinkTweets = tweets.filter(
new RichFilterFunction[String] {
override def filter(value: String): Boolean = {
value.contains("flink")
}
}
)
我們filter的字符串"flink"還可以當作參數傳進去。
val tweets: DataStream[String] = ...
val flinkTweets = tweets.filter(new KeywordFilter("flink"))
class KeywordFilter(keyWord: String) extends FilterFunction[String] {
override def filter(value: String): Boolean = {
value.contains(keyWord)
}
}
匿名函數(Lambda Functions)
val tweets: DataStream[String] = ...
val flinkTweets = tweets.filter(_.contains("flink"))
富函數(Rich Functions)
“富函數”是DataStream API提供的一個函數類的接口,所有Flink函數類都有其Rich版本。它與常規函數的不同在於,可以獲取運行環境的上下文,並擁有一些生命週期方法,所以可以實現更復雜的功能。
RichMapFunction
RichFlatMapFunction
RichFilterFunction
Rich Function有一個生命週期的概念。典型的生命週期方法有:
- open()方法是rich function的初始化方法,當一個算子例如map或者filter被調用之前open()會被調用。
- close()方法是生命週期中的最後一個調用的方法,做一些清理工作。
- getRuntimeContext()方法提供了函數的RuntimeContext的一些信息,例如函數執行的並行度,任務的名字,以及state狀態
class MyFlatMap extends RichFlatMapFunction[Int, (Int, Int)] {
var subTaskIndex = 0
override def open(configuration: Configuration): Unit = {
subTaskIndex = getRuntimeContext.getIndexOfThisSubtask
// 以下可以做一些初始化工作,例如建立一個和HDFS的連接
}
override def flatMap(in: Int, out: Collector[(Int, Int)]): Unit = {
if (in % 2 == subTaskIndex) {
out.collect((subTaskIndex, in))
}
}
override def close(): Unit = {
// 以下做一些清理工作,例如斷開和HDFS的連接。
}
}