什么是Flink
Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态的计算。Flink被设计为可以在所有常见的集群环境中运行,以内存速度和任何规模执行计算。
https://flink.apache.org/flink-architecture.html
什么是有界和无界的数据流
- 无界流有一个起点,但没有定义的终点。它们不会终止并在生成数据时提供数据。无限制的流必须被连续处理,即,事件被摄取后必须立即处理。无法等待所有输入数据到达,因为输入是无界的,并且在任何时间都不会完成。处理无限制的数据通常要求以特定顺序(例如事件发生的顺序)提取事件,以便能够推断出结果的完整性。
- 有界流具有定义的开始和结束。可以通过在执行任何计算之前提取所有数据来处理有界流。由于有界数据集始终可以排序,因此不需要有序摄取即可处理有界流。绑定流的处理也称为批处理。
Flink可以做什么
Flink 它可以处理有界的数据集、也可以处理无界的数据集、它可以流式的处理数据、也可以批量的处理数据。
为什么选择Flink
Flink 是一个开源的分布式流式处理框架:
- 提供准确的结果,甚至在出现无序或者延迟加载的数据的情况下。
- 它是状态化的容错的,同时在维护一次完整的的应用状态时,能无缝修复错误。
- 大规模运行,在上千个节点运行时有很好的吞吐量和低延迟。
- Flink 的流式计算模型启用了很多功能特性,如状态管理,处理无序数据,灵活的视窗,这些功能对于得出无穷数据集的精确结果是很重要的。
状态管理
Flink 保证状态化计算强一致性。”状态化“意味着应用可以维护随着时间推移已经产生的数据聚合,
Flink 保存点提供了一个状态化的版本机制,使得能以无丢失状态和最短停机时间的方式更新应用或者回退历史数据。
处理无序数据
Flink 支持流式计算和带有事件时间语义的视窗。事件时间机制使得那些事件无序到达甚至延迟到达的数据流能够计算出精确的结果。
灵活的视窗
除了提供数据驱动的视窗外,Flink 还支持基于时间,计数,session 等的灵活视窗。视窗能够用灵活的触发条件定制化从而达到对复杂的流传输模式的支持。Flink 的视窗使得模拟真实的创建数据的环境成为可能。
轻量级容错能力
Flink 的容错能力是轻量级的,允许系统保持高并发,同时在相同时间内提供强一致性保证。Flink 以零数据丢失的方式从故障中恢复,但没有考虑可靠性和延迟之间的折衷。
Flink程序基本结构
- 获得执行环境 environment
- 加载/创建初始数据 dataSet表示批处理的数据、dataStream表示流处理的数据
- 指定对此数据的转换,
- 指定将计算结果放在何处,
- 触发程序执行 environment .execute
按照官网的例子遇到的问题
- 本地启动flink,可能需要修改java_home,位置在bin目录下的config.sh文件的128行,还可以配置一些JVM,log相关的参数
- 按照官网的例子,需要选择maven的环境,否则程序无法启动,即添加flink-java、flink-streaming-java相关的依赖
示例程序
public class Datastreamtest {
public static void main(String[] args) throws Exception {
// 创建Execution Environment。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 通过从本地TXT文件读取数据。
//DataStream<String> text = env.readTextFile("./test.txt");
DataStream<String> text = env.fromElements("hello world", "hello jason", "wonderful world");
// 解析数据,先按word进行分组,然后进行开窗和聚合操作。
DataStream<Tuple2<String, Integer>> windowCounts = text
.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
for (String word : value.split("\\s")) {
out.collect(Tuple2.of(word, 1));
}
}
})
.keyBy(0)
.timeWindow(Time.seconds(5))
.sum(1);
// 将结果打印到控制台。请使用单线程打印,而非多线程打印。
windowCounts.print().setParallelism(1);
env.execute("Socket Window WordCount");
}
}