深度剖析阿里巴巴对Apache Flink的优化与改进

本文主要从两个层面深度剖析:阿里巴巴对Flink究竟作了哪些优化?算法

取之开源,用之开源

1、SQL层数据库

为了可以真正作到用户根据本身的业务逻辑开发一套代码,可以同时运行在多种不一样的场景,Flink首先须要给用户提供一个统一的API。在通过一番调研以后,阿里巴巴实时计算认为SQL是一个很是适合的选择。在批处理领域,SQL已经经历了几十年的考验,是公认的经典。在流计算领域,近年来也不断有流表二象性、流是表的ChangeLog等理论出现。在这些理论基础之上,阿里巴巴提出了动态表的概念,使得流计算也能够像批处理同样使用SQL来描述,而且逻辑等价。这样一来,用户就可使用SQL来描述本身的业务逻辑,相同的查询语句在执行时能够是一个批处理任务,也能够是一个高吞吐低延迟的流计算任务,甚至是先使用批处理技术进行历史数据的计算,而后自动的转成流计算任务处理最新的实时数据。在这种声明式的API之下,引擎有了更多的选择和优化空间。接下来,咱们将介绍其中几个比较重要的优化。网络

首先是对SQL层的技术架构进行升级和替换。调研过Flink或者使用过Flink的开发者应该知道,Flink有两套基础的API,一套是DataStream,另外一套是DataSet。DataStream API是针对流式处理的用户提供,DataSet API是针对批处理用户提供,可是这两套API的执行路径是彻底不同的,甚至须要生成不一样的Task去执行。Flink原生的SQL层在通过一系列优化以后,会根据用户但愿是批处理仍是流处理的不一样选择,去调用DataSet或者是DataStream API。这就会形成用户在平常开发和优化中,常常要面临两套几乎彻底独立的技术栈,不少事情可能须要重复的去作两遍。这样也会致使在一边的技术栈上作的优化,另一边就享受不到。所以阿里巴巴在SQL层提出了全新的Quyer Processor,它主要包括一个流和批能够尽可能作到复用的优化层(Query Optimizer)以及基于相同接口的算子层(Query Executor)。这样一来, 80%以上的工做能够作到两边复用,好比一些公共的优化规则,基础数据结构等等。同时,流和批也会各自保留本身一些独特的优化和算子,以知足不一样的做业行为。数据结构

在SQL层的技术架构统一以后,阿里巴巴开始寻求一种更高效的基础数据结构,以便让Blink在SQL层的执行更加高效。在原生Flink SQL中,都统一使用了一种叫Row的数据结构,它彻底由JAVA的一些对象构成关系数据库中的一行。假如如今的一行数据由一个整型,一个浮点型以及一个字符串组成,那么Row当中就会包含一个JAVA的Integer、Double和String。众所周知,这些JAVA的对象在堆内有很多的额外开销,同时在访问这些数据的过程当中也会引入没必要要的装箱拆箱操做。基于这些问题,阿里巴巴提出了一种全新的数据结构BinaryRow,它和原来的Row同样也是表示一个关系数据中的一行,但与之不一样的是,它彻底使用二进制数据来存储这些数据。在上述例子中,三个不一样类型的字段统一由JAVA的byte[]来表示。这会带来诸多好处:多线程

一、首先在存储空间上,去掉了不少无谓的额外消耗,使得对象的存储更为紧凑; 二、其次在和网络或者状态存储打交道的时候,也能够省略掉不少没必要要的序列化反序列化开销; 三、最后在去掉各类没必要要的装箱拆箱操做以后,整个执行代码对GC也更加友好。架构

经过引入这样一个高效的基础数据结构,整个SQL层的执行效率获得了一倍以上的提高。异步

在算子的实现层面,阿里巴巴引入了更广范围的代码生成技术。得益于技术架构和基础数据结构的统一,不少代码生成技术得以达到更广范围的复用。同时因为SQL的强类型保证,用户能够预先知道算子须要处理的数据的类型,从而能够生成更有针对性更高效的执行代码。在原生Flink SQL中,只有相似a > 2或者c + d这样的简单表达式才会应用代码生成技术,在阿里巴巴优化以后,有一些算子会进行总体的代码生成,好比排序、聚合等。这使得用户能够更加灵活的去控制算子的逻辑,也能够直接将最终运行代码嵌入到类当中,去掉了昂贵的函数调用开销。一些应用代码生成技术的基础数据结构和算法,好比排序算法,基于二进制数据的HashMap等,也能够在流和批的算子之间进行共享和复用,让用户真正享受到了技术和架构的统一带来的好处。在针对批处理的某些场景进行数据结构或者算法的优化以后,流计算的性能也可以获得提高。接下来,咱们聊聊阿里巴巴在Runtime层对Flink又大刀阔斧地进行了哪些改进。数据结构和算法

2、Runtime层函数

为了让Flink在Alibaba的大规模生产环境中生根发芽,实时计算团队如期遇到了各类挑战,首当其冲的就是如何让Flink与其余集群管理系统进行整合。Flink原生集群管理模式还没有完善,也没法原生地使用其余其余相对成熟的集群管理系统。基于此,一系列棘手的问题接连浮现:多租户之间资源如何协调?如何动态的申请和释放资源?如何指定不一样资源类型?性能

为了解决这个问题,实时计算团队经历大量的调研与分析,最终选择的方案是改造Flink资源调度系统,让Flink能够原生地跑在Yarn集群之上;而且重构Master架构,让一个Job对应一个Master,今后Master再也不是集群瓶颈。以此为契机,阿里巴巴和社区联手推出了全新的Flip-6架构,让Flink资源管理变成可插拔的架构,为Flink的可持续发展打下了坚实的基础。现在Flink能够无缝运行在YARN、Mesos和K8s之上,正是这个架构重要性的有力说明。

解决了Flink集群大规模部署问题后,接下来的就是可靠和稳定性,为了保证Flink在生产环境中的高可用,阿里巴巴着重改善了Flink的FailOver机制。首先是Master的FailOver,Flink原生的Master FailOver会重启全部的Job,改善后Master任何FailOver都不会影响Job的正常运行;其次引入了Region-based的Task FailOver,尽可能减小任何Task的FailOver对用户形成的影响。有了这些改进的保驾护航,阿里巴巴的大量业务方开始把实时计算迁移到Flink上运行。

Stateful Streaming是Flink的最大亮点,基于Chandy-Lamport算法的Checkpoint机制让Flink具有Exactly Once一致性的计算能力,但在早期Flink版本中Checkpoint的性能在大规模数据量下存在必定瓶颈,阿里巴巴也在Checkpoint上进行了大量改进,好比:

一、增量Checkpoint机制:阿里巴巴生产环境中遇到大JOB有几十TB State是常事,作一次全量CP地动山摇,成本很高,所以阿里巴巴研发了增量Checkpoint机制,今后以后CP从狂风暴雨变成了细水长流;

二、Checkpoint小文件合并:都是规模惹的祸,随着整个集群Flink JOB愈来愈多,CP文件数也水涨船高,最后压的HDFS NameNode不堪重负,阿里巴巴经过把若干CP小文件合并成一个大文件的组织方式,最终把NameNode的压力减小了几十倍。

虽说全部的数据能够放在State中,但因为一些历史的缘由,用户依然有一些数据须要存放在像HBase等一些外部KV存储中,用户在Flink Job须要访问这些外部的数据,可是因为Flink一直都是单线程处理模型,致使访问外部数据的延迟成为整个系统的瓶颈,显然异步访问是解决这个问题的直接手段,可是让用户在UDF中写多线程同时还要保证ExactlyOnce语义,却并不是易事。阿里巴巴在Flink中提出了AsyncOperator,让用户在Flink JOB中写异步调用和写“Hello Word”同样简单 ,这个让Flink Job的吞吐有了很大的飞跃。

Flink在设计上是一套批流统一的计算引擎,在使用过快如闪电的流计算以后,批用户也开始有兴趣入住Flink小区。但批计算也带来了新的挑战,首先在任务调度方面,阿里巴巴引入了更加灵活的调度机制,可以根据任务之间的依赖关系进行更加高效的调度;其次就是数据Shuffle,Flink原生的Shuffle Service和TM绑定,任务执行完以后要依旧保持TM没法释放资源;还有就是原有的Batch shuffle没有对文件进行合并,因此基本没法在生产中使用。阿里巴巴开发了Yarn Shuffle Service功能的同时解决了以上两个问题。在开发Yarn Shuffle Service的时候,阿里巴巴发现开发一套新的Shuffle Service很是不便,须要侵入Flink代码的不少地方,为了让其余开发者方便的扩展不一样Shuffle,阿里巴巴同时改造了Flink Shuffle架构,让Flink的Shuffle变成可插拔的架构。目前阿里巴巴的搜索业务已经在使用Flink Batch Job,而且已经开始服务于生产。

通过3年多打磨,Blink已经在阿里巴巴开始茁壮生长,可是对Runtime的优化和改进是永无止境的,一大波改进和优化正在路上。


更多资讯请访问 Apache Flink 中文社区网站

相关文章
相关标签/搜索