Flink中的DataStream程序是对数据流进行转换的常规程序(例如,过滤,更新状态,定义窗口,聚合)。数据流的最初的源可以从各种来源(例如,消息队列,套接字流,文件)创建,并通过sink返回结果,例如可以将数据写入文件或标准输出。Flink程序以各种上下文运行,独立或嵌入其他程序中。执行可能发生在本地JVM或许多机器的集群上。
一,套接字流
下面举一个例子,该例子,数据来源是网络套接字,带窗口的流处理,窗口大小是5s,这些概念玩过spark Streaming应该都很清楚,我们后面也会给大家详细讲解。
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
/**
* Created by spark on 2017/8/31.
*/
object WindowWordCount {
object WindowWordCount {
def main(args: Array[String]) {
val env = StreamExecutionEnvironment.getExecutionEnvironment
val text = env.socketTextStream("localhost", 9999)
val counts = text.flatMap { _.toLowerCase.split("\\W+") filter { _.nonEmpty } }
.map { (_, 1) }
.keyBy(0)
.timeWindow(Time.seconds(5))
.sum(1)
counts.print
env.execute("Window Stream WordCount")
}
}
}
要测试该demo,首先要启动一个tcp server监听9999端口,这里可以使用netcat。
nc -lk 9999
这样就可以用nc统计,然后DataStream输出结果。根据不同的模式会有不同的输出位置,提交到集群的话,要去日志里查看。
该代码可以直接粘贴复制到你自己的工程,只需要导入Flink的相关依赖,具体工程构建方法,请参考<构建Flink工程及demo演示>。
二,数据转换
数据转换将一个或多个数据流转换成新的DataStream。 程序可以将多种转换组合成复杂的拓扑结构。
下面介绍常用的操作,然后举例讲解。
1,map操作
DataStream → DataStream
取出一个元素,产生一个元素。比如,使用map将数据元素乘以2.
dataStream.map { x => x * 2 }
2,FlatMap
DataStream → DataStream
取出一个元素,产生零个,一个,或者多个元素。比如,可以使用flatmap分割句子。
dataStream.flatMap { str => str.split(" ") }
3,Filter
DataStream → DataStream
每个函数都去执行一个布尔函数,并保留使得布尔函数返回为true的元素。
过滤零值的函数。
dataStream.filter { _ != 0 }
4,KeyBy
DataStream → KeyedStream
将流逻辑分区为不相交的分区,每个分区包含相同key的元素。在内部,这是用哈希分区来实现的。看上篇文章来了解如何指定一个key。
dataStream.keyBy("someKey") // Key by field "someKey"
dataStream.keyBy(0) // Key by the first element of a Tuple
5,Reduce
KeyedStream → DataStream
滚动的聚合keyedStream.将当前元素和上一个聚合的元素进行合并,返回一个新的值。
比如,将相同key的值进行求和。
keyedStream.reduce { _ + _ }
6,Fold
KeyedStream → DataStream
滚动聚合一个KeyedStream,需要指定一个初始值。合并当前的值和前一次合并过(floded)的值,返回一个新值。
比如,下面的折叠函数,假如作用于一个序列(1,2,3,4,5),会返回一个序列:"start-1", "start-1-2", "start-1-2-3", ...
val result: DataStream[String] =
keyedStream.fold("start")((str, i) => { str + "-" + i })
7,Aggregations
KeyedStream → DataStream
KeyedStream 进行滚动聚合。min和minBy之间的区别在于min返回最小值,而minBy返回该字段中具有最小值的元素(对于max和maxBy相同)。
keyedStream.sum(0)
keyedStream.sum("key")
keyedStream.min(0)
keyedStream.min("key")
keyedStream.max(0)
keyedStream.max("key")
keyedStream.minBy(0)
keyedStream.minBy("key")
keyedStream.maxBy(0)
keyedStream.maxBy("key")
8,Window
KeyedStream → WindowedStream
作用于partitioned KeyedStreams.根据一些特性(如,最近五分钟的数据)进行按key分组。
dataStream.keyBy(0).window(TumblingEventTimeWindows.of(Time.seconds(5))) // Last 5 seconds of data
对于windows操作后面会出文章详细介