分布式计算中,Flink会将算子(operator) 的子task链式组成tasks,每一个task由一个线程执行。把算子链化为tasks是一个很是好的优化:它减小了线程之间的通讯和缓冲,并且还能增长吞吐量下降延迟。链化操做的配置详情可参考: chaining docshtml
下图中dataflow有5个subtasks,所以有5个线程并发进行处理。 后端
Flink运行时包含两类进程:api
至少须要一个JobManager。高可用部署下会有多个JobManagers,其中一个做为leader,其他处于standby状态。缓存
至少须要一个TaskManager。安全
有多种方式能够启动JobManagers和TaskManagers:直接在计算机上启动做为 standalone cluster,在容器中或者由资源管理器YARN 或者 Mesos启动。 TaskManagers链接到JobManagers后,会通知JobManagers本身已可用,接着被分配工做。数据结构
client 不做为运行时(runtime)和程序执行的一部分,只是用于准备和发送dataflow做业给JobManager。 所以客户端能够断开链接,或者保持链接以接收进度报告。客户端能够做为触发执行的Java/Scala 程序的一部分或者运行在命令行进程中 ./bin/flink run ...。并发
每一个worker(TaskManager)都是一个JVM 进程,而且能够在不一样的线程中执行一个或多个subtasks。每一个worker用task slots(任务槽位) (至少有一个)来控制能够接收多少个tasks。分布式
每一个task slot表明TaskManager中一个固定的资源子集。例如,有3个slots的TaskManager会将它的内存资源划分红3份分配给每一个slot。划分资源意味着subtask不会和来自其余做业的subtasks竞争资源,可是也意味着它只拥有固定的内存资源。注意划分资源不进行CPU隔离,只划份内存资源给不一样的tasks。高并发
经过调整slots的个数进而能够调整subtasks之间的隔离方式。当每一个TaskManager只有一个slot时,意味着每一个task group运行在不一样的JVM中(例如:可能在不一样的container中)。当每一个TaskManager有多个slots时,意味着多个subtasks能够共享同一个JVM。同一个JVM中的tasks共享TCP链接(经过多路复用技术)和心跳消息。可能还会共享数据集和数据结构,从而减小每一个task的开销。优化
默认状况下,只要subtasks是来自同一个job,Flink容许不一样tasks的subtasks共享slots。所以,一个slot可能会负责job的整个pipeline。容许slot sharing有两个好处:
APIs还包含了一种 *资源组(resource group)*机制,用来防止没必要要的slot sharing。
经验来说,task slots的默认值应该与CPU核数一致。在使用超线程下,一个slot将会占用2个或更多的硬件资源。
key/values索引存储的准确数据结构取决于选择的 state backend。其中一个 state backend将数据存储在内存hash map中,另外一个 state backend使用RocksDB做为key/value 存储。 除了定义存储状态的数据结构, state backends还实现了获取 key/value状态的时间点快照的逻辑,并将该快照存储为checkpoint的一部分。
使用Data Stream API编写的程序能够从一个savepoint恢复执行。Savepoints容许在不丢失任何状态的状况下修改程序和Flink集群。
Savepoints 是手动触发的checkpoints,它依赖常规的checkpointing机制,生成程序快照并将其写入到状态后端。在运行期间,worker节点周期性的生成程序快照并产生checkpoints。在恢复重启时只会使用最后成功的checkpoint。而且只要有一个新的checkpoint生成时,旧的checkpoints将会被安全地丢弃。
Savepoints与周期性触发的checkpoints很相似,可是其式由由用户触发的,且当更新的checkpoints完成时,老的checkpoint不会自动失效。能够经过命令行或者在取消一个job时调用REST API的方式建立Savepoints。