- 说好的流批一体呢?
- 现状是截止1.10版本依然采用了 DataSet 和 DataStream 两套 API 来适配不同的应用场景。
- DateSet 和 DataStream 的区别和联系
1、Apache Flink 在诞生之初的设计哲学是:用同一个引擎支持多种形式的计算,包括批处理、流处理和机器学习等。尤其是在流式计算方面,Flink 实现了计算引擎级别的流批一体
2、对于DataSet而言,Source部分来源于文件、表或者Java集合
3、对于DataStream而言,Source部分一般是消息中间件比如Kafka等
- DataStream
- 自定义实时数据源
- Map
最常用函数
- FlatMap
平铺列表元素
- Filter
返回true则保留,否则丢弃
- KeyBy
1、使用KeyBy函数时会把DataStream转换为KeyedStream,后者继承前者
2、大数据量和key分布不均匀时非常容易出现数据倾斜和反压,导致任务失败
3、常见的解决方式:把所有数据加上随机前后缀
- Aggregations
1、min 和 minBy 的区别在于,min 会返回我们指定字段的最小值,minBy 会返回对应的元素(max 和 maxBy 同理)。
2、min 和 minBy 都会返回整个元素,只是 min 会根据用户指定的字段取最小值,并且把这个值保存在对应的位置,而对于其他的字段,并不能保证其数值正确。max 和 maxBy 同理。
3、对于 Aggregations 函数,Flink 帮助我们封装了状态数据,这些状态数据不会被清理。所以尽量避免在一个无限流上使用 Aggregations。而且,对于同一个 keyedStream ,只能调用一次 Aggregation 函数。
- Reduce
会在每一个分组的 keyedStream 上生效,它会按照用户自定义的聚合逻辑进行分组聚合。
package com.flink.demo.source;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import java.util.ArrayList;
import java.util.Random;
/**
* description
*
* @author zsyoung@qq.com
* 2020/7/8 0:31
*/
public class MyStreamingSource implements SourceFunction<MyStreamingSource.Item> {
private boolean isRunning = true;
@Override
public void run(SourceContext<Item> sourceContext) throws Exception {
while (isRunning) {
Item item = generateItem();
sourceContext.collect(item);
//每秒产生一条数据
Thread.sleep(1000);
}
}
//随机产生一条商品数据
private Item generateItem() {
int i = new Random().nextInt(100);
ArrayList<String> list = new ArrayList<>();
list.add("HAT");
list.add("TIE");
list.add("SHOE");
Item item = new Item();
item.setId(i);
item.setName(list.get(new Random().nextInt(3)));
return item;
}
@Override
public void cancel() {
isRunning = false;
}
public static class Item {
private String name;
private Integer id;
public Item() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "Item{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
}
package com.flink.demo.source;
import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
/**
* description
*
* @author zsyoung@qq.com
* 2020/7/8 0:37
*/
public class StreamingDemo {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 获取数据源
DataStreamSource<MyStreamingSource.Item> text = env.addSource(new MyStreamingSource()).setParallelism(1);
//打印name和id
// SingleOutputStreamOperator<MyStreamingSource.Item> item = text.map((MapFunction<MyStreamingSource.Item, MyStreamingSource.Item>) value -> value);
//利用map函数只打印name
// SingleOutputStreamOperator<Object> item = text.map((MapFunction<MyStreamingSource.Item, Object>) Obj -> Obj.getName());
//利用flatMap函数平铺打印
// SingleOutputStreamOperator<Object> item = text.flatMap((FlatMapFunction<MyStreamingSource.Item, Object>) (item1, collector) -> {
// String name = item1.getName();
// collector.collect(name);
// });
//利用filter字段过滤出来id为偶数的字段
SingleOutputStreamOperator<MyStreamingSource.Item> item = text.filter((FilterFunction<MyStreamingSource.Item>) item12 -> item12.getId() % 2 == 0);
item.print().setParallelism(1);
env.execute("user defined streaming job");
}
}