资讯详情

第一课 大数据技术之Fink1.13的实战学习-部署使用和基础概念

第一课 大数据技术之一Fink1.13的实战学习

文章目录

  • 第一课 大数据技术之一Fink1.13的实战学习
    • 第一节 Fink介绍
      • 1.1 Flink介绍背景
      • 1.2 Flink 的应用场景
      • 1.3 介绍流式数据处理
      • 1.4 流式数据处理的发展
      • 1.5 流式数据处理的典型应用
      • 1.6 Flink 的特性总结
      • 1.7 Flink与 Spark的比较
    • 第二节 Flink 快速上手
      • 2.1 环境准备
      • 2.2 编写代码逻辑-批处理
      • 2.3 流程处理-文件数据
      • 2.4 流处理-读取socket文本流
    • 第三节 Flink 部署
      • 3.1 快速启动一个 Flink 集群
      • 3.2 向集群提交作业
      • 3.3 部署模式
      • 3.4 独立模式(Standalone)
      • 3.5 YARN 模式
    • 第四节 Flink 运行时架构
      • 4.1 系统架构
      • 4.2 JobManager和TaskManager
      • 4.3 作业提交流程
      • 4.4 数据流图和算子介绍
      • 4.5 并行度介绍
      • 4.6 算子链介绍
      • 4.7 作业图和执行图
      • 4.8 任务槽和任务槽

第一节 Fink介绍

1.1 Flink介绍背景

  1. Flink 是 Apache 基金会旗下的一个开源大数据处理框架。目前,Flink 已成为各大公司实时处理大数据的重点,特别是以阿里为代表的国内众多互联网大厂商正在全力投资Flink 社区贡献了大量的源代码。如今 Flink 许多人认为这是大数据实时处理的方向和未来,许多公司也在招聘和储备 Flink 技术人才。
  2. Flink 起源和设计理念
    • Flink 起源于一个名字 Stratosphere 这个项目是由的 3 位于柏林的大学和其他欧洲大学 2010~2014 年共同进行的研究项目,由柏林理工大学的教授沃克尔·马尔科(Volker Markl)领衔开发。2014 年 4 月,Stratosphere 代码被复制并捐赠给 Apache 软件基金会,Flink 在此基础上重新设计。
    • 在德语中,flink快速灵巧一词。 logo 这不仅仅是因为它是一只彩色松鼠 Apache 大数据项目对动物的偏好是否相关 Hadoop、Hive?),更重要的是,小动物松鼠完美地体现了快速、灵巧的特点。
  3. 从命名可以从命名中看到 Flink 项目对于自身特点的定位,那就是对于大数据处理,要做到快速和灵活。
    • 2014 年 8 月,Flink 第一个版本 0.6 正式发布(至于 0.5 之前的版本,也就是在Stratosphere 名下)。与此同时。 Fink 几位核心开发者创立了 Data Artisans 公司,主要做 Fink 帮助企业部署大规模数据处理解决方案的商业应用。
    • 2014 年 12 月,Flink 项目孵化完成后,一跃成为 Apache 顶级软件基金会项目。
    • 2015 年 4 月,Flink 重要版本的里程碑发布了 0.9.0.国内外很多大公司也开始关注和参与 Flink 社区建设。
    • 2019 年 1 月,长期对 Flink 阿里巴巴投资研发 9000 以1万欧元的价格收购 Data Artisans 公司;之后又将自己的内部版本 Blink 开源,然后和 8 月份发布的 Flink 1.9.合并0版本。自此之后,Flink 新一代大数据处理框架被越来越多的人所熟知。
  4. 由此可见,Flink 从真正开始到火爆只需要几年时间。短短几年,Flink 从最初的第一个稳定版本开始 0.9.到目前为止已经发布了 1.13.在此期间,新功能、新特性不断加入。从一开始,Flink 拥有一个非常活跃的社区,并且一直在快速成长。到目前为止,Flink的代码贡献(Contributors)已经超过 800 人,并且 Flink 它已发展成为最复杂的开源流处理引擎之一,并得到了广泛的应用。 根据 Apache 软件基金会发布 2020 年度报告,Flink 该项目的社区参与和贡献仍然非常活跃 Apache 它的许多项目都保持着许多领先地位:
    • 邮件列表(Mailing List)活动,排名第一
    • 代码提交(Commits)数,排名第二
    • GitHub 访问量排名第二
  5. Flink 就像一列高速列车向我们呼啸而来,奔向未来更实时、更稳定的大数据处理。我们可以迟到地上车,但不要错过这辆通往未来的车。
  6. 我们需要记住 Flink 的官网主页地址:https://flink.apache.org/
  7. 在 Flink 从官网主页的顶部可以看出,项目的核心目标是(Stateful Computations over Data Streams)。
  8. 具体定位如下:Apache Flink 如图所示 1-2 用于有状态计算无界和有界数据流。Flink 以内存执行速度和任群环境中运行,计算内存执行速度和任何规模。 在这里插入图片描述
  9. Flink 是流式大数据处理引擎。内存执行速度和任意规模突出 Flink 两个特点:速度快,可扩展性强

1.2 Flink 的应用场景

  1. Flink 它是一种大数据流处理引擎,可以为不同的行业提供大数据实时处理解决方案。 Flink 如今,世界上许多公司都能看到快速发展和完善 Flink 目前,北美、欧洲和金砖国家都在全球范围内 Flink 流行区域的应用。当然,这些地区实际上是 IT、互联网产业比较发达的地区。
  2. Flink 由于阿里的贡献和带头效应,在中国尤其受欢迎,另一方面也与中国的应用场景密切相关。中国的人口规模和互联网使用的普及决定了大数据处理的速度,迫使中国互联网企业追求更高的数据处理效率。想象一下,在中国,一个网站可能不得不面对数亿日常用户和每秒数亿次的计算峰值,这是许多外国公司无法想象的。而Flink 为我们高速准确地处理海量流式数据提供了可能。
  3. Flink 应用于企业。Flink 为世界上许多公司和企业的关键业务应用提供了强有力的支持。
    • 对于数据处理,任何行业或公司的需求实际上都是相同的:数据规模大、实时要求高、结果准确、扩展方便、故障后可恢复——作为新一代大数据流处理引擎 Flink 可以满足统一!这就是! Flink 广泛应用于世界各地的原因。
  4. 以熟悉的阿里为例。庞大的电子商务公司阿里巴巴为买卖双方提供了交易平台。。用户购买或浏览的商品可以作为推荐的基础,这就是为什么我们经常发现网站刚刚推出。当用户数据量非常大时,特别难以快速分析响应并实时提出准确的推荐。 Flink 这样,真正意义上的大数据流处理引擎就可以做到这一点。这也是阿里在 Flink 充分努力,成为领导者的原因。
  5. Flink 从主要的应用场景可以看出,各行业的许多公司都在使用它 Flink,他们到底用过 Flink 处理什么需求?换句话说,什么场景最适合? Flink 大展身手呢?
  6. 回到 Flink 它是一个大数据流处理引擎,处理流数据,即数据流(Data Flow)。顾名思义,数据流的意义是,数据不是收集好的,而是像水流一样,是一组有序的数据序列,一个接一个地到达和处理。由于数据到达后会立即处理,流处理的一个主要特点是快速,即良好的实时性。Flink 适合的场景,其实也就是需要实时处理数据流的场景。 具体来看,一些行业中的典型应用有:

1.3 流式数据处理的介绍

  1. 我们已经了解,Flink 的主要应用场景,就是处理大规模的数据流。那为什么一定要用 Flink呢?数据处理还有没有其他的方式?要解答这个疑惑,我们就需要先从流处理和批处理的概念讲起。
  2. 数据处理有不同的方式。
    • 对于具体应用来说,有些场景数据是一个一个来的,是一组有序的数据序列,我们把它叫作“数据流”;而有些场景的数据,本身就是一批同时到来,是一个有限的数据集,这就是批量数据(有时也直接叫数据集)。
    • 容易想到,处理数据流,当然应该“来一个就处理一个”,这种数据处理模式就叫作流处理;
  3. 那真实的应用场景中,到底是数据流更常见、还是批量数据更常见呢?
    • 生活中,这两种形式的数据都有,如图 1-4 所示。比如我们日常发信息,可以一句一句地说,也可以写一大段一起发过去。一句一句的信息,就是一个一个的数据,它们构成的序列就是一个数据流;而一大段信息,是一组数据的集合,对应就是批量数据(数据集)。
  4. 不论传输处理的方式是怎样的,数据的生成,一般都是流式的。
    • 在 IT 应用场景中,这一点会体现得更加明显。企业的绝大多数应用程序,都是在不停地接收用户请求、记录用户行为和系统日志,或者持续接收采集到的状态信息。所以数据会在不同的时间持续生成,形成一个有序的数据序列——这就是典型的数据流。
  5. 所以流数据更真实地反映了我们的生活方式。真实场景中产生的,一般都是数据流。那处理数据流,就一定要用流处理的方式吗?
    • 这个问题似乎问得有点无厘头。不过仔细一想就会发现,很多数据流的场景其实也可以用“攒一批”的方式来处理。比如聊天,我们可以收到一条信息就回一条;也可以攒很多条一起回复。对于应用程序,也可以把要处理的数据先收集齐,然后才一并处理。但是这样做的缺点也非常明显:数据处理不够及时,实时性变差了。流处理,是真正的即时处理,没有“攒批”的等待时间,所以会更快、实时性更好。
    • 另外,在批处理的过程中,必须有一个固定的时间节点结束“攒批”的过程、开始计算。而数据流是连续不断、无休无止的,我们没有办法在某一时刻说:“好!现在收集齐所有数据了,我们可以开始分析了。”如果我们需要实现“持续计算”,就必须采用流处理的方式,来处理数据流。
  6. 很显然,对于流式数据,用流处理是最好、也最合理的方式。
    • 但我们知道,传统的数据处理架构并不是这样。无论是关系型数据库、还是数据仓库,都倾向于先“收集数据”,然后再进行处理。为什么不直接用流处理的方式呢?这是因为,分布式批处理在架构上更容易实现。想想生活中发消息聊天的例子,我们就很容易理解了:如果来一条消息就立即处理,“微信秒回”,这样做一定会很受人欢迎;但是这要求自己必须时刻关注新消息,这会耗费大量精力,工作效率会受到很大影响。如果隔一段时间查一下新消息,做个“批处理”,压力明显就小多了。当然,这样的代价就是可能无法及时处理有些消息,造成一定的后果。

1.4 流式数据处理的发展

  1. 想要弄清楚流处理的发展演变,我们先要了解传统的数据处理架构。
    • IT 互联网公司往往会用不同的应用程序来处理各种业务。比如内部使用的企业资源规划(ERP)系统、客户关系管理(CRM)系统,还有面向客户的 Web 应用程序。这些系统一般都 会进行分层设计:“计算层”就是应用程序本身,用于数据计算和处理;而“存储层”往往是传统的关系型数据库,用于数据存储。
  2. 我们发现,这里的应用程序在处理数据的模式上有共同之处:接收的数据是持续生成的事件,比如用户的点击行为,客户下的订单,或者操作人员发出的请求。处理事件时,应用程序需要先读取远程数据库的状态,然后按照处理逻辑得到结果,将响应返回给用户,并更新数据库状态。一般来说,一个数据库系统可以服务于多个应用程序,它们有时会访问相同的数据库或表。
  3. 这就是传统的“事务处理”架构。系统所处理的连续不断的事件,其实就是一个数据流。而对于每一个事件,系统都在收到之后进行相应的处理,这也是符合流处理的原则的。所以可以说,传统的事务处理,就是最基本的流处理架构。
  4. 对于各种事件请求,事务处理的方式能够保证实时响应,好处是一目了然的。但是我们知道,这样的架构对表和数据库的设计要求很高;当数据规模越来越庞大、系统越来越复杂时,可能需要对表进行重构,而且一次联表查询也会花费大量的时间,甚至不能及时得到返回结果。于是,作为程序员就只好将更多的精力放在表的设计和重构,以及 SQL 的调优上,而无法专注于业务逻辑的实现了——我们都知道,这种工作费力费时,却没法直接体现在产品上给老板看,简直就是噩梦。 那有没有更合理、更高效的处理架构呢?
    • 不难想到,如果我们对于事件流的处理非常简单,例如收到一条请求就返回一个“收到”,那就可以省去数据库的查询和更新了。但是这样的处理是没什么实际意义的。在现实的应用中,往往需要还其他一些额外数据。我们可以把需要的额外数据保存成一个“状态”,然后针对这条数据进行处理,并且更新状态。在传统架构中,这个状态就是保存在数据库里的。这就是所谓的“有状态的流处理”。
    • 为了加快访问速度,我们可以直接将状态保存在本地内存,如下图所示。当应用收到一个新事件时,它可以从状态中读取数据,也可以更新状态。而当状态是从内存中读写的时候,这就和访问本地变量没什么区别了,实时性可以得到极大的提升。
    • 另外,数据规模增大时,我们也不需要做重构,只需要构建分布式集群,各自在本地计算就可以了,可扩展性也变得更好。
    • 因为采用的是一个分布式系统,所以还需要保护本地状态,防止在故障时数据丢失。我们可以定期地将应用状态的一致性检查点(checkpoint)存盘,写入远程的持久化存储,遇到故障时再去读取进行恢复,这样就保证了更好的容错性。

1.5 流式数据处理的典型应用

  1. 有状态的流处理是一种通用而且灵活的设计架构,可用于许多不同的场景。具体来说,有以下几种典型应用。
  2. 事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。比较典型的就是以 Kafka 为代表的消息队列几乎都是事件驱动型应用。
  3. 这其实跟传统事务处理本质上是一样的,区别在于基于有状态流处理的事件驱动应用,不再需要查询远程数据库,而是在本地访问它们的数据,如图 1-7 所示,这样在吞吐量和延迟方面就可以有更好的性能。
  4. 另外远程持久性存储的检查点保证了应用可以从故障中恢复。检查点可以异步和增量地完成,因此对正常计算的影响非常小。
  5. .
  6. 所谓的数据分析,就是从原始数据中提取信息和发掘规律。传统上,数据分析一般是先将数据复制到数据仓库(Data Warehouse),然后进行批量查询。如果数据有了更新,必须将最新数据添加到要分析的数据集中,然后重新运行查询或应用程序。
  7. 如今,Apache Hadoop 生态系统的组件,已经是许多企业大数据架构中不可或缺的组成部分。现在的做法一般是将大量数据(如日志文件)写入 Hadoop 的分布式文件系统(HDFS)、S3 或 HBase 等批量存储数据库,以较低的成本进行大容量存储。然后可以通过 SQL-on-Hadoop类的引擎查询和处理数据,比如大家熟悉的 Hive。这种处理方式,是典型的批处理,特点是可以处理海量数据,但实时性较差,所以也叫离线分析。
  8. 如果我们有了一个复杂的流处理引擎,数据分析其实也可以实时执行。流式查询或应用程序不是读取有限的数据集,而是接收实时事件流,不断生成和更新结果。结果要么写入外部数据库,要么作为内部状态进行维护。
  9. Apache Flink 同事支持流式与批处理的数据分析应用,与批处理分析相比,流处理分析最大的优势就是低延迟,真正实现了实时。另外,流处理不需要去单独考虑新数据的导入和处理,实时更新本来就是流处理的基本模式。当前企业对流式数据处理的一个热点应用就是实时数仓,很多公司正是基于 Flink 来实现的。
  10. ETL 也就是数据的提取、转换、加载,是在存储系统之间转换和移动数据的常用方法。在数据分析的应用中,通常会定期触发 ETL 任务,将数据从事务数据库系统复制到分析数据库或数据仓库。
  11. 所谓数据管道的作用与 ETL 类似。它们可以转换和扩展数据,也可以在存储系统之间移动数据。不过如果我们用流处理架构来搭建数据管道,这些工作就可以连续运行,而不需要再去周期性触发了。比如,数据管道可以用来监控文件系统目录中的新文件,将数据写入事件日志。连续数据管道的明显优势是减少了将数据移动到目的地的延迟,而且更加通用,可以用于更多的场景。
  12. 有状态的流处理架构上其实并不复杂,很多用户基于这种思想开发出了自己的流处理系统,这就是第一代流处理器。Apache Storm 就是其中的代表。Storm 可以说是开源流处理的先锋,最早是由 Nathan Marz 和创业公司 BackType 的一个团队开发的,后来才成为 Apache 软件基金会下属的项目。Storm 提供了低延迟的流处理,但是它也为实时性付出了代价:很难实现高吞吐,而且无法保证结果的正确性。用更专业的话说,它并不能保证“ 精确一次”(exactly-once);即便是它能够保证的一致性级别,开销也相当大。关于状态一致性和exactly-once,我们会在后续展开讨论。
  13. 对于有状态的流处理,当数据越来越多时,我们必须用分布式的集群架构来获取更大的吞吐量。但是分布式架构会带来另一个问题:怎样保证数据处理的顺序是正确的呢?
  14. 对于批处理来说,这并不是一个问题。因为所有数据都已收集完毕,我们可以根据需要选择、排列数据,得到想要的结果。可如果我们采用“来一个处理一个”的流处理,就可能出现“乱序”的现象:本来先发生的事件,因为分布处理的原因滞后了。怎么解决这个问题呢?
  15. 以 Storm 为代表的第一代分布式开源流处理器,主要专注于具有毫秒延迟的事件处理,特点就是一个字“快”;而对于准确性和结果的一致性,是不提供内置支持的,因为结果有可能取决于到达事件的时间和顺序。另外,第一代流处理器通过检查点来保证容错性,但是故障恢复的时候,即使事件不会丢失,也有可能被重复处理——所以无法保证 exactly-once。
  16. 与批处理器相比,可以说第一代流处理器牺牲了结果的准确性,用来换取更低的延迟。而 批处理器恰好反过来,牺牲了实时性,换取了结果的准确。
  17. 我们自然想到,如果可以让二者做个结合,不就可以同时提供快速和准确的结果了吗?正是基于这样的思想,Lambda 架构被设计出来,如图 所示。我们可以认为这是第二代流处理架构,但事实上,它只是第一代流处理器和批处理器的简单合并。
  18. Lambda 架构主体是传统批处理架构的增强。它的“批处理层”(Batch Layer)就是由传统的批处理器和存储组成,而“实时层”(Speed Layer)则由低延迟的流处理器实现。数据到达之后,两层处理双管齐下,一方面由流处理器进行实时处理,另一方面写入批处理存储空间,等待批处理器批量计算。流处理器快速计算出一个近似结果,并将它们写入“流处理表”中。而批处理器会定期处理存储中的数据,将准确的结果写入批处理表,并从快速表中删除不准确的结果。最终,应用程序会合并快速表和批处理表中的结果,并展示出来。
  19. Lambda 架构现在已经不再是最先进的,但仍在许多地方使用。它的优点非常明显,就是兼具了批处理器和第一代流处理器的特点,同时保证了低延迟和结果的准确性。而它的缺点同样非常明显。首先,Lambda 架构本身就很难建立和维护;而且,它需要我们对一个应用程序,做出两套语义上等效的逻辑实现,因为批处理和流处理是两套完全独立的系统,它们的 API也完全不同。为了实现一个应用,付出了双倍的工作量,这对程序员显然不够友好。
    • 之前的分布式流处理架构,都有明显的缺陷,人们也一直没有放弃对流处理器的改进和完善。终于,在原有流处理器的基础上,新一代分布式开源流处理器诞生了。为了与之前的系统区分,我们一般称之为第三代流处理器,代表当然就是 Flink。
    • 第三代流处理器通过巧妙的设计,完美解决了乱序数据对结果正确性的影响。这一代系统还做到了精确一次(exactly-once)的一致性保障,是第一个具有一致性和准确结果的开源流处理器。另外,先前的流处理器仅能在高吞吐和低延迟中二选一,而新一代系统能够同时提供这两个特性。所以可以说,这一代流处理器仅凭一套系统就完成了 Lambda 架构两套系统的工作,它的出现使得 Lambda 架构黯然失色。
    • 除了低延迟、容错和结果准确性之外,新一代流处理器还在不断添加新的功能,例如高可 用的设置,以及与资源管理器(如 YARN 或 Kubernetes)的紧密集成等等。我们会将 Flink 的特性做一个总结,从中可以体会到新一代流处理器的强大。

1.6 Flink 的特性总结

  1. Flink 是第三代分布式流处理器,它的功能丰富而强大。
  2. Flink 的核心特性 Flink 区别与传统数据处理框架的特性如下。
    • 高吞吐和低延迟。每秒处理数百万个事件,毫秒级延迟。
    • 结果的准确性。Flink 提供了事件时间(event-time)和处理时间(processing-time)语义。对于乱序事件流,事件时间语义仍然能提供一致且准确的结果。
    • 精确一次(exactly-once)的状态一致性保证。
    • 可以连接到最常用的存储系统,如 Apache Kafka、Apache Cassandra、Elasticsearch、 JDBC、Kinesis 和(分布式)文件系统,如 HDFS 和 S3。
    • 高可用。本身高可用的设置,加上与 K8s,YARN 和 Mesos 的紧密集成,再加上从故障中快速恢复和动态扩展任务的能力,Flink 能做到以极少的停机时间 7×24 全天候运行。
    • 能够更新应用程序代码并将作业(jobs)迁移到不同的 Flink 集群,而不会丢失应用程序的状态。
  3. 分层 API。除了上述这些特性之外,Flink 还是一个非常易于开发的框架,因为它拥有易于使用的分层 API,整体 API 分层如图所示。
  4. 最底层级的抽象仅仅提供了有状态流,它将处理函数(Process Function)嵌入到DataStream API 中。底层处理函数(Process Function)与 DataStream API 相集成,可以对某些操作进行抽象,它允许用户可以使用自定义状态处理来自一个或多个数据流的事件,且状态具有一致性和容错保证。除此之外,用户可以注册事件时间并处理时间回调,从而使程序可以处理复杂的计算。
  5. 实际上,大多数应用并不需要上述的底层抽象,而是直接针对核心 API(Core APIs) 进行编程,比如 DataStream API(用于处理有界或无界流数据)以及 DataSet API(用于处理有界数据集)。这些 API 为数据处理提供了通用的构建模块,比如由用户定义的多种形式的转换(transformations)、连接(joins)、聚合(aggregations)、窗口(windows)操作等。DataSet API为有界数据集提供了额外的支持,例如循环与迭代。这些 API 处理的数据类型以类(classes)的形式由各自的编程语言所表示。
  6. **Table API 是以表为中心的声明式编程,其中表在表达流数据时会动态变化。**Table API 遵循关系模型:表有二维数据结构(schema)(类似于关系数据库中的表),同时 API 提供可比较的操作,例如 select、join、group-by、aggregate 等。
  7. 尽管 Table API 可以通过多种类型的用户自定义函数(UDF)进行扩展,仍不如核心 API更具表达能力,但是使用起来代码量更少,更加简洁。除此之外,Table API 程序在执行之前会使用内置优化器进行优化。
  8. 我们可以在表与 DataStream/DataSet 之间无缝切换,以允许程序将 Table API 与 DataStream 以及 DataSet 混合使用。
  9. Flink 提供的最高层级的抽象是 SQL。这一层抽象在语法与表达能力上与 Table API 类似,但是是以 SQL 查询表达式的形式表现程序。SQL 抽象与 Table API 交互密切,同时 SQL 查询可以直接在 Table API 定义的表上执行。
  10. 目前 Flink SQL 和 Table API 还在开发完善的过程中,很多大厂都会二次开发符合自己需要的工具包。而 DataSet 作为批处理 API 实际应用较少,2020 年 12 月 8 日发布的新版本 1.12.0,已经完全实现了真正的流批一体,DataSet API 已处于软性弃用(soft deprecated)的状态。用Data Stream API 写好的一套代码, 即可以处理流数据, 也可以处理批数据,只需要设置不同的执行模式。这与之前版本处理有界流的方式是不一样的,Flink 已专门对批处理数据做了优化处理。本书中以介绍 DataStream API 为主,采用的是目前最新版本 Flink 1.13.0。

1.7 Flink与 Spark的比较

  1. 谈到大数据处理引擎,不能不提 Spark。Apache Spark 是一个通用大规模数据分析引擎。它提出的内存计算概念让大家耳目一新,得以从 Hadoop 繁重的 MapReduce 程序中解脱出来,可以说是划时代的大数据处理框架。除了计算速度快、可扩展性强,Spark 还为批处理(Spark SQL)、流处理(Spark Streaming)、机器学习(Spark MLlib)、图计算(Spark GraphX)提供了统一的分布式数据处理平台,整个生态经过多年的蓬勃发展已经非常完善。

  2. 然而正在大家认为 Spark 已经如日中天、即将一统天下之际,Flink 如一颗新星异军突起,使得大数据处理的江湖再起风云。很多读者在最初接触都会有这样的疑问:想学习一个大数据处理框架,到底选择 Spark,还是 Flink 呢?

  3. 这就需要我们了解两者的主要区别,理解它们在不同领域的优势。

  4. 数据处理架构。我们已经知道,数据处理的基本方式,可以分为批处理和流处理两种。批处理针对的是有界数据集,非常适合需要访问海量的全部数据才能完成的计算工作,一般用于离线统计。流处理主要针对的是数据流,特点是无界、实时, 对系统传输的每个数据依次执行操作,一般用于实时统计。

  5. 从根本上说,Spark 和 Flink 采用了完全不同的数据处理方式。可以说,两者的世界观是截然相反的。

  6. Spark 以批处理为根本,并尝试在批处理之上支持流计算;在 Spark 的世界观中,万物皆批次,离线数据是一个大批次,而实时数据则是由一个一个无限的小批次组成的。所以对于流处理框架 Spark Streaming 而言,其实并不是真正意义上的“流”处理,而是“微批次”(micro-batching)处理

  7. 而 Flink 则认为,流处理才是最基本的操作,批处理也可以统一为流处理。在 Flink 的世界观中,万物皆流,实时数据是标准的、没有界限的流,而离线数据则是有界限的流。如图所示,就是所谓的无界流和有界流。

    • 数据流(Unbounded Data Stream)所谓无界数据流,就是有头没尾,数据的生成和传递会开始但永远不会结束,如图 1-13所示。我们无法等待所有数据都到达,因为输入是无界的,永无止境,数据没有“都到达”的时候。所以对于无界数据流,必须连续处理,也就是说必须在获取数据后立即处理。在处理无界流时,为了保证结果的正确性,我们必须能够做到按照顺序处理数据。
    • 有界数据流(Bounded Data Stream)对应的,有界数据流有明确定义的开始和结束,如图所示,所以我们可以通过获取所有数据来处理有界流。处理有界流就不需要严格保证数据的顺序了,因为总可以对有界数据集进行排序。有界流的处理也就是批处理。
  8. 正因为这种架构上的不同,Spark 和 Flink 在不同的应用领域上表现会有差别。一般来说,Spark 基于微批处理的方式做同步总有一个“攒批”的过程,所以会有额外开销,因此无法在流处理的低延迟上做到极致。在低延迟流处理场景,Flink 已经有明显的优势。而在海量数据的批处理领域,Spark 能够处理的吞吐量更大,加上其完善的生态和成熟易用的 API,目前同样优势比较明显。

  9. 。Spark 底层数据模型是弹性分布式数据集(RDD),Spark Streaming 进行微批处理的底层接口 DStream,实际上处理的也是一组组小批数据 RDD 的集合。可以看出,Spark 在设计上本身就是以批量的数据集作为基准的,更加适合批处理的场景。而 Flink 的基本数据模型是数据流(DataFlow),以及事件(Event)序列。Flink 基本上是完全按照 Google 的 DataFlow 模型实现的,所以从底层数据模型上看,Flink 是以处理流式数据作为设计目标的,更加适合流处理的场景。数据模型不同,对应在运行处理的流程上,自然也会有不同的架构。Spark 做批计算,需要将任务对应的 DAG 划分阶段(Stage),一个完成后经过 shuffle 再进行下一阶段的计算。而Flink 是标准的流式执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理。 10.Spark 还是 Flink?

    • 通过前文的分析,我们已经可以看出,Spark 和 Flink 可以说目前是各擅胜场,批处理领域 Spark 称王,而在流处理方面 Flink 当仁不让。具体到项目应用中,不仅要看是流处理还是批处理,还需要在延迟、吞吐量、可靠性,以及开发容易度等多个方面进行权衡。
    • 如果在工作中需要从 Spark 和 Flink 这两个主流框架中选择一个来进行实时流处理,我们更加推荐使用 Flink,主要的原因有:
      • Flink 的延迟是毫秒级别,而 Spark Streaming 的延迟是秒级延迟。
      • Flink 提供了严格的精确一次性语义保证。
      • Flink 的窗口 API 更加灵活、语义更丰富。
      • Flink 提供事件时间语义,可以正确处理延迟数据。
      • Flink 提供了更加灵活的对状态编程的 API。
  10. 基于以上特点,使用 Flink 可以解放程序员, 加快编程效率, 把本来需要程序员花大力气手动完成的工作交给框架完成。当然,在海量数据的批处理方面,Spark 还是具有明显的优势。而且 Spark 的生态更加成熟,也会使其在应用中更为方便。相信随着 Flink 的快速发展和完善,这方面的差距会越来越小。

  11. 另外,Spark 2.0 之后新增的 Structured Streaming 流处理引擎借鉴 DataFlow 进行了大量优化,同样做到了低延迟、时间正确性以及精确一次性语义保证;Spark 2.3 以后引入的连续处理(Continuous Processing)模式,更是可以在至少一次语义保证下做到 1 毫秒的延迟。而 Flink自 1.9 版本合并 Blink 以来,在 SQL 的表达和批处理的能力上同样有了长足的进步。

第二节 Flink 快速上手

2.1 环境准备

  1. Flink 底层是以 Java 编写的,并为开发人员同时提供了完整的 Java 和 Scala API。
  2. IntelliJ IDEA 作为开发工具,用实际项目中最常见的Maven 作为包管理工具,在开发环境中编写一个简单的 Flink 项目,实现零基础快速上手。
    • java 8
    • IDEA
    • Maven、Git
    • Flink 1.13.0
  3. 创建Maven 工程, 工程命名为 FlinkTutorial。添加项目依赖,在项目的 pom 文件中,我们需要添加的依赖最重要的就是 Flink 的相关组件,包括** flink-java、flink-streaming-java,以及 flink-clients(客户端,也可以省略)**。另外,为了方便查看运行日志,我们引入 slf4j 和 log4j 进行日志管理。
    <properties>
        <flink.version>1.13.0</flink.version>
        <java.version>1.8</java.version> <scala.binary.version>2.12</scala.binary.version>
        <slf4j.version>1.7.30</slf4j.version>
    </properties>

    <dependencies>
        <!-- 引入 Flink 相关依赖-->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId> <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java_${scala.binary.version}</artifactId> <version>${flink.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients_${scala.binary.version}</artifactId>
            <version>${flink.version}</version>
        </dependency>
        <!-- 引入日志管理相关依赖-->
        <dependency>
            <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId> <version>2.14.0</version>
        </dependency>
    </dependencies>
  1. 这里做一点解释:在属性中,我们定义了<scala.binary.version>,这指代的是所依赖的 Scala 版本。这有一点奇怪:Flink 底层是 Java,而且我们也只用 Java API,为什么还会依赖 Scala 呢?。我们本书中用到的 Scala 版本为 2.12。
  2. 配置日志管理, 在目录 src/main/resources 下添加文件:log4j.properties,内容配置如下:
log4j.rootLogger=error, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

2.2 编写代码逻辑-批处理

  1. 我们会用一个最简单的示例来说明 Flink 代码怎样编写:统计一段文字中,每个单词出现的频次。这就是传说中的WordCount 程序——它是大数据领域非常经典的入门案例,地位等同于初学编程语言时的Hello World。
  2. 我们的源码位于 src/main/java 目录下。首先新建一个包,命名为com.atguigu.wc,在这个包下我们将编写 Flink 入门的 WordCount 程序。
  3. 尽管 。所以接下来,我们会针对不同的处理模式、不同的输入数据形式,分别讲述 WordCount 代码的实现。
  4. :对于批处理而言,输入的应该是收集好的数据集。这里我们可以将要统计的文字,写入一个文本文档,然后读取这个文件处理数据就可以了。
    • 在工程根目录下新建一个 input 文件夹,并在下面创建文本文件 words.txt
    • 在 words.txt 中输入一些文字
    • com.atguigu.chapter02包下新建 Java 类BatchWordCount,在静态 main 方法中编写测试代码。
hello world 
hello flink 
hello java
  1. 我们进行单词频次统计的基本思路是:先逐行读入文件数据,然后将每一行文字拆分成单词;接着按照单词分组,统计每组数据的个数,就是对应单词的频次。
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.operators.AggregateOperator;
import org.apache.flink.api.java.operators.DataSource;
import org.apache.flink.api.java.operators.FlatMapOperator;
import org.apache.flink.api.java.operators.UnsortedGrouping;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;

public class BatchWordCount { 
        
    public static void main(String[] args) throws Exception { 
        
        // 1. 创建执行环境
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        // 2. 从文件读取数据 按行读取(存储的元素就是每行的文本)
        DataSource<String> lineDS = env.readTextFile("input/words.txt");
        // 3. 将每行数据进行分词,转换成二元组类型
        FlatMapOperator<String, Tuple2<String, Long>> wordAndOne = lineDS.flatMap((String line, Collector<Tuple2<String, Long>> out) -> { 
        
                        // 将一行文本进行分词
                        String[] words = line.split(" ");
                        // 将每个单词转换成二元组
                        for (String word : words) { 
        
                            out.collect(Tuple2.of(word, 1L));
                        }
                // 注意: 当 Lambda 表达式 使用 Java 泛型的时候, 由于泛型擦除的存在, 需要显示的声明类型信息
                }).returns(Types.TUPLE(Types.STRING, Types.LONG));
        // 4. 按照 word 进行分组
        UnsortedGrouping<Tuple2<String, Long>>	wordAndOneUG =  wordAndOne.groupBy(0);
        // 5. 分组内聚合统计
         

标签: 压力变送器tm21

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台