目录
1、Dataflow Programming Model(Dataflow编程模型)
1.1、Levels of Abstraction(抽象层)
1.2、Programs and Dataflows(编程和数据流)
1.3、Parallel Dataflows(并行数据流图)
1.4、Windows(窗口)
1.5、Time(时间)
1.6、Stateful Operations(有状态操作)
1.7、Checkpoints for Fault Tolerance(检查点容错)
1.8、Batch on Streaming(流之上的批处理)
2、Distributed Runtime Environment
2.1、Tasks and Operator Chains(任务和操作链)
2.2、Job Managers, Task Managers, Clients(作业管理器,任务管理器,客户端)
2.3、Task Slots and Resources
2.4、State Backends
2.5、Savepoints(存储点)
Flink提供了不同的抽象层来开发流/批处理应用程序。
Flink的基本组成部分是streams和transformations。(请注意,Flink的DataSet API中使用数据集也在内部流中--后面有更多介绍)。从概念上说,stream是数据记录流(可能是永不休止的),transformation是一种操作,它将一个或多个stream作为输入并产生一个或多个输出流。
当执行时,Flink程序会映射为Streaming dataflows,包括streams和transformation操作。每个dataflow开始于一个或多个sources,并以一个或多个sinks结束。dataflows类似于有向无环图(DAG)。尽管通过迭代构造可以允许形成特殊的环,但为了简化说明,大部分情况下我们不考虑这种结构。
通常,程序中的转换(transformation)和数据流图(dataflow)中的操作符之间存在一对一的对应关系。然后,有时,一个转换(transformation)可能由多个转换操作符组成
Sources和sinks记录在 streaming connectors and batch connectors文档中,Transformation记录在DataStream operators and DataSet transformations文档中。
Flink程序本质上是并行和分布式的。在执行期间,一个stream有一个或多个 stream partitions(流分区),每个运算符有一个或多个operator subtasks(运算子任务)。运算子任务是彼此独立的,并在不同的线程中执行,可能在不同的机器或container中执行。
运算子任务的数量是特定操作的并发度(parallelism )。stream的并发度通常是操作符产生的。同一个程序的不同操作符可能有不同级别的并行度。
Stream可以通过一对一(forward)模式或重分布式(redistributing)模式在两个操作符之间传输数据。
聚合事件(例如:count,sum)在流和批处理的工作方式是不同的。例如,不可能在一个流中count所有元素,因为流通常是无限的(无界的)。相反,流的聚合(count,sum等)是由窗口作用的,例如“count最后五分钟的数据”或者“最后100个元素求和”
Window可以是时间驱动的(每30秒)或者数据驱动的(每100个元素)。一个典型的区别是不同类型的窗口,例如滚动窗口(没有重叠),滑动窗口(有重叠),回话窗口(中间有一个不活动的间隙)。
当提到Streaming程序中的time(例如定义的window),可以引出不同的时间概念。
Event time: 是事件发生的时间,它通常由事件发生中的时间戳来描述,例如由生产传感器或生产服务所创建的时间戳。Flink通过时间戳来访问事件时间戳
Ingestion time:摄入时间是一个事件在source操作符中进入的Flink的时间
Processing time:处理时间是每个操作符基于时间操作的当前时间
• 一条日志进入Flink的时间为2017-11-12 10:00:00,123,到达window的系统时间为2017-11-12 10:00:01,234.
日志的内容如下:
• 2018-11-02 18:37:15,624 INFO org.apache.hadoop.yarn.client.ConfiguredRMFailoverProxyProvider - Failing over to rm2
虽然dataflow中的很多操作符只是一次查看一个单独的事件(如:事件解析器),但是某些操作会记住多个事件的信息(如窗口操作)。这些操作称为有状态。
有状态操作的状态被维护在一个可以被认为是嵌入key/value的存储状态中。状态是分区的,并严格地与有状态的操作读取的流一起分发。因此,在keyBy函数之后,才能在keyed stream上访问key/value的状态,并且限制为与当前事件key相关联的值。对齐流和状态的key,可确保所有状态更新都是本地操作,从而保证一致性而无需事务开销。这种对齐还允许Flink重新分配状态并透明的调整流分区。
状态分类:
Flink使用stream replay(流回放)和checkpointing(检查点)的组合来实现容错。checkpoint是与每个输入流中的特定点以及每个操作符对应的状态相关。通过恢复操作符的状态,并从检查的点重新播放事件,可以从检查点恢复数据流,同时保持一致性(exactly-once处理语义)。检查点间隔是一种在执行期间与恢复时间(需要重新回放的事件数量)执行容错操作的方法。
• 轻量级容错机制(全局异步,局部同步)
• 保证exactly-once 语义
• 用于内部失败的恢复
• 基本原理:
通过往source 注入barrier
barrier作为checkpoint的标志
Flink将批处理(batch programs)程序作为一种特殊的流程序,其中的流是有限的(有限的元素)。DataSet在内部被当做数据流来处理。上面的概念同样适用于批处理程序,他们也适用于流处理,但也有列外:
对于分布式执行,Flink将操作子任务链在一起为任务(tasks)。每个task由一个线程执行。将操作链接到task是一种有用的优化:它减少了线程到线程的转移和缓存,并且降低延迟的同时增加了总的吞吐量。操作链的配置 see the chaining docs for details.
下图的实例dataflow以5个子任务执行,因此有5个并行线程。
Flink的运行时由两种过程组成:
JobManagers(也叫masters)协调分布式执行。它调度tasks,协调检查点,协调故障恢复等等。至少有一个JobManager。高可用性设置将有多个JobManagers,其中一个始终是leader,而其他的是standby状态
TaskManagers(也叫workders)执行一个dataflow的tasks(更具体是subtasks),并且进行缓存,交换数据流。必须至少有一个TaskManager
JobManager和TaskManager可以以不同的方式启动:直接在机器上以 standalone cluster,container容器,或者资源管理器yarn或mesos的方式。TaskManager连接到JobManager,通知JobManager自己是可用的,并且可以被分配任务。
client不是程序执行的一部分,而是用来准备和发送一个dataflow到JobManager。然后,client可以断开连接,或者保持连接以接收进度报告。client要么触发执行的Java/Scala程序,要么在命令行过程中执行: ./bin/flink run ...
每个worker(TaskManager)是一个JVM进程,并且可以在单独的线程中执行一个或多个子任务。为了控制一个worker接收多个任务,一个worker又被称为task slots(至少有一个)。
每个task slots表示TaskManager的固定资源子集。例如,一个有3个slots的TaskManager将它的管理内存的1/3用于每个slot。对资源进行操作,意味着子任务将不会与其他作业的子任务的管理内存竞争,而是有一定数量的保留的管理内存。注意,这里没有CPU隔离,当前slots只分离任务的管理内存。通过调整任务的slots数量,用户可以定义如何相互隔离子任务。每个TaskManager有一个slot意味着每个任务组运行在一个单独的JVM中(例如,可以在一个单独的容器中启动)。拥有多个slots意味着更多的子任务共享同一个JVM。相同的JVM中任务共享TCP连接(通过多路复用)和心跳消息。他们还可以共享数据集合数据结构,从而减少每个任务的开销。
在默认情况下,Flink允许子任务共享slot,即使它们是不同任务的子任务,只要它们来自同一个job。其结果是,一个slot能够容纳整个工作流程。允许这种共享slot有两个主要的好处:
这些API也包含了资源组(resource group )的机制,可用于防止不受欢迎的slot共享。
作为一个经验法则,一个好的默认数量的任务slot是CPU core的数量,对于超线程,每个slot都需要2个或更多的硬件线程上下文。
ey/value索引存储的确切的数据结构依赖于所选的 state backend。一种state backend 将数据存储在内存中的hash map中,另一种state backend 使用RocksDB作为key/value存储。除了定义保存状态的数据结构外,state backend还实现以获取key/value的时间点快照逻辑,并将该快照作为检查点的一部分存储。
在DataStream API中编写的程序可以从保存点恢复执行。savepoints 允许更新你的程序和Flink集群,而不会失去任何状态。
Savepoints是手动触发的检查点,它会对程序进行快照,并将其写入到一个state backend。它们依赖于常规的检查点机制。在执行程序期间,周期性地在工作节点上快照并生成检查点。对于恢复来说,只有最后一个完成的检查点是需要的,并且旧的检查点可以在新的完成之后被安全的丢弃。
Savepoints类似于周期性检查点,但它们是由用户触发的,当更新的检查点完成时不会自动过期。可以从命令行创建保存点,也可以通过REST API取消作业。
• 流处理过程中的状态历史版本
• 具有可以replay的功能
• 外部恢复(应用重启和升级)
• 两种方式触发
• Cancel with savepoint
• 手动主动触发