大数据实时流式计算引擎 Flink 简单剖析
Posted 野指针er
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据实时流式计算引擎 Flink 简单剖析相关的知识,希望对你有一定的参考价值。
本文目录
1.Hadoop、Spark和Storm简介及特点
2.Flink简介及特点
3.Flink exactly-once(恰好一次语义)
4.Flink window(窗口机制)
5.Flink集群启动架构
1.Hadoop、 Spark和Storm简介及特点
当今,大数据平台最流行的莫过于Hadoop。它是Apache 软件基金会下的一个开源分布式计算平台,主要思想是将一个大型的任务切割成多个部分给多台计算机,让每台计算机处理其中的一部分。
在硬盘存储层面,Hadoop 的数据处理工作借助HDFS,将架构下每一台计算机中的硬盘资源汇聚起来,无论是存储计算还是调用,都可以视为一块硬盘使用,就像计算机中的C盘、D盘。
在计算处理层面,Hadoop 利用MapReduce 进行计算编程,将复杂的、运行在大规模集群上的并行计算过程高度抽象成两个函数—— Map (映射)和Reduce(归约)。
●高可靠性。采用冗余数据存储方式,即使某副本发生故障,其他的仍能正常提供服务。
●高效性。采用分布式存储和分布式处理两大核心技术,能高效处理PB级数据。
●成本低。采用廉价计算机集群,成本低,普通用户很容易搭建。
●可扩展性。可高效稳定运行在廉价的计算机集群上,扩展到数以千计的计算机节点上。
然而任何事物都不是完美的。hadoop由于计算过程放在硬盘上,受制于硬件条件限制,数据的吞吐和处理速度明显不如使用内存快,尤其是进行迭代计算时,非常耗资源,且在开发过程中需要编写不少相对底层的代码,不够高效。
我们知道,大数据的计算模式主要分为批量计算(batch computing)、流式计算(stream computing)、交互计算(interactive computing)、图计算(graph computing)等。其中主要的流式计算引擎有Spark Streaming、Storm 和Flink三种,解决了处理速度和实时性问题。
我们先来看一下Spark。Spark 也是Apache 软件基金会下的开源项目,用Scala 语言编写的,用于对大规模数据的快速处理,它与Hadoop 相比最大的优点就是“快”,当初设计目标也是如此。为了使程序运行更快,Spark提供了内存计算,减少了迭代计算时的I/O开销。Spark 不但具备Hadoop MapReduce的优点,而且解决了其存在的缺陷,逐渐成为当今领域最热门的计算平台。
● 速度快。采用先进的有向无环图执行引擎,以支持循环数据流与内存计算,基于内存的执行速度比Hadoop MapReduce快上百倍,基于磁盘的执行速度也较之快十倍。
● 通用性。提供体系化的技术栈,包括SQL查询、流式计算、和图等组件,这些组件可无缝整合在同一应用中,足以应对复杂计算。
● 易用性。支持Scala、Java、Python和R等语言,API设计简洁,用户上手快,且支持交互式。
● 运行模式多样。Spark可运行在独立的集群模式中,或运行在Hadoop中,也可运行在Amazon EC2等云环境中,并且可以访问HDFS、HBase、Hive等多种数据源。
Spark除了数据存储需借助Hadoop 的HDFS或Amazon S3之外,其主要功能组件包括:
SparkCore:基本通用功能,可进行复杂的批处理计算
SparkSQL:支持基于历史数据的交互式查询计算
MLlib:提供常用机器学习算法,支持基于历史数据的数据挖掘
尽管
Spark
有很多优点,但它并不能完全替代
Hadoop
,而是主要替代
MapReduce
计算引擎。在实际应用中,
Spark
常与
Hadoop
结合使用,它可以借助
YARN
来实现资源调度管理,借助
HDFS
实现分布式存储。
Storm主要用于实时的流式数据处理,它与Spark 最大的区别在于“实时性”的差异:Spark 是“准实时”的,它先收集一段时间的数据再进行统一处理,好比看网页统计票数,每隔一段时间刷新一次;而Storm 则是“完全实时”的,来一条数据就立刻处理一条,源源不断地流入。
但Storm 的缺点在于,无论是离线、高延迟,还是交互式查询,它都不如Spark 框架。不同的机制决定了二者所适用的场景不同,比如炒股,股价的变化不是按秒计算的,因此适合采用计算延迟度为秒级的Spark 框架;而高频交易往往就在1ms之间,就比较适合采用实时计算延迟度低的Storm 框架。
●整合性。Storm可方便地与消息队列系统(如Kafka)和数据库系统进行整合。
●可扩展性。Storm的并行特性使其可以运行在分布式集群中。
●简易的API。Storm的API在使用上既简单又方便。
●可靠的消息处理。Storm保证每个消息都能完整处理。
●容错性。Storm可以自动进行故障节点的重启,以及节点故障时任务的重新分配。
●支持多种语言。Storm支持使用各种语言来定义任务。
Flink是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
任何类型的数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。
无界流
:有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。
有界流
:有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理。
精确的时间控制和状态化使得 Flink的运行时(runtime)能够运行任何处理无界流的应用。有界流则由一些专为固定大小数据集特殊设计的算法和数据结构进行内部处理,都有出色的性能。
Flink是一个分布式系统,它需要计算资源来执行应用程序。Flink集成了所有常见的集群资源管理器,例如 Hadoop YARN、 Apache Mesos 和 Kubernetes 等,但同时也可以作为独立集群运行。
Flink旨在任意规模上运行有状态流式应用。因此,应用程序被并行化为可能数千个任务,这些任务分布在集群中并发执行。所以应用程序能够充分利用无尽的CPU、内存、磁盘和网络IO。而且Flink很容易维护非常大的应用程序状态。其异步和增量的检查点(checkpoint)算法对处理延迟产生最小的影响,同时保证恰好一次(exactly-once)状态的一致性。
如果处理一个事件(或一条数据)的结果只跟事件本身的内容有关,称为无状态处理;反之结果还和之前处理过的事件有关,称为有状态处理。稍微复杂一点的数据处理,比如说基本的聚合,数据流之间的关联都是有状态处理。
有状态的Flink程序针对本地状态访问进行了优化。任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中。任务通过访问本地(通常在内存中)状态来进行所有的计算,从而产生非常低的处理延迟。Flink通过定期和异步地对本地状态进行持久化存储来保证故障场景下恰好一次(exactly-once)的状态一致性。
State、Checkpoint、Time、Window
支持容错机制。Flink开启Checkpoint之后,会按照一定的时间间隔对程序的运行状态进行备份,当发生故障时,会将所有任务的状态恢复至最后一次发生 Checkpoint 中的状态,并从那里开始重新开始执行。
支持状态存储。State可存储在内存、磁盘、文件、RocksDB 等。
提供多种 Time语义。如Event time、Ingestion Time、Processing Time。
提供灵活的窗口机制。如 Time Window、Count Window、Session Window,还支持自定义Window。
3. Flink exactly-once(恰好一次语义)
Storm仅能保证“最多一次”(AtMost Once) 和“至少一次”(AtLeast Once) 的消息投递语义,即可能存在重复发送的情况。有很多业务场景对数据的精确性要求较高,希望消息投递不重不漏,Flink支持“恰好一次”(Exactly Once)的语义。
这本质上是一种尽力而为的方法。保证数据或事件最多由应用程序中的所有算子处理一次。这意味着如果数据在被流应用程序完全处理之前发生丢失,则不会进行其他重试或者重新发送。
应用程序中的所有算子都保证数据或事件至少被处理一次。这通常意味着如果事件在流应用程序完全处理之前丢失,则将从源头重放或重新传输事件。然而,由于事件是可以被重传的,因此一个事件有时会被处理多次,这就是所谓的至少一次。
即使是在各种故障的情况下,流应用程序中的所有算子都保证事件只会被恰好一次的处理。Flink使用状态检查点机制来实现恰好一次处理语义。
实现『恰好一次』的状态检查点方法受到分布式快照算法的启发。通过这种机制,流应用程序中每个算子的所有状态都会定期做checkpoint。如果是在系统中的任何地方发生失败,每个算子的所有状态都回滚到最新的全局一致 checkpoint 点。在回滚期间,将暂停所有处理。源也会重置为与最近 checkpoint 相对应的正确偏移量。
在时间T1流处理程序正常工作,并且做了checkpoint。
在时间T2,由于算子未能处理输入的数据。此时S=4 的状态值已保存到持久存储器中,而状态值S=12 保存在算子的内存中。
为了修复这种差异,在时间T3,处理程序将状态回滚到 S=4 并“重放”流中的每个连续状态直到最近,并处理每个数据。
最终结果是有些数据已被处理了多次,但这没关系,因为无论执行了多少次回滚,结果状态都是相同的。即:事件的处理可以发生多次,但是该处理的效果只在持久后端状态存储中反映一次。
Flink认为批处理是流处理的一个特例,所以Flink底层引擎是一个流式引擎,在上面实现了流处理和批处理。而窗口(window)就是从流处理到批处理的一个桥梁。
流计算中一般在对流数据进行操作之前都会先进行开窗,即基于一个什么样的窗口上做这个计算。Flink提供了开箱即用的各种窗口,比如滑动窗口、滚动窗口、会话窗口以及非常灵活的自定义的窗口。
在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户点击了我们的网页。在这种情况下,我们必须定义一个窗口,用来收集最近1分钟内的数据,并对这个窗口内的数据进行计算。
窗口可以是时间驱动的(Time Window,例如:每30秒钟),也可以是计数驱动的(Count Window,例如:每一百个元素)。一种经典的窗口分类可以分成:翻滚窗口(Tumbling Window,无重叠),滚动窗口(Sliding Window,有重叠),和会话窗口(Session Window,活动间隙)。
我们举个具体的场景来形象地理解不同窗口的概念。假设,淘宝会记录每个用户每次购买的商品个数,我们要做的是统计不同窗口中用户购买商品的总数。下图给出了几种经典的窗口切分图:
上图中,raw stream data 代表用户的购买行为流,圈中的数字代表该用户本次购买的商品个数,事件是按时间分布的,所以可以看出事件之间是有time gap 的。
会话窗口:计算每个用户在活跃期间总共购买的商品数量,如果用户30秒没有活动则视为会话断开。(假设rawdata stream是单个用户的购买行为流)。
翻滚计数窗口:每当窗口中填满3个购买用户,则统计购买商品总数。
滑动时间窗口:每30秒计算一次最近1分钟用户购买的商品总数。
翻滚时间窗口:将用户的购买行为按每1分钟进行切分。
当Flink集群启动后,首先会启动一个JobManger和一个或多个的TaskManager。由 Client提交任务给JobManager,JobManager再调度任务到各个TaskManager去执行,然后TaskManager将心跳和统计信息汇报给JobManager。TaskManager之间以流的形式进行数据的传输。上述三者均为独立的JVM进程。
ProgramCode
:我们编写的Flink应用程序代码。
Client
:为提交 Job的客户端。提交Job 后,Client可以结束进程(Streaming的任务),也可以不结束并等待结果返回。
JobManager
:主要负责调度 Job 并协调Task 做 checkpoint。
从Client处接收到 Job 和JAR 包等资源后,会生成优化后的执行计划,并以 Task 的单元调度到各个TaskManager去执行。
TaskManager
:在启动的时候就设置好了槽位数(Slot),每个槽能启动一个Task,Task为线程。从JobManager处接收需要部署的Task并部署启动。
Flink编程模型的抽象层级主要分为以下4种,越往下抽象度越低,编程越复杂,灵活度越高。
这4层中,一般用于开发的是第三层,即DataStrem/DataSetAPI。用户可以使用 DataStream API 处理无界数据流,使用 DataSet API 处理有界数据流。同时这两个API都提供了各种各样的接口来处理数据。例如常见的map、filter等,而且支持java、python、scala等编程语言。
事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。
在传统架构中,应用计算存储分离,应用需要读写远程事务型数据库。相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入checkpoint。下图描述了传统应用和事件驱动型应用架构的区别。
事件驱动型应用无须查询远程数据库,本地数据访问具有更高的吞吐和更低的延迟。
传统架构下,通常多个应用共享同一个数据库,因而任何对数据库自身的更改都需要谨慎协调。而事件驱动型应用,由于只需考虑自身数据,因此所需的协调工作将大大减少。
传统的分析方式通常是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了得到最新数据的分析结果,必须先将它们加入分析数据集并重新执行查询或运行应用,随后将结果写入存储系统或生成报告。
和传统模式下读取有限数据集不同,流式查询会接入实时事件流,并随着事件持续产生来更新查询结果。这些结果数据可能会写入外部数据库系统或以内部状态的形式维护。仪表展示应用可以相应地从外部数据库读取数据或直接查询应用的内部状态。
下图描述了Flink同时支持批量分析及流式分析应用。
和批量分析相比,由于流式分析省掉了周期性的数据导入和查询过程,因此从事件中获取指标的延迟更低。
电信网络质量监控、消费者相关技术中的实时数据即时分析、大规模图分析。
提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。
数据管道和ETL作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个。但数据管道是以持续流模式运行,而非周期性触发。因此它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。
下图描述了周期性 ETL作业和持续数据管道的差异。
和周期性ETL作业相比,持续数据管道可以明显降低将数据移动到目的端的延迟。此外,由于它能够持续消耗和发送数据,因此用途更广。
大数据起源自批处理,Spark 最初的定位就是改进Hadoop,更快速的进行批处理。 Storm 擅长的则是进行无状态的流计算(在无状态的流计算领域,它的延迟是最小的),而Flink则是Storm 的下一代解决方案,能够进行高吞吐、低延迟(毫秒级)的有状态的流计算。
https://www.cnblogs.com/tree1123/p/11510282.html(点击原文链接查看)
吞吐量
:Storm 单线程吞吐约8.7 万条/秒。Flink单线程吞吐约35 万条/秒。即 Flink吞吐约为Storm的 3-5 倍。
延迟
:Storm QPS接近吞吐时延迟(含Kafka读写时间)中位数约100 毫秒,99线约 700 毫秒。Flink中位数约 50 毫秒,99 线约300 毫秒。即 Flink在满吞吐时的延迟约为Storm的一半,且随着QPS逐渐增大,Flink在延迟上的优势更加开始体现出来。
以上是关于大数据实时流式计算引擎 Flink 简单剖析的主要内容,如果未能解决你的问题,请参考以下文章
Storm+Kafka实现流式大数据实时日志分析
Flink原理|Flink流式计算在节省资源方面剖析
伍翀 :大数据实时计算Flink SQL解密
Flink从入门到精通100篇(二十一)-Flink 状态(State)管理在推荐场景中的应用
赵强老师免费公开课第三季:大数据实时计算
Flink面试通关手册