您的位置  > 互联网

宋辛童:Flink的演进流批融合云原生自适应3.0

Flink之进化流批量融合云原生自适应3.0

点击查看直播回放及演讲PPT

1.Flink 的演变

纵观整个演进过程,1.0和2.0的概念并没有被明确提出。 但从其技术发展经历来看,我们可以将其分为两个阶段,如上图所示。

在1.0阶段,只具备基础的数据传输能力,Flink项目也处于比较年轻的阶段。

在2.0阶段,我们做了一系列的优化。

综上,我们可以发现,性能和稳定性都是 Flink 大规模生产必备的能力,而流批融合是 Flink 社区过去发展的主要方向之一。 整个2.0阶段,我们发现Flink已经成熟,并且在生产中表现良好。

谈3.0,我们应该关注哪些问题? 或者说,随着时代的发展、技术的进步,又带来了哪些新的挑战? 这里我们也列出三个关键词:流批融合、云原生、自适应。 接下来我也将与大家进行一一拓展讨论。

2. 流批一体化

“流批一体化”和“流批一体化”有何联系和区别?

如上图所示,左侧是Flink经典的流批一体化架构。 在这个架构中,Flink 为流和批提供了统一的 API 表达,然后使用统一的引擎 Flink 来进行流和批的数据处理。 另外,我们通常会将实时任务和离线任务调度到同一个集群上进行共置,从而提高研发运维效率和资源利用率。

目前Flink的流批一体化架构主要体现在面向用户的流批一体化。 如果我们深入引擎内部,我们会发现Flink任务的流模式和批模式的区别非常明显,整个架构中仍然存在离线和实时两个数据链路。 可见,流式处理和批处理的融合主要是一个面向用户的概念。

流批融合,所谓Flink流批融合能力,不仅仅是把流批技术放到一个引擎里。 我们希望在引擎端打破流式和批式的技术界限,流式技术和批式技术并存。 技术同时服务不同场景。

在流批融合方面,主要有两点:

流批一体化的重点是打破流批之间的界限。 从引擎端把所有技术整合到一起,服务于不同的场景。 不难看出,流批融合的概念是一个端到端的事情。 纵观执行计划的优化、编译、调度、运行、容错等场景,都需要按照流批融合的理念进行改变和改进。

是一种将流式技术应用于批量场景的技术。

目前Flink主要包括 和 。 其中,流式传输的上下游任务是同时运行的,大大缩短了任务的运行时间。 同时,它的数据可以在任务之间直接传输,而不需要放在磁盘上。

但在批量场景下,仍然无法用于生产。 因为上下游同时运行时对资源要求更高。 如果同时有多个任务,每个任务只能获取一部分资源,这样很容易造成资源调度的死锁。

批处理模式具有更好的资源适应性。 在极端情况下,我们可以使用一个槽来执行所有任务。 但其性能较慢,因为批量任务是按照阶段调度运行的,每个阶段都需要等待长尾任务完成。 其次,它的所有数据都需要写入磁盘,导致IO开销较高。

可见,无论是流式还是批式,在某些情况下都会出现资源碎片,即虽然持有资源,但任务无法调度执行,造成资源浪费。

思路是结合流式和批处理的特点,这样用户在写入数据时,既可以写入内存并直接通过内存进行消费,也可以在内存无法存储这么多数据时使用。下游消费不够及时。 将数据写入磁盘以供以后使用。 通过自适应切换,上游数据产生期间和产生之后,下游可以随时消费,从而彻底消除资源碎片。

当资源充足时,所有上下游任务可以同时运行,其性能与流式相同。 在资源有限的情况下,可以让上游先执行,将数据落盘,然后下游消费。 其资源适应性较好。

另外,内存和磁盘之间的切换是一种动态的自适应切换,而不是静态的一次性切换。 在数据消费过程中,当内存满了的时候,我们可以随时切换到磁盘模式。 当内存中的数据消耗完毕,剩余空间较多时,可以切换回内存进行消费。

目前已经在 Flink 1.16 中发布。 经过测试,与资源受限条件下相比,性能提升了7.2%。 如果有足够的资源,会有更大的性能提升。

接下来,我们将继续完善和优化 Flink 1.17。 主要包括对广播数据的性能优化以及与大规模生产中批处理的其他重要特性的兼容性。

任务单点重启是一种将批处理技术应用于流式场景的技术。 在Flink的流任务中,如果任务失败,必须全局重启相关的上下游任务,以保证数据的一致性。 然而,这种全球重启的成本很高,特别是对于一些大规模、复杂的工作。

单点只能在当前失败的任务发生时重新启动它。 目前,我们支持三种一致性语义,即 Best-、At-least-once 和 -once。 一致性保证越强,相应的开销就越高。 其中,Best-需要恢复任务状态。 为了解决这个问题,我们使用分布式本地快照,为每个任务定期拍摄本地快照,以避免全局同步开销。 在At-least-once语义下,我们需要重播上游数据以避免数据丢失。 在-once语义下,我们不仅需要重放数据,还需要对下游数据进行重复数据删除。

无论是重放输入还是对输出进行去重,都是在层面上完成的。 它们与半持久数据放置非常相似,并且支持重复消费。 因此,在实践中,我们在现有批量能力的基础上进行了扩展和二次开发。

目前,Task工作仍处于内部实践阶段。 At-least-once语义很快就会在阿里云内上线,而-once还在开发中。

3.云原生

云原生场景3.0实践。 从 Flink 1.9 版本开始,我们一直在构建 Flink 云原生部署体系,包括 K8s 部署模式、轻量级客户端模式、K8s HA 模式、资源管理方式等。

Flink的云原生部署体系越来越完善。 Flink流式任务的生产也比较成熟,经过了大量的生产测试。 但我们在运行批处理任务时仍然遇到问题。

其中,最重要的问题是批量数据存储。 在Batch任务中,我们需要存储大量的中间数据。 这时候就出现了数据存放在哪里的问题。 目前Flink有两种主流模式,分别是 和 。

数据直接写入TM中。 这里有两个问题。

云盘虽然具有动态挂载和共享存储空间的能力,但其成本比磁盘高,访问速度比本地访问慢,而且动态挂载也比较耗时。

综上所述,主要问题是资源效率和磁盘成本。

问题是数据传输开销。 本来,数据只需要在两个TM之间传输。 现在我们需要将它从上游TM传输到远程系统,然后下游TM从远程系统消费它。 这将使传输成本至少增加一倍。

另外,我们不仅需要运维Flink集群,还需要部署额外的集群,这在部署和运维方面也会产生一些成本。

最后,虽然它可以在一定程度上缓解磁盘空间和磁盘成本问题,但由于它可以建立一个并同时服务大量不同的 Flink 实例,可以起到削峰填谷的作用,因此不能从根本上消除磁盘空间。 问题。

因此,目前还没有非常完善的方案来解决Flink的Batch数据在云原生场景下的存储问题。

人们在使用云产品的时候,经常会用到对象存储。 基于对象存储,资源弹性灵活,成本相对较低。 然而,对象存储通常是不可修改的。 当上游写数据时,下游看不到数据。 一旦下游数据可见,上游就无法修改或追加数据。 另外,性能相比本地盘或者云盘还是有一定的差距。

因此,在流处理场景中,对象存储仍然面临一些挑战。 一方面需要基于不可修改的对象存储来实现同时读写的能力。 另一方面,对象存储很难满足低延迟的要求。 虽然对象存储很难独立支持数据管理,但当本地磁盘不够用时,可以使用对象存储作为其他数据存储方式的补充,达到性能和成本的平衡。

目前基于对象存储的存储还处于内部实践阶段,预计在 Flink 1.18 版本中发布。

4. 自适应

,在最新的 Flink 1.16 中,有四种不同的,分别是 Hash、Sort-Based 和最新推出的。 未来Flink可能会引入Task、对象存储、Merge-Based等。另外,在第三方项目中,Flink也是基于Flink的接口来实现的。

大量不同的实现同时存在,这也带来了一些问题。 用户不知道如何选择类型,使用起来很困难。 根据场景选择合适的类型,需要用户深入了解内部原理。 选择类型后,在实际生产中,用户在进行参数整定时,也面临着不同类型的整定参数和原理不同的问题。 另外,由于部分用户场景丰富,可能需要同时使用多种类型。 这些类型如何匹配? 它的复杂性给用户带来了困难。

在开发人员维护方面,随着越来越多的软件出现,工作人员需要维护更多的代码,甚至重复开发。 另外,内部复杂性开始蔓延到整个Flink链路,比如SQL编译、调度和运行等,对项目的长期维护产生了一定的影响。

为了解决上述问题,我们提出了三种提高适应性的方法。

5.3.0

最后介绍一下我们基于上述关键词提出的 Flink 3.0 架构设计。 这种架构称为自适应分层存储架构。 在该架构中,我们将上下游之间的数据交换过程抽象为上游将数据写入某个存储,下游从存储中提取需要查询的数据的过程。

在分层自适应存储架构中,有写端和读端,主要负责向不同的存储介质写入和读取数据。 在中间存储层,内部实现细节被隐藏并且有统一的抽象。

动态适配方面,写入端按照优先级将数据写入存储层。 如果遇到空间不足等问题,存储层会报告当前无法接收数据,然后继续写入下一个优先级存储层。 在读取方面,我们按照优先级顺序查询想要的数据。 通过分层存储和动态适配,我们对多个存储层的介质进行整合和补充,以满足我们不同情况下的需求。

在存储层规划方面,Local TM层主要包括内存和磁盘。 在TM层,用户将数据写入第三方TM的内存和磁盘进行管理。 还有一层远程存储介质。

目前,我们在3.0自适应存储架构的探索中遇到了以下关键技术问题。

在数据分组方面,不同位置存储的数据分组方式不同,这就决定了数据索引结构和文件存储格式的差异。

在数据管理粒度方面,采用更大的粒度进行存储层之间的切换,以降低切换频率和搜索成本。 不同的粒度适合不同的存储层。 在存储层内,内存存储更适合较小的粒度,对实时可见性要求较高,管理数据的成本较低。 对于像对象存储这样的远程存储服务,我们会更加关注如何减少文件数量,并且往往会有比较大的数据管理粒度。

在数据索引方面,数据存储的位置决定了适用的索引方法。 例如,在本地TM和远程TM上,内存索引的查询性能更好。 由于对象存储缺乏外部服务流程,因此它对数据进行管理。 因此,我们根据文件命名方式对文件进行简单的列表操作,根据文件名判断文件中是否有当前想要的数据。

目前3.0还处于探索阶段。 未来,在 Flink 1.18 中,社区将推出第一个版本的分层自适应架构存储,其中包括本地 TM 内存和磁盘的存储层,并支持远程对象存储能力。 未来我们会逐步增加流处理、Task、远程TM的内存+磁盘能力。

点击查看直播回放及演讲PPT