前言
以下都尽量对比Spark(或者大数据生态的其他技术)进行理解。
Flink简介,Flink能做什么
Flink简介
Flink最初是一个名为Stratosphere的研究项目,目标是为柏林地区的一些大学建立下一代大数据分析平台。 它于2014年4月16日成为Apache孵化器项目。Stratosphere的初始版本基于Nephele的研究论文http://stratosphere.eu/assets/papers/Nephele_09.pdf
Flink最重要的功能,即Flink的流API,是Flink 0.7才引入的。 最开始只有Java API,后来的版本也开始支持Scala API。
下图为Stratosphere的演变:
当下1.x版本的架构为:
Flink能做什么
- 支持批处理
- 交互式处理
- 实时流数据处理
- 支持用SQL分析
- 支持机器学习
- 数据处理后的托管状态(managed state)
- 以及仅一次交付(exactly-once)保证
补充:
Atmost-once(在发生故障时可能无法处理)
Atleast-once(即使在出现故障时也至少会被处理一次)
Exactly-once(将被处理一次且恰好一次即使出现故障)
(下图的特性是不完整的)
所以,这样看来,Flink的目标,和Spark是差不多的。
一些异同举例:
- 虽然目标差不多,都想“一统江湖”,但是Flink的生态,还不太完善,还在慢慢的建立
- Flink实时处理是其优势,基于此的机器学习,也是优势,虽然也不够完善
- 托管状态(managed state) 是Flink的优势。【尽量将每个Task的历史状态保存在内存中。】
【在流处理中,有些操作仅仅在某一时间针对单一事件(如事件转换map),有些操作需要记住多个事件的信息并进行处理(window operators),受到其他信息的处理结果的影响。后者的这些操作称为有状态的操作。】 - 准实时处理(微处理)以及较为完善的生态,依然是Spark的大优势。
- Flink 与 Spark Streaming都保证 仅一次交付(exactly-once)。【Flink通过定期的异步checkpointing本地状态保存到持久层来保证在出现故障时的exactly-once】
Flink guarantees exactly-once state consistency in case of failures by periodically and asynchronously checkpointing the local state to durable storage.
- 在 Flink 中,DataSet APi(批) 和 DataStream API(流) 是同一个公用引擎之上的两个独立的抽象。所以,这两者的行为目前无法合并在一起操作,目前官方正在处理这种问题,详见[FLINK-2320];但是Spark就不同,DStream以及DataSet(DataFrame[T])都是封装在RDD之上的,所以可以交互。
- 计算操作都是懒加载。
下图的红色框,现在看来,可能不太严谨了。(TODO:Flink纯自动化内存管理?连基本的配置都不需要?就因为其是自己控制内存,而spark基于JVM控制内存,就把它们分为configured和automatic?)
- 1.6开始,spark推出UnifiedMemoryManager开始朝自动化内存管理发展
- Spark 内存管理以及内存消耗估算 可参考该官方说明
- Spark 统一内存管理可参考:Apache Spark 统一内存管理模型详解
Filink也支持三大部署模式:Local、Cluster(Standalone,Yarn,messos)以及Cloud
选择微批处理还是实时处理
- 第一个用例是金融:信用卡欺诈检测与欺诈预防有些不同。检测是在微批或实时流上发生的事情,而欺诈预防必须实时发生。想象一下,用户正在进行交易,您希望系统查看是欺诈性交易还是有效交易。
- 比如有两个广告科技行业的场景:一个是聚合来自不同IP地址的不同IP请求,将IP归入黑名单或白名单;另一个是设法阻止一个黑名单IP的特定请求。前者使用微批处理就可以,而后者就需要实时流处理。再比如,在电信行业,统计特定用户使用的带宽,微批处理可能是一个更高效的方案,而网络异常检测就需要实时流处理了。也有一些场景,微批处理和实时流处理都适用,如在IoT行业查看特定工业设备的使用情况。
- 视频中还对IOT以及电信行业进行了例举。对应博客
计算流程(组件)
这里只是简单的类比下:
- 在Spark中,我们知道,是RDD/dstream + transform算子 + action算子
- 而在Flume中,是source、channel、sink
- Kafka中,是produce 、存储(或者不存储)、consume
- Hadoop中,map、落磁盘(也可以不落磁盘)、reduce
- Storm中,是图状结构(拓扑):spout、bolt
- Hive:HiveSQL ->AST(抽象语法树:完成SQL词法,语法解析,将SQL转化为抽象 语法树AST Tree;) -> QB(查询块) ->OperatorTree(操作树)->优化后的操作树->mapreduce任务树->优化后的mapreduce任务树
- 这里的Flink,是source、transformation、sink
Flink如何支持批流处理
理解Flink如何流式实时处理数据,如果不是深入细节去理解,还是很好理解,泛泛而谈,就是来一条处理一条,但是具体是怎样的,还需要以后深入学习才知道。
比如说:
- 哪条消息发送往哪台机器去计算,是怎样决定的?
- 处理某条消息如果牵扯到之前的消息处理的状态,那么之前的消息相关的,是怎样传输到其他节点的?
- 等等
这里先理解下Flink如何进行批处理:
- 首先,Flink 把批处理看成 Stream 的特殊例子(也就是批处理建立在流式基础之上,Spark Streaming可以理解为是相反的),具体到架构图可知道:
面向流处理对应DataStream API,面向批处理对应DataSet API。 - 官网讲解的Dataset都是从文件获取数据,我想知道的是:Flink是如何将流式数据批量对待的(因为Flink将批作为流的特例,有文章说——Flink中有一个时间参数,控制缓存多少的数据之后再进行处理。但我迟迟没有找到证据)。
- 先放着,TODO
程序开发步骤
DataStream和DataSet API是程序员调用的接口。编译程序时,这些API会生成JobGraphs。编译后,DataSet API允许优化器生成最佳执行计划,而DataStream API使用流构建的方式来实现高效的执行计划。然后根据部署模型将优化的JobGraph提交给执行程序。
与Spark“套路”差不多:
- 获取上下文执行环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
【Spark中是
SparkContext / SparkSession / StreamingContext 或者
JavaSparkContext / JavaSparkStreaming
】
- 加载数据,比如:
env.readTextFile
等
【spark:
spark.read.jdbc
spark.read.json
spark.read.orc
spark.read.parquet
spark.read.textFile
】
- Transformations 算子,比如:
data.flatMap(new FlatMapFunction<String, String>() {
public void flatMap(String value, Collector<String> out) {
for (String s : value.split(" ")) {
out.collect(s);
}
}
});
- sinks,比如:
textData.writeAsText
- 执行
env.execute();
spark:spark-submit
参考
[1.] YouTube:Apache Spark vs. Apache Flink
[2.] Apache Spark vs. Apache Flink – Whiteboard Walkthrough
[4.] Spark Memory Management Overview & Determining Memory Consumption
[5.] 简书:Flink介绍和基本概念
[6.] 官网:Dataset doc
[7.] 《Learning Apache Flink》packt