Apache Flink实战(一) - 简介

了解Flink是什么,Flink应用程序运行的多样化,对比业界经常使用的流处理框架,Flink的发展趋势,Flink生态圈,Flink应用场景及Flink如何进行高效的Flink学习。git

0 相关源码

1 前言

1.1 功能

1.2 用户

  • 国际
  • 国内

1.3 特色

◆ 结合Java、Scala两种语言 ◆ 从基础到实战 ◆ 系统学习Flink的核心知识 ◆ 快速完成从入门到上手企业开发的能力提高github

1.4 安排

◆ 初识Flink ◆ 编程模型及核心概念 ◆ DataSet API编程 ◆ DataStream API编程 ◆ Flink Table&SQL ◆ Window和Time操做 ◆ Flink Connectors ◆ Flink部署及做业提交 ◆ Flink监控及调优web

  • 使用Flink自定义数据源读取配置数据
  • 使用Flink完成实时数据清洗
  • 使用Flink完成实时结果统计
  • 统计结果可视化展现(Kibana)

1.5 收获

◆ 系统入门Flink开发 ◆ 掌握应用Java SE/Scala的Flink实现 ◆理解Flink项目的开发流程 ◆ 快速上手企业开发正则表达式

1.6 环境

◆ Mac OS: 10.14.12 ◆ Kafka: 1.1.1 ◆ Hadoop : CDH ( 5.15.1) ◆ ES/Kibana : 6+ ◆ FXIQ: IDEA ◆ Flink : 1.7算法

1.7 确保你已掌握

◆ 了解Linux经常使用基本命令的使用 ◆ 熟悉Java SE或Scala的基本使用 ◆ 熟悉Hadoop基础应用数据库

1.8 学习方法推荐

◆认真阅读本教程!多思考、多动手! ◆合理利用网络资源 ◆善于提问:QQ群讨论apache

2 教程大纲

◆ Flink概述 ◆ Flink应用场景 ◆ Flink Layer ◆ Flink发 展趋势 ◆ Flink应用程序运行方式多样化 ◆ 如何学习Flink ◆ Flink VS Storm VS Spark Streaming编程

Flink概述

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行状态计算。 Flink设计为在全部常见的集群环境中运行,之内存速度和任何规模执行计算。后端

在这里,咱们解释Flink架构的重要方面。bash

架构

处理无界和有界数据

任何类型的数据都是做为事件流产生的。信用卡交易,传感器测量,机器日志或网站或移动应用程序上的用户交互,全部这些数据都做为流生成。

数据能够做为无界或有界流处理。

  • 无界流有一个开始但没有定义的结束。它们不会在生成时终止并提供数据。必须连续处理无界流,即必须在摄取以后当即处理事件。没法等待全部输入数据到达,由于输入是无界的,而且在任什么时候间点都不会完成。处理无界数据一般要求以特定顺序摄取事件,例如事件发生的顺序,以便可以推断结果完整性。

  • 有界流具备定义的开始和结束。能够在执行任何计算以前经过摄取全部数据来处理有界流。处理有界流不须要有序摄取,由于能够始终对有界数据集进行排序。有界流的处理也称为批处理

  • Apache Flink擅长处理无界和有界数据集。精确控制时间和状态使Flink的运行时可以在无界流上运行任何类型的应用程序。有界流由算法和数据结构内部处理,这些算法和数据结构专为固定大小的数据集而设计,从而产生出色的性能。

经过探索在Flink之上构建的用例来讲服本身。

利用内存中性能

有状态Flink应用程序针对本地状态访问进行了优化。任务状态始终保留在内存中,若是状态大小超过可用内存,则保存在访问高效的磁盘上数据结构中。所以,任务经过访问本地(一般是内存中)状态来执行全部计算,从而产生很是低的处理延迟。 Flink经过按期和异步地将本地状态检查点到持久存储来保证在出现故障时的一次状态一致性。

应用

Apache Flink是一个用于对无界和有界数据流进行有状态计算的框架。 Flink在不一样的抽象级别提供多个API,并为常见用例提供专用库。

在这里,咱们介绍Flink易于使用和富有表现力的API和库。

流媒体应用程序的构建块

能够由流处理框架构建和执行的应用程序类型由框架控制流,状态和时间的程度来定义。在下文中,咱们描述了流处理应用程序的这些构建块,并解释了Flink处理它们的方法。

显然,流是流处理的一个基本方面。可是,流能够具备不一样的特征,这些特征会影响流的处理方式。 Flink是一个多功能的处理框架,能够处理任何类型的流。

  • 有界和无界流:流能够是无界的或有界的,即固定大小的数据集。 Flink具备处理无界流的复杂功能,但也有专门的运营商来有效地处理有界流。
  • 实时和记录的流:全部数据都做为流生成。有两种方法能够处理数据。在生成时实时处理它或将流持久保存到存储系统,例如文件系统或对象存储,并在之后处理它。 Flink应用程序能够处理记录或实时流。

状态

每一个非平凡的流应用程序都是有状态的,即,只有对各个事件应用转换的应用程序不须要状态。运行基本业务逻辑的任何应用程序都须要记住事件或中间结果,以便在之后的时间点访问它们,例如在收到下一个事件时或在特定持续时间以后。

应用状态是Flink的一等公民。您能够经过查看Flink在状态处理环境中提供的全部功能来查看。

  • 多状态基元:Flink为不一样的数据结构提供状态基元,例如原子值,列表或映射。开发人员能够根据函数的访问模式选择最有效的状态原语。
  • 可插拔状态后端:应用程序状态由可插拔状态后端管理和检查点。 Flink具备不一样的状态后端,能够在内存或RocksDB中存储状态,RocksDB是一种高效的嵌入式磁盘数据存储。也能够插入自定义状态后端。
  • 彻底一次的状态一致性:Flink的检查点和恢复算法可确保在发生故障时应用程序状态的一致性。所以,故障是透明处理的,不会影响应用程序的正确性。
  • 很是大的状态:因为其异步和增量检查点算法,Flink可以维持几兆兆字节的应用程序状态。 可扩展的应用程序:Flink经过将状态从新分配给更多或更少的工做人员来支持有状态应用程序的扩展。

时间

时间是流应用程序的另外一个重要组成部分大多数事件流都具备固有的时间语义,由于每一个事件都是在特定时间点生成的。此外,许多常见的流计算基于时间,例如窗口聚合,会话化,模式检测和基于时间的链接。流处理的一个重要方面是应用程序如何测量时间,即事件时间和处理时间的差别。

Flink提供了一组丰富的与时间相关的功能。

  • 事件时间模式:使用事件时间语义处理流的应用程序根据事件的时间戳计算结果。所以,不管是否处理记录的或实时的事件,事件时间处理都容许准确和一致的结果。
  • 水印支持:Flink使用水印来推断事件时间应用中的时间。水印也是一种灵活的机制,能够权衡结果的延迟和完整性。
  • 延迟数据处理:当使用水印在事件 - 时间模式下处理流时,可能会在全部相关事件到达以前完成计算。这类事件被称为迟发事件。 Flink具备多个选项来处理延迟事件,例如经过侧输出从新路由它们以及更新之前完成的结果。
  • 处理时间模式:除了事件时间模式以外,Flink还支持处理时间语义,该处理时间语义执行由处理机器的挂钟时间触发的计算。处理时间模式适用于具备严格的低延迟要求的某些应用,这些要求能够容忍近似结果。

4 Layered APIs

Flink提供三层API。 每一个API在简洁性和表达性之间提供不一样的权衡,并针对不一样的用例。

咱们简要介绍每一个API,讨论其应用程序,并显示代码示例。

ProcessFunctions

ProcessFunctions是Flink提供的最具表现力的功能接口。 Flink提供ProcessFunction来处理来自窗口中分组的一个或两个输入流或事件的单个事件。 ProcessFunctions提供对时间和状态的细粒度控制。 ProcessFunction能够任意修改其状态并注册将在将来触发回调函数的定时器。所以,ProcessFunctions能够根据许多有状态事件驱动的应用程序的须要实现复杂的每事件业务逻辑。

如下示例显示了一个KeyedProcessFunction,它对KeyedStream进行操做并匹配START和END事件。收到START事件时,该函数会记住其状态的时间戳,并在四小时内注册一个计时器。若是在计时器触发以前收到END事件,则该函数计算END和START事件之间的持续时间,清除状态并返回该值。不然,计时器只会触发并清除状态。

/**
 * Matches keyed START and END events and computes the difference between 
 * both elements' timestamps. The first String field is the key attribute, * the second String attribute marks START and END events. */ public static class StartEndDuration extends KeyedProcessFunction<String, Tuple2<String, String>, Tuple2<String, Long>> { private ValueState<Long> startTime; @Override public void open(Configuration conf) { // obtain state handle startTime = getRuntimeContext() .getState(new ValueStateDescriptor<Long>("startTime", Long.class)); } /** Called for each processed event. */ @Override public void processElement( Tuple2<String, String> in, Context ctx, Collector<Tuple2<String, Long>> out) throws Exception { switch (in.f1) { case "START": // set the start time if we receive a start event. startTime.update(ctx.timestamp()); // register a timer in four hours from the start event. ctx.timerService() .registerEventTimeTimer(ctx.timestamp() + 4 * 60 * 60 * 1000); break; case "END": // emit the duration between start and end event Long sTime = startTime.value(); if (sTime != null) { out.collect(Tuple2.of(in.f0, ctx.timestamp() - sTime)); // clear the state startTime.clear(); } default: // do nothing } } /** Called when a timer fires. */ @Override public void onTimer( long timestamp, OnTimerContext ctx, Collector<Tuple2<String, Long>> out) { // Timeout interval exceeded. Cleaning up the state. startTime.clear(); } } 复制代码

该示例说明了KeyedProcessFunction的表达能力,但也强调了它是一个至关冗长的接口。

DataStream API

DataStream API为许多常见的流处理操做提供原语,例如窗口化,一次记录转换以及经过查询外部数据存储来丰富事件。 DataStream API可用于Java和Scala,它基于函数,例如map(),reduce()和aggregate()。 能够经过扩展接口或Java或Scala lambda函数来定义函数。

如下示例显示如何对点击流进行会话并计算每一个会话的点击次数。

// a stream of website clicks
DataStream<Click> clicks = ...

DataStream<Tuple2<String, Long>> result = clicks
  // project clicks to userId and add a 1 for counting
  .map(
    // define function by implementing the MapFunction interface.
    new MapFunction<Click, Tuple2<String, Long>>() {
      @Override
      public Tuple2<String, Long> map(Click click) {
        return Tuple2.of(click.userId, 1L);
      }
    })
  // key by userId (field 0)
  .keyBy(0)
  // define session window with 30 minute gap
  .window(EventTimeSessionWindows.withGap(Time.minutes(30L)))
  // count clicks per session. Define function as lambda function.
  .reduce((a, b) -> Tuple2.of(a.f0, a.f1 + b.f1));
复制代码

SQL & Table API

Flink具备两个关系API,Table API和SQL。 这两个API都是用于批处理和流处理的统一API,即,在无界的实时流或有界的记录流上以相同的语义执行查询,并产生相同的结果。 Table API和SQL利用Apache Calcite进行解析,验证和查询优化。 它们能够与DataStream和DataSet API无缝集成,并支持用户定义的标量,聚合和表值函数。

Flink的关系API旨在简化数据分析,数据流水线和ETL应用程序的定义。

如下示例显示用于会话点击流的SQL查询,并计算每一个会话的点击次数。 这与DataStream API示例中的用例相同。

SELECT userId, COUNT(*)
FROM clicks
GROUP BY SESSION(clicktime, INTERVAL '30' MINUTE), userId
复制代码

Flink具备几个用于常见数据处理用例的库。这些库一般嵌入在API中,而不是彻底独立的。所以,他们能够从API的全部功能中受益,并与其余库集成。

  • 复琐事件处理(CEP):模式检测是事件流处理的一个很是常见的用例。 Flink的CEP库提供了一个API来指定事件模式(想一想正则表达式或状态机)。 CEP库与Flink的DataStream API集成,以便在DataStream上评估模式。 CEP库的应用包括网络入侵检测,业务流程监控和欺诈检测。

  • DataSet API:DataSet API是Flink用于批处理应用程序的核心API。 DataSet API的原语包括map,reduce,(外部)join,co-group和iterate。全部操做都由算法和数据结构支持,这些算法和数据结构对内存中的序列化数据进行操做,并在数据大小超过内存预算时溢出到磁盘。 Flink的DataSet API的数据处理算法受到传统数据库运算符的启发,例如混合散列链接或外部合并排序。

  • Gelly:Gelly是一个可扩展的图形处理和分析库。 Gelly在DataSet API之上实现并与之集成。所以,它受益于其可扩展且强大的运营商。 Gelly具备内置算法,例如标签传播,三角形枚举和页面排名,但也提供了一种Graph API,能够简化自定义图算法的实现。

5 运行多样化

5.1 随处部署应用程序

Apache Flink是一个分布式系统,须要计算资源才能执行应用程序。 Flink与全部常见的集群资源管理器(如Hadoop YARN,Apache Mesos和Kubernetes)集成,但也能够设置为做为独立集群运行。

Flink旨在很好地运做之前列出的每一个资源管理器。 这是经过特定于资源管理器的部署模式实现的,这些模式容许Flink以其惯用方式与每一个资源管理器进行交互。

部署Flink应用程序时,Flink会根据应用程序配置的并行性自动识别所需资源,并从资源管理器请求它们。 若是发生故障,Flink会经过请求新资源来替换发生故障的容器。提交或控制应用程序的全部通讯都经过REST调用。 这简化了Flink在许多环境中的集成。

5.2 以任何规模运行应用程序

Flink旨在以任何规模运行有状态流应用程序。 应用程序并行化为数千个在集群中分布和同时执行的任务。所以,应用程序能够利用几乎无限量的CPU,主内存,磁盘和网络IO。并且,Flink很容易保持很是大的应用程序状态。其异步和增量检查点算法确保对处理延迟的影响最小,同时保证一次性状态一致性。

用户报告了在其生产环境中运行的Flink应用程序使人印象深入的可扩展性数字,例如

  • 应用程序天天处理数万亿个事件,
  • 应用程序维护多个TB的状态
  • 运行在数千个核心上的应用程序

6 业界流处理框架对比

7 Flink 使用案例

Apache Flink 功能强大,支持开发和运行多种不一样种类的应用程序。它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。 Flink 不只能够运行在包括 YARN、 Mesos、Kubernetes 在内的多种资源管理框架上,还支持在裸机集群上独立部署。 在启用高可用选项的状况下,它不存在单点失效问题。事实证实,Flink 已经能够扩展到数千核心,其状态能够达到 TB 级别,且仍能保持高吞吐、低延迟的特性。世界各地有不少要求严苛的流处理应用都运行在 Flink 之上。

接下来咱们将介绍 Flink 常见的几类应用并给出相关实例连接。

  • [事件驱动型应用]
  • [数据分析应用]
  • [数据管道应用]

7.1 事件驱动型应用

7.1.1 什么是事件驱动型应用?

事件驱动型应用是一类具备状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其余外部动做。

事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用须要读写远程事务型数据库。

相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)便可获取数据。系统容错性的实现依赖于按期向远程持久化存储写入 checkpoint。

  • 传统应用和事件驱动型应用架构的区别

7.1.2 事件驱动型应用的优点?

事件驱动型应用无须查询远程数据库,本地数据访问使得它具备更高的吞吐和更低的延迟。而因为按期向远程持久化存储的 checkpoint 工做能够异步、增量式完成,所以对于正常事件处理的影响甚微。事件驱动型应用的优点不只限于本地数据访问。传统分层架构下,一般多个应用会共享同一个数据库,于是任何对数据库自身的更改(例如:由应用更新或服务扩容致使数据布局发生改变)都须要谨慎协调。反观事件驱动型应用,因为只需考虑自身数据,所以在更改数据表示或服务扩容时所需的协调工做将大大减小。

7.1.3 Flink 如何支持事件驱动型应用?

事件驱动型应用会受制于底层流处理系统对时间和状态的把控能力,Flink 诸多优秀特质都是围绕这些方面来设计的。 它提供了一系列丰富的状态操做原语,容许以精确一次的一致性语义合并海量规模(TB 级别)的状态数据。 此外,Flink 还支持事件时间和自由度极高的定制化窗口逻辑,并且它内置的 ProcessFunction 支持细粒度时间控制,方便实现一些高级业务逻辑。 同时,Flink 还拥有一个复琐事件处理(CEP)类库,能够用来检测数据流中的模式。

Flink 中针对事件驱动应用的明星特性当属 savepoint。Savepoint 是一个一致性的状态映像,它能够用来初始化任意状态兼容的应用。在完成一次 savepoint 后,便可放心对应用升级或扩容,还能够启动多个版本的应用来完成 A/B 测试。

典型的事件驱动型应用实例

数据分析应用

什么是数据分析应用?

数据分析任务须要从原始数据中提取有价值的信息和指标。传统的分析方式一般是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了获得最新数据的分析结果,必须先将它们加入分析数据集并从新执行查询或运行应用,随后将结果写入存储系统或生成报告。

借助一些先进的流处理引擎,还能够实时地进行数据分析。和传统模式下读取有限数据集不一样,流式查询或应用会接入实时事件流,并随着事件消费持续产生和更新结果。这些结果数据可能会写入外部数据库系统或之内部状态的形式维护。仪表展现应用能够相应地从外部数据库读取数据或直接查询应用的内部状态。

以下图所示,Apache Flink 同时支持流式及批量分析应用。

[图片上传失败...(image-a51e80-1556549767091)]

流式分析应用的优点?

和批量分析相比,因为流式分析省掉了周期性的数据导入和查询过程,所以从事件中获取指标的延迟更低。不只如此,批量查询必须处理那些由按期导入和输入有界性致使的人工数据边界,而流式查询则无须考虑该问题。

另外一方面,流式分析会简化应用抽象。批量查询的流水线一般由多个独立部件组成,须要周期性地调度提取数据和执行查询。如此复杂的流水线操做起来并不容易,一旦某个组件出错将会影响流水线的后续步骤。而流式分析应用总体运行在 Flink 之类的高端流处理系统之上,涵盖了从数据接入到连续结果计算的全部步骤,所以能够依赖底层引擎提供的故障恢复机制。

Flink 如何支持数据分析类应用?

Flink 为持续流式分析和批量分析都提供了良好的支持。具体而言,它内置了一个符合 ANSI 标准的 SQL 接口,将批、流查询的语义统一块儿来。不管是在记录事件的静态数据集上仍是实时事件流上,相同 SQL 查询都会获得一致的结果。同时 Flink 还支持丰富的用户自定义函数,容许在 SQL 中执行定制化代码。若是还需进一步定制逻辑,能够利用 Flink DataStream API 和 DataSet API 进行更低层次的控制。此外,Flink 的 Gelly 库为基于批量数据集的大规模高性能图分析提供了算法和构建模块支持。

典型的数据分析应用实例

数据管道应用

什么是数据管道?

提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的经常使用方法。ETL 做业一般会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。

数据管道和 ETL 做业的用途类似,均可以转换、丰富数据,并将其从某个存储系统移动到另外一个。但数据管道是以持续流模式运行,而非周期性触发。所以它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。例如:数据管道能够用来监控文件系统目录中的新文件,并将其数据写入事件日志;另外一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。

下图描述了周期性 ETL 做业和持续数据管道的差别。

image

数据管道的优点?

和周期性 ETL 做业相比,持续数据管道能够明显下降将数据移动到目的端的延迟。此外,因为它可以持续消费和发送数据,所以用途更广,支持用例更多。

Flink 如何支持数据管道应用?

不少常见的数据转换和加强操做能够利用 Flink 的 SQL 接口(或 Table API)及用户自定义函数解决。若是数据管道有更高级的需求,能够选择更通用的 DataStream API 来实现。Flink 为多种数据存储系统(如:Kafka、Kinesis、Elasticsearch、JDBC数据库系统等)内置了链接器。同时它还提供了文件系统的连续型数据源及数据汇,可用来监控目录变化和以时间分区的方式写入文件。

典型的数据管道应用实例

X 联系我

  • 公众号

    图片标题

  • Q群

博客

  • 知乎
相关文章
相关标签/搜索