Tasks 和 Operator Chains
分布式执行时,Flink 可以将算子子任务链接成任务,每个任务由一个线程执行,这种链接是一种有效的优化,规避了线程切换和缓冲的开销,在降低延时的前提下提高了整体吞吐量,链接行为是可以被配置的
Job Managers,Task Managers 和 Clients
Flink 运行时包括两种类型的过程,①JobManager 也被称为 Master,用于协调分布式的执行,负责调度任务(schedule task),协调处理检查点(coordinate checkpoints)和协调错误恢复(coordinate recovery on failures)等等,集群中至少需要有一个 JobManager,高可用的集群可以有多个 JobManager,其中一个是 leader,其他的处于待机(standby)状态 ②TaskManager 也被称为 Worker,用于处理数据流上的任务或子任务,并负责缓冲和交换流式数据,集群中至少需要有一个 TaskManager
可以用多种方式启动 JobManager 和 TaskManager,例如在单机模拟的独立集群上运行,在容器内运行或者通过 Mesos 和 YARN 等资源管理框架运行
TaskManager 主动连接 JobManager,报告自己是可用的并接受指派的任务
Client 不是运行时和程序执行的一部分,而是用来准备和发送数据流到 JobManager 的,完成这项工作后即可断开连接,当然也可以保持连接以接收处理程序的输出
Task Slots 和 Resource
每个 Worker,即 TaskManager,都是一个 JVM 进程,并且可能在不同的线程中执行若干个子任务
为了处理分配到 Worker 上的多个任务,Worker 设置了一系列的任务插槽(task slot)
每个任务插槽代表着 TaskManager 上一份固定的资源,这些资源是相互分隔的,资源的分隔意味着子任务不会相互竞争内存,目前的设计中,CPU 资源不会被分隔,只有存储资源被分隔
通过调整任务插槽的数量,用户可以定义子任务之间相互隔离的方法,只分配一个 Slot 意味着每个任务组拥有单独的 JVM,分配多个 Slot 意味着多个子任务共享一个 JVM,同一个 JVM 上的任务通过多路复原共享 TCP 连接并共享心跳(heartbeat)信息,也可能共享数据信息和数据结构,从而降低了每个任务的开销
默认情况下 Flink 支持子任务共享 Slot,只要它们是同一个 Job 里面的,这使得同一个 Slot 里面可以有 Job 的整个流程所需的信息,这样处理有以下几点好处
-
Flink 集群划分 Slot 时只需要关心 Job 中的最高复杂度
-
更好的利用资源,如果不使用 Slot 共享,非密集型的
source/map()
任务会阻塞和密集型的一样多的资源;如果使用 Slot 共享,例如在下面的示例中,我们可以将基本并行度从 2 提升到 6,这样充分利用了已有的资源,同时确保了难的子任务在 TaskManager 之间公平地分配
Flink API 还提供资源分组的机制,以防止不需要的 Slot 共享
State Backends
存储键值索引的具体的数据结构取决于选定的 State Backend,可能一个 State Backend 将数据存储在内存里的哈希表中,另一个 State Backend 使用 RocksDB 存储
除了定义保存状态的数据结构外,State Backend 还实现了获取键值索引的时间点快照并将该快照存储为检查点的一部分的逻辑
Savepoints
应用 DataStream API 写成的程序可以从 Savepoint 上恢复执行,这使得更新程序或者更换集群不会丢失状态信息
Savepoint 类似于 Checkpoint,Checkpoint 依赖于定期保存状态的 Checkpointing 机制,程序执行时周期性的拍摄工作节点的快照并产生 Checkpoint,为了达到恢复执行的效果,我们只需要最新的 Checkpoint,当新的 Checkpoint 产生后,此前的 Checkpoint 即可被安全的丢弃
与之相比,Savepoint 由用户手动触发产生,并且不会主动过期