并行度
并行数据流Flink程序本质上是并行和分布式的。在程序执行期间,一个流会生成一个或者多个stream partition,并且一个operator会生成一个或者多个operator subtask。operator的 subtask 彼此之间是独立的,分别在不同的线程里去执行并且可能分布在不同的机器上或者containers上。 operator的subtasks的数量等于该操作算子的并行度的数量。流的并行度有总是取决于产生它的操作算子的并行度决定的。同一个flink程序中的不同的operators可能有不同的并行度。
数据流在两个operators之间进行传递的方式有两种:
- one-to-one 模式
和 redistributing 模式one-to-one 模式 两个operator用此模式传递的时候,会保持数据的分区数和数据的排序,比如:在下图中Source和map() operators之间的数据传递方式;map、filter、flatMap等都是one-to-one对应关系 - Redistributing 模式(重新分配模式)
这种模式会改变数据的分区数;每个一个operator subtask会根据选择transformation把数据发送到不同的目标subtasks,比如keyBy()会通过hashcode重新分区,broadcast()和rebalance()方法会随机重新分区,比如:在下图中map()和keyBy/window ,keyBy/window和Sink之间的数据传递方式;Flink每个算子都可以设置并行度,然后就是也可以设置全局并行度。
图中包含source-map[6 parallelism]、keyBy/window/apply[6 parallelism]、sink[1 parallelism]三种Task,总计占用了6个Slot;由左向右开始第一个slot内部运行着3个SubTask[3 Thread],持有Job的一条完整pipeline;剩下5个Slot内分别运行着2个SubTask[2 Thread],不同TaskManager的数据,最终通过网络传递(Akka)。
- job运行task需要的slot数量,为作业中并行度最高的值
- 每个TaskManger可以设置不同的slot数,通过这个特性,可以对不同配置的机器设置不同的slot数量,来最资源合理分配
任务链(Operator Chains)
flink采用任务链计技术,可以在特定条件下减少本地通信的开销(不同的slot数传输会有序列化操作,和线程切换)。
- 算子之间是否可以组成一个Operator Chains,看是否满足以下条件:
- 上下游算子的并行度一致
- 下游节点的入度为1(one-to-one)
- 上下游节点都在同一个 slot group 中
- 下游节点的 chain 策略为 ALWAYS(可以与上下游链接,map、flatmap、filter等默认是ALWAYS。只能与下游链接,不能与上游链接,Source默认是HEAD)
- 两个节点间数据分区方式是 forward
- 用户没有禁用 chain(代码中是否配置disableChain())
//从该运算符开始启动新的任务链。
SingleOutputStreamOperator.startNewChain()
//关闭此运算符的链接,以便线程协同定位不会用作*优化。
SingleOutputStreamOperator.disableChaining()
//禁用任务链
StreamExecutionEnvironment.disableOperatorChaining()