Flink学习笔记(基本概念)
一、概述
1、架构简介
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。Flink 集成了所有常见的集群资源管理器,例如 Hadoop YARN、 Apache Mesos 和 Kubernetes,但同时也可以作为独立集群运行。特点如下:
1)无边界:数据流有开始没有结束,持续处理到来的数据(实时处理)
2)有边界:数据的批处理(如等待一定量的数据到达后进行处理、存储后处理)
3)有状态:处理后一个数据时会用到之前处理过的数据的特点,该特点即为状态,需要保存。任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中。
2、Flink状态特点
1)多种状态基础类型:多种状态基础类型,例如原子值(value),列表(list)以及映射(map)。
2)插件化的State Backend:State Backend 负责管理应用程序状态,并在需要的时候进行 checkpoint。可以将状态存在内存或者 RocksDB。RocksDB 是一种高效的嵌入式、持久化键值存储引擎。Flink 也支持插件式的自定义 state backend 进行状态存储。
3)精确一次语义:checkpoint 和故障恢复算法保证了故障发生后应用状态的一致性。
4)超大数据量状态:利用其异步以及增量式的 checkpoint 算法,存储数 TB 级别的应用状态。
5)可弹性伸缩的应用:Flink 能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。
3、Flink时间语义
1)事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。如,用户点击某一页面后一个小时内再次返回该页面的次数,此时使用事件时间。
2)Watermark 支持:衡量事件时间进展,是一种平衡处理延时和完整性的灵活机制。如处理数据的顺序(判断是否等待更早的数据到来)可以根据水印判断。
3)迟到数据处理:当以带有 watermark 的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink 提供了多种处理迟到数据的选项,如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。
4)处理时间模式:处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。如处理11:00-12:00内的页面点击数。
4、分层API
根据抽象程度分层,提供了三种不同的 API。每一种 API 在简洁性和表达力上有着不同的侧重,并且针对不同的应用场景。
二、Flink架构
1、 进程组成
1)JobManager:它决定何时安排下一个任务(或任务组),对任务的完成或失败采取动作,协调检查点与故障恢复,等等。此过程包含三个不同的组件:
——ResourceManager:负责在集群中分配资源和配置文件,管理任务slots(资源调度单元)
——Dispatcher:提供了一个提交执行Flink任务的接口,还运行Flink WebUI以提供有关作业执行的信息。
——JobMaster:一个JobMaster负责管理一个单一的 JobGraph执行。Flink群集中可以同时运行多个作业,每个作业都有自己的JobMaster。
始终至少有一个JobManager。高可用性设置可能有多个JobManager,其中一个始终是领导者,而其他则 处于待机状态
2)TaskManagers:执行数据流的任务,以及缓冲和交换数据流。TaskManager中资源调度的最小单位是任务slot。TaskManager中任务slot的数量指示并发处理任务的数量。请注意,多个operator可以在一个任务slot中执行
2、Tasks and Operator Chains
每个任务由一个线程执行。将operator链接到任务是一个有用的优化:它减少了线程到线程的切换和缓冲的开销,并在降低延迟的同时提高了总体吞吐量。可以配置链接行为。
3、Task Slots and Resources
每个工作程序(TaskManager)是一个JVM进程,并且可以在单独的线程中执行一个或多个子任务。为了控制TaskManager接受多少个任务,它具有所谓的任务slot(至少一个)。
每个任务slot代表TaskManager资源的固定子集。例如,具有三个slot的TaskManager会将其托管内存的1/3专用于每个插槽。分配资源意味着子任务不会与其他作业的子任务竞争托管内存,而是具有一定数量的保留托管内存。请注意,此处没有发生CPU隔离。当前插槽仅将任务的托管内存分开。
通过调整任务slot的数量,用户可以定义子任务如何相互隔离。每个TaskManager具有一个插槽,意味着每个任务组都在单独的JVM中运行(例如,可以在单独的容器中启动)。具有多个插槽意味着更多子任务共享同一JVM。同一JVM中的任务共享TCP连接(通过多路复用)和心跳消息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。
默认情况下,Flink允许子任务共享插槽,即使它们是不同任务的子任务也是如此,只要它们来自同一job即可。
4、Flink执行的集群环境
1)Flink会话集群
——生命周期:在Flink会话群集中,客户端连接到可以接受多个作业提交的、预先存在的、长时间运行的群集。即使所有作业完成后,群集(和JobManager)也将继续运行,直到手动停止会话为止。因此,Flink会话群集的生存期不与任何Flink作业的生存期绑定。
——资源隔离:TaskManager slots由ResourceManager在作业提交时分配,并在作业完成后释放。由于所有作业都共享同一个群集,因此在群集资源方面存在一些竞争,例如提交作业阶段中的网络带宽。此共享设置的局限性在于,如果一个TaskManager崩溃,则所有在此TaskManager上运行任务的作业都将失败;以类似的方式,如果JobManager发生一些致命错误,它将影响集群中正在运行的所有作业。
——其他注意事项:拥有预先存在的群集可以节省大量时间来申请资源和启动TaskManager。在作业执行时间非常短且启动时间过长会对端到端用户体验产生负面影响的情况下(如对短查询进行交互式分析的情况),这很重要,在这种情况下,希望作业可以快速使用现有资源执行计算。
2)Flink工作集群
——生命周期:在Flink作业群集中,可用的集群管理器(例如YARN或Kubernetes)用于为每个提交的作业启动一个群集,并且该群集仅可用于该作业。在这里,客户端首先从集群管理器请求资源以启动JobManager,然后将作业提交给在此过程中运行的Dispatcher。然后根据作业的资源需求延迟分配TaskManager。作业完成后,Flink作业群集将被拆除。
——资源隔离:JobManager中的致命错误仅影响在Flink Job Cluster中运行的一个作业。
——其他注意事项:由于ResourceManager必须应用并等待外部资源管理组件来启动TaskManager进程并分配资源,因此Flink作业集群更适合于长期运行,具有高稳定性要求且不敏感的大型作业更长的启动时间。
3)Flink Application集群
——群集生命周期:Flink应用程序群集是专用的Flink群集,它仅从一个Flink应用程序执行作业,并且该 main()
方法在群集上而不是客户端上运行。作业提交是一个单步过程:您无需先启动Flink集群,然后再将作业提交到现有的集群会话;相反,您将应用程序逻辑和相关性打包到可执行的作业JAR中,集群入口点(ApplicationClusterEntryPoint
)负责调用main()
方法以提取JobGraph。例如,这使您可以像在Kubernetes上部署任何其他应用程序一样部署Flink应用程序。因此,Flink应用程序集群的生存期与Flink应用程序的生存期绑定在一起。
——资源隔离:在Flink应用程序集群中,ResourceManager和Dispatcher的作用域为单个Flink应用程序,与Flink会话集群相比,它提供了更好的关注点分离。
三、故障恢复
1、可持续运行及其一致性
1)检查点的一致性: 建立分布式应用服务状态一致性检查,当有故障产生时,应用服务会重启后,再重新加载上一次成功备份的状态检查点信息。结合可重放的数据源,该特性可保证精确一次(exactly-once)的状态一致性。
2)高效的检查点: 如果一个应用要维护一个TB级的状态信息,对此应用的状态建立检查点服务的资源开销是很高的,为了减小因检查点服务对应用的延迟性(SLAs服务等级协议)的影响,采用异步及增量的方式构建检查点服务。
3)端到端的精确一次: Flink 为某些特定的存储支持了事务型输出的功能,及时在发生故障的情况下,也能够保证精确一次的输出。
4)集成多种集群管理服务:与多种集群管理服务紧密集成,如 Hadoop YARN, Mesos, 以及 Kubernetes。当集群中某个流程任务失败后,一个新的流程服务会自动启动并替代它继续执行。
5)内置高可用服务:内置了为解决单点故障问题的高可用性服务模块,此模块是基于Apache ZooKeeper 技术实现的,是一种可靠的、交互式的、分布式协调服务组件。
2、升级、迁移、暂停、恢复应用服务
Savepoint 服务是为解决升级服务过程中记录流应用状态信息及其相关难题而产生的一种唯一的、强大的组件。一个 Savepoint,就是一个应用服务状态的一致性快照,因此其与checkpoint组件的很相似,但是与checkpoint相比,Savepoint 需要手动触发启动,而且当流应用服务停止时,它并不会自动删除。Savepoint 常被应用于启动一个已含有状态的流服务,并初始化其(备份时)状态。Savepoint 有以下特点:
1)便于升级应用服务版本: Savepoint 常在应用版本升级时使用,当前应用的新版本更新升级时,可以根据之前版本程序记录的 Savepoint 内的服务状态信息来重启服务。
2)方便集群服务移植: 通过使用 Savepoint,流服务应用可以自由的在不同集群中迁移部署。
3)方便Flink版本升级: 通过使用 Savepoint,可以使应用服务在升级Flink时,更加安全便捷。
4)增加应用并行服务的扩展性: Savepoint 也常在增加或减少应用服务集群的并行度时使用。
5)便于A/B测试及假设分析场景对比结果: 通过把同一应用在使用不同版本的应用程序,基于同一个 Savepoint 还原点启动服务时,可以测试对比2个或多个版本程序的性能及服务质量。
6)暂停和恢复服务: 一个应用服务可以在新建一个 Savepoint 后再停止服务,以便于后面任何时间点再根据这个实时刷新的 Savepoint 还原点进行恢复服务。
7)归档服务: Savepoint 还提供还原点的归档服务,以便于用户能够指定时间点的 Savepoint 的服务数据进行重置应用服务的状态,进行恢复服务。
3、监控和控制应用服务
Flink与许多常见的日志记录和监视服务集成得很好,并提供了一个REST API来控制应用服务和查询应用信息。具体表现如下:
1)Web UI方式: Flink提供了一个web UI来观察、监视和调试正在运行的应用服务。并且还可以执行或取消组件或任务的执行。
2)日志集成服务:Flink实现了流行的slf4j日志接口,并与日志框架log4j或logback集成。
3)指标服务: Flink提供了一个复杂的度量系统来收集和报告系统和用户定义的度量指标信息。度量信息可以导出到多个报表组件服务,包括 JMX, Ganglia, Graphite, Prometheus, StatsD, Datadog, 和 Slf4j.
4)标准的WEB REST API接口服务: Flink提供多种REST API接口,有提交新应用程序、获取正在运行的应用程序的Savepoint服务信息、取消应用服务等接口。REST API还提供元数据信息和已采集的运行中或完成后的应用服务的指标信息。
4、checkpoint
异步及增量式快照。
1)State Backends:生成checkpoint之前保存状态信息。由 Flink 管理的 keyed state 是一种分片的键/值存储,每个 keyed state 的工作副本都保存在负责该键的 taskmanager 本地中。另外,Operator state 也保存在机器节点本地。Flink 定期获取所有状态的快照,并将这些快照复制到持久化的位置,例如分布式文件系统。Flink 管理的状态存储在 state backend 中。Flink 有两种 state backend 的实现 :
——基于 RocksDB 内嵌 key/value 存储将其工作状态保存在磁盘上的;
——另一种基于堆的 state backend,将其工作状态保存在 Java 的堆内存中。这种基于堆的 state backend 有两种类型:FsStateBackend,将其状态快照持久化到分布式文件系统;MemoryStateBackend,它使用 JobManager 的堆保存状态快照。
2)快照:快照包括指向每个数据源的指针(例如,到文件或 Kafka 分区的偏移量)以及每个作业的有状态运算符的状态副本,该状态副本是处理了 sources 偏移位置之前所有的事件后而生成的状态
3)barriers:当 checkpoint coordinator(job manager 的一部分)指示 task manager 开始 checkpoint 时,它会让所有 sources 记录它们的偏移量,并将编号的 checkpoint barriers 插入到它们的流中。Flink 的 state backends 利用写时复制(copy-on-write)机制允许当异步生成旧版本的状态快照时,能够不受影响地继续流处理。只有当快照被持久保存后,这些旧版本的状态才会被当做垃圾回收。
4)批处理程序的容错功能不使用检查点。通过完全重播流来进行恢复;DataSet API中的状态操作使用简化的内存/核外数据结构;DataSet API引入了特殊的同步(基于超步)迭代
5、实时处理
1)window:窗口分为滚动窗口、滑动窗口、时间窗口。
2)水印:Flink的数据源在确认所有小于某个时间戳的消息都已输出到Flink流处理系统后,会生成一个包含该时间戳的WaterMark,插入到消息流中输出到Flink流处理系统中,Flink operator算子按照时间窗口缓存所有流入的消息。
3)水印产生:
——Punctuated:数据流中每一个递增的EventTime都会产生一个Watermark。在实际的生产中Punctuated方式在TPS很高的场景下会产生大量的Watermark在一定程度上对下游算子造成压力,所以只有在实时性要求非常高的场景才会选择Punctuated的方式进行Watermark的生成。
——Periodic:周期性的(一定时间间隔或者达到一定的记录条数)产生一个Watermark。在实际的生产中Periodic的方式必须结合时间和积累条数两个维度继续周期性产生Watermark,否则在极端情况下会有很大的延时。