DataStream API 一 之 DataStream 编程模型
一.DataSource
1.1 内部数据源
1.1.1 文件 数据源
val textStream =env.readTextFile("/User/local/data_example.log")
1.1.2 Socket 数据源
val sockectDataStream =env.socketTextStream("localhost",9999)
1.1.3 集合 数据源
//fromElements
val dataStream =env.fromElements(Tuple2(1L,3L),Tuple2(1L,5L),Tuple2(1L,7L),Tuple2(1L,4L),Tuple2(1L,2L))
//fromCollection
String[] elements =new String[]{"hello","flink"};
DataStream<String> dataStream =env.fromCollection(Arrays.asList(elements));
1.2 外部数据源
1.2.1 数据源连接器
通过StreamExecutionEnvironment.addSource(sourceFunction)来为你的程序添加一个官方提供的source。
官方内置Connectors有如下:
• Kafka
• Elasticsearch
• Hadoop FileSystem
• RabbitMQ
• Apache ActiveMQ
• Redis
1.2.2 自定义数据源连接器
① 通过实现sourceFunction接口来自定义无并行度的source
② 也可以通过实现ParallelSourceFunction 接口 or 继承RichParallelSourceFunction 来自定义有并行度的source
二.DataStream Translate
2.1 Single-DataStrem
2.1.1 Map
[DataStream -> DataStream]
val dataStream =env.fromElements(("a",3),("d",4),("c",2),("c",5),("a",5))
val mapStream:DataStream[(String,Int)]=dataStream.map(t=>(t._1,t._2+1))
2.1.2 FlatMap
[DataStream -> DataStream]
val resultStream[String]=dataStream.flatMap{str => str.split(" ")}
2.1.3 Filter
[DataStream -> DataStream]
val filter:DataStream[Int]=dataStream.fliter{_ %2 == 0 }
val filter:DataStream[Int]=dataStream.fliter{x => x %2 == 0 }
2.1.4 KeyBy
[DataStream -> KeyedStream]
2.1.5 Reduce
[ KeyedStream -> DataStream]
val dataStream =env.fromElements(("a",3),("d",4),("c",2),("c",5),("a",5))
val KeyedStream:KeyedStream[(String,Int),Tuple]=dataStream.keyby(0)
val reduceStream =keyedStream.reduce{(t1,t2) => (t1._1,t1._2+t2._2)}
//通过实现ReduceFunction 匿名类
val reduceStream1=keyedStream.reduce(new ReduceFuncation[(String,Int)] {
override def reduce(t1:(String,Int),t2:(String,Int):(String,Int)={
(t1._1,t1._2+t2._2)
}})
2.1.6 Aggregations
[ KeyedStream -> DataStream]
聚合算子,聚合操作有 sum(),min(),max(),minBy(),maxBy()
val dataStream =env.fromElements((1,5),(2,2),(2,4),(1,3))
val keyedStream:KeyedSream[(Int,Int),Tuple] = dataStream.keyBy(0)
val sumStream:DataStream[(Int,Int)]=keyedSream.sum(1)
sumStream.print()
//输出结果是将每条记录所叠加的结果输出
//key=1 (1,5) (1,8)
//key=2 (2,2) (2,6)
2.2 Multi-DataStrem
2.2.1 Union
[ DataStream -> DataStream]
Union 算子主要是将两个或者多个输入的数据集合并成一个数据集,需要保证两个数据集的格式一致,输出的数据集的格式和输入的数据集格式保持一致。
//创建相同数据类型的多个数据集
val dataStream1 : DataStream[(String,Int)]=env.fromElements(("a",3),("d",4),("c",2),("c",5),("a",5))
val dataStream2 : DataStream[(String,Int)]=env.fromElements(("d",1),("s",2),("a",4),("e",5),("a",6))
val dataStream3 : DataStream[(String,Int)]=env.fromElements(("a",2),("d",1),("s",2),("c",3),("b",1))
//合并两个DataStream数据集
val unionStream =dataStream1.union(data_Stream2)
//合并多个DataStream数据集
val allUnionStream =dataStream1.union(data_Stream2,data_Stream3)
2.2.2 Connect,CoMap,CoFlatMAp
[ DataStream -> DataStream]
Connect 算子主要是为了合并两种或者多种不同数据类型的数据集,合并后会保留原来数据集的数据类型。
//创建不同的数据类型额数据集
val dataStream1 : DataStream[(String,Int)]=env.fromElements(("a",3),("d",4),("c",2),("c",5),("a",5))
val dataStream2:DataStream[Int]=env.fromElements(1,2,4,5,6)
//连接两个DataStream 数据集
val connectStream:ConnectedStreams[(String,Int),Int]=dataStream1.connect(dataStream2)
//通过定义CoMapFunction处理ConnectedStreams数据集中的数据
val resultStream =connectedStream.map(new CoMapFunction[(String,Int),Int,(Int,String)]{
//定义第一个数据集函数处理逻辑,输入值为第一个DataStream
override def map1(in1:(String,Int)):(Int,String)={
(in1._2,in1._1)
}
//定义第二个数据集函数处理逻辑,输入值为第一个DataStream
override def map2(in2:Int):(Int,String)={
(in2,"default")
}
})
//通过定义CoFlatMapFunction处理ConnectedStreams数据集中的数据
val resultStream2 =connectedStream.flatmap(new CoFlatMapFunction[(String,Int),Int,(String,Int,Int)]{
//定义共享变量
var number=0
//定义第一个数据集函数处理逻辑
override def flatmap1(in1:(String,Int),collector:Collector[(String,Int,Int)]):Unit={
collector.collect((in1._1,in1._2,number))
}
//定义第二个数据集函数处理逻辑
override def flatmap2(in2:Int,collector:Collector[(String,Int,Int)]):Unit={
number=in2
}
})
//通过keyby 函数根据指定的key连接两个数据集
val keyedConnect:ConnectedStrams[(String,Int),Int]=dataStream.connect(dataStream2).keyBy(1,0)
//通过broadcast关联两个数据集
val broadcatConnect:BroadcastConnectedStream[(String,Int),Int]=dataStream1.connect(dataStream2.broadcast())
2.2.3 Split
[ DataStream -> SplitStream] 拆分
2.2.4 Select
[ SplitStream -> DataStream] 仅标记不拆分
2.2.5 Iterate
[ DataStream -> IterativeStream -> DataStream]
2.2.6 Aggregations
2.3 物理分区
2.3.1 Random Partitioning
随机分区[ DataStream -> DataStream]
val shuffleStream =dataStream.shuffle
2.3.2 Roundrobin Partitioning
循环分区[ DataStream -> DataStream]
通过循环的方式对数据集中的数据进行重分区,能够尽可能保证每个分区的数据平衡。可用于解决数据倾斜问题。
val shuffleStream =dataStream.rebalance()
2.3.3 Rescaling Partitioning
仅对上下游继承的算子数据进行重平衡的循环分区[ DataStream -> DataStream]
例如,上游算子并发度为2,下游算子的并发度为4,就会发生上游算子中一个分区的数据按照同等比例将数据 路由 在下游的固定的两个分区中,另外一个分区同理 路由到下游的两个分区中。
val shuffleStream =dataStream.rescale()
2.3.4 Broadcasting
广播变量[ DataStream -> DataStream]
广播策略将输入的数据复制到下游算子的并行的tasks实例中,下游算子中的Tasks可以直接从本地内存中获取广播数据集,不再依赖于网络传输。适合于小数据集。
val shuffleStream =dataStream.broadcast()
2.3.5 Custom Partitioning
自定义分区[ DataStream -> DataStream]
三.DataSink
3.1 基本数据输出
包含文件输出、客户端输出、Socket 网络端口等。
val personStream =env.fromElements(("Alex",18),("Peter",43))
personStream.writeAsCsv("file:///path/to/person.csv",WriteMode.OVERWRITE)
personStream.writeAsTxt("file:///path/to/person.txt")
personStream.writeToSockect(outputHost,outputPort,new SimpaleStringSchema())
3.2 第三方数据输出
val wordStream=env.fromElements("Alex","Peter","Linda")
val kafkaProduer = new FlinkKafkaProducer011[String](
"localhost:9092",//指定Broker List 参数
"kafka-topic",//指定Broker List 参数
new SimpleStringSchema//设定序列化Schema
wordStream.addSink(kafkaProduer )
)