仍然是学概念,以下大部分是对官方doc的翻译,但是也会有些个人的理解(主要是对比Spark),以及查找的一些解决自己的一些疑惑相关资料。
从Flink 的数据流编程模型和分布式运行环境的基本概念开始学习会对您了解其他部分的文档有帮助,包括安装以及编程指南。强烈推荐先阅读这两部分文档。
Flink提供了不同的抽象级别以支持开发流式、批处理等应用。
补充: 与常规SQL语言中将查询指定为字符串不同,Table API查询是以Java或Scala中的语言嵌入样式来定义的,具有IDE支持如:自动完成和语法检测。Elasticsearch有基于json的查询DSL,不知道是否可以类比理解。
Table API可以用于Scala和Java中,Scala Table API利用了Scala表达式,Java Table API则是基于字符串来的,字符串会被解析并转换成等价的表达式。
对于Table API,以后细学、使用时是再做记录,现在的话,大家可以参考简书——写Bug的张小天:Flink的Table API
Flink程序的基础构建模块是 流(streams) 与 转换(transformations)。从概念上来讲,流是(可能永无止境的)数据记录流,而转换是一种操作,它取一个或多个流作为输入,并生产出一个或多个输出流作为结果。
类比Spark:
Spark执行程序时,通过宽窄依赖来划分Stage,然后也是组织为DAG,由TaskScheduler、DAGScheduler执行相应操作。所以,Flink又是怎样调度作业的?
Flink程序本质上是并行分布的。在执行过程中,一个 流包含一个或多个 流分区(stream partitions) ,而每一个 operator 包含一个或多个 子operator 任务(operator subtasks) 。operator 子任务间彼此独立,以不同的线程执行,甚至有可能运行在不同的机器或容器上。
operator subtasks的数量即这一特定operator的并行度 。【同Spark并行度概念。】
流在两个算符之间传输数据,可以通过 一对一 (或称 forwarding )模式,或者通过 redistributing 模式。
【forwarding的概念类似于Spark中的窄依赖,只是暂时不知道Flink的forwarding模式是否包含多对一;redistributing模式类似于宽依赖,数据可以一对多。】
That means that subtask[1] of the map() operator will see the same elements in the same order as they were produced by subtask[1] of the Source operator.
but the parallelism does introduce non-determinism regarding the order in which the aggregated results for different keys arrive at the sink.
流上的聚合事件(比如counts、sums)的工作方式与批处理的工作方式不同(???Flink的批处理不是基于窗口?):
比如,对流中的所有元素进行计数是不可能的,因为流通常是无限的(无边界的)。
解决方案是:流上的聚合由窗口来划定范围,比如 “count over the last 5 minutes”” ,或者“sum of the last 100 elements” 。
更多窗口示例可以在此博客中找到。详细信息在窗口文档中。
当在流程序中(例如定义窗口)提到时间时,你可以参考以下不同的时间概念:
事件时间 是一个事件被创建的时间。它通常由事件中的时间戳描述。Flink通过时间戳分配器——timestamp assigners访问事件时间戳。
摄入时间 是事件进入Flink数据流的source operator的时间。
关于如何处理时间的更多细节可以查看文档:事件时间。
虽然数据流中的很多操作一次只针对一个独立的事件(比如事件解析器),但有些操作却会记录多个事件间的信息(比如窗口算符)。 这些操作被称为 有状态的 。
下面的一段话,理解不到位:
有状态操作的状态保存在一个可被视作嵌入式键/值存储的部分中。
状态与stateful operators读取的流一起,被严格地分区与分布——partitioned and distributed。因此,只能在keyBy() 函数之后才能访问keyed streams 上的键/值状态,并且仅限于与当前事件键相关联的值。
对齐streams中的key、state确保了所有状态更新都是本地操作,以在没有事务开销的情况下确保一致性。这种对齐还使得Flink可以透明地重新分配状态与调整流的分区。
更多信息请参阅文档:状态。
Flink通过使用 流重播——stream replay 与 检查点 结合的方式实现了容错。检查点与每个输入流中的特定点以及每个操作符的对应状态相关。 A streaming dataflow can be resumed from a checkpoint while maintaining consistency (exactly-once processing semantics) by restoring the state of the operators and replaying the events from the point of the checkpoint.(一个streaming dataflow可以从一个检查点恢复出来,其通过恢复operators的状态并从检查点重播事件来保持一致性 (恰好一次处理语义))。
Flink将批处理程序作为流处理程序的特殊情况,只是这种情况下的流是有界的(有限个元素)。 DataSet 内部仍被视为数据流。
上述适用于流处理程序的概念同样适用于批处理程序,下面是一些区别:
DataSet API中的程序不使用检查点。而通过完全地重播流来恢复。因为输入是有界的,因此这是可行的。这种方法使得恢复的成本增加,但也正是因为避免了检查点,使得正常情况下的处理的开销更小。
DataSet API中的有状态操作使用简化的im-memory/out-of-core数据结构,而不是键/值索引。
DataSet API引入了特殊的同步(基于superstep的)迭代,而这种迭代仅仅能在有界流上执行。细节可以查看迭代文档。
还是不知道流怎样变为批的,感觉应该是时间窗口,但是上文又说窗口与批处理不同。。。