任务与操作链
对于分布式计算场景,flink会将几个操作符的subtask链接为一个task。每个task在一个线程上执行。将操作符链接起来组成task是一个很有用的优化:它减少了线程与线程之间(task与task之间)的交流与缓存开销,同时增加了总体的吞吐,减少了延迟。如何链接操作符是可以进行配置的。
下面的这个简单的数据流会有5个subtask(注:我觉得这里原文应该是笔误,按照刚刚的说法,source与map已经链接起来了,是作为task存在的,其他的操作符同理,因此这里我觉得应该是5个task),因此有5个并发线程。
JobManager,TaskManager与Client
Flink的运行时包括两种类型的进程:
- JobManager(也称作 master)负责协调分布式计算。它调度task,协调checkpoint,协调故障恢复等。
应该至少存在一个JobManager。配置了HA会有多个JobManager,它们其中的一个是leader,其他的是standby。 - TaskManager(也称作 worker)执行数据流中的task(更确切的说是一个或多个subtask),缓存并交换数据流。
必须至少有一个TaskManager。
JobManager与TaskManager可以通过多种方式启动:以standalone集群方式在本地机器启动,在容器中或者在资源管理框架如YARN/MESOS中启动。TaskManager会与JobManager建立连接,报告自己可用且可以被分配任务。
Client不是运行时以及程序执行时的一部分,它被用来准备数据流图,并且发送数据流图到JobManager。发送完后,client可以关闭,也可以继续与Jobmanager保持联系获取程序运行的报告。Clint既可以作为能够触发flink计算的java/scala程序来启动,也可以使用命令行 ./bin/flink run... 来启动。
Task Slots 与 资源
每一个 TaskManager都是一个JVM进程,可以在不同的线程中执行一个或多个subtask。TaskManager通过一个叫做task slot的配置,来控制可以在一个TaskManager中处理多少task。(每个Taskmanager需要至少一个slot)。
每一个task slot代表着taskManager资源中一个固定的子集。例如,一个taskManager有3个slot,那么每个slot会有1/3的taskManager的资源。资源分隔意味着不同job的subtask间不会有内存资源的竞争。注意的是这里不存在cpu的资源隔离,目前slot仅隔离各个task间的内存。
通过调整task slot的数量,用户可以定义subtask之间如何进行隔离。一个TaskManager只有一个slot意味着,每个task都运行在一个独立的JVM上。一个TaskManager有多个slot意味着subtask之间需要分享同一个JVM。同一个JVM的task可以共享TCP连接(多路复用)以及心跳信息。它们也可能会共享数据集与数据结构,这样会减少每个任务的开销。
(注:总觉得上面这两段文字的原文写的有些概念不清。根据本文最开始的说法,多个subtask组合在一起形成一个task,也可能会有一个task仅有一个subtask组成。但是此处的task slot中运行的是task,但是原文中拼却频频说slot中的subtask,我觉得将上面两段中的subtask换成task可能会好理解些)
默认情况下,Flink允许多个subtask分享同一个slot,即便这些subtask是来自不同的task,只要这些task是同一个job的task。(也就是说一个slot中会存在同一个job中的多个task)这样一个slot中可能含有一个job中整个处理逻辑。允许slot级别的共享有以下两个好处:
- flink集群只需要根据job中最大的并行度来分配slot资源就可以了。不必计算在不同算子有不同并发情况下,总共有多少task
-
资源利用更高。不使用slot共享机制时,有多少个 source/map task就会有多少个 window task,占用两倍的slot。而允许slot共享后,将并发度从2增加到6,会将图中的两个taskManager资源全部使用,同时保证较“重”的subtask在taskManager中均匀的分配
API中包含了 资源组合 机制的api,可以用来阻止不需要的slot共享。
根据经验,slot最好配置为cpu的数量。如果cpu支持超线程,那么每个slot会持有两个或者更多的硬件级别的线程上下文(hardware thread contexts)
状态后端
上文说道,operator中的state是以key/value形式存储的。但是确切的数据格式,取决于所选的状态后端。存储在内存的使用hash map,存储在RocksDB使用的key/value存储。除了定义持有state的数据结构,状态后端还实现了支撑checkpoint的功能:对其状态做快照,该快照会作为checkpoint的一部分。
保存点 Savepoint
使用DataStream API编写的程序,可以实现从savepoint处进行重启。使用savepoint可以用来更新你的应用或者进行集群升级,而不会丢失任何任务的状态。
savepoint是手动触发的checkpoint,它会对程序做一个快照然后存储在状态后端。savepoint机制依赖于checkpoint机制。在运行时,程序会周期性的对worker节点做快照生成checkpoint。发生故障时,只有最新生成的checkpoint是有用的,因此当新的checkpoint生成后,其他的checkpoint会被安全的删除。
savepoint和这些周期性生成的checkpoint类似,但是savepoint是用户手动触发生成的,并且当新的checkpoint生成后,这个savepoint不会自动被删除或过期。可以使用命令行或者REST API来生成savepoint。
网友评论