Flink基础教程-----学习笔记

Flink基础教程

  1. Flink,Apache Flink 是为分布式、高性能、随时可用以及准确的流处理应用程序打造的开源流处理框架。
  2. Flink是如何实现批处理和流处理?Flink 将批处理(即处理有限的静态数据)视作一种特殊的流处理。
  3. Flink技术栈的核心组成部分,如下图:

  1. DataStream API 可以流畅地分析无限数据流,并且可以用Java 或者Scala 来实现。开发人员需要基于一个叫DataStream 的数据结构来开发,这个数据结构用于表示永不停止的分布式数据流。Flink 的分布式特点体现在它能够在成百上千台机器上运行,它将大型的计算任务分成许多小的部分,每个机器执行一个部分。Flink 能够自动地确保在发生机器故障或者其他错误时计算能持续进行,或者在修复bug 或进行版本升级后有计划地再执行一次。这种能力使得开发人员不需要担心失败。Flink 本质上使用容错性数据流,这使得开发人员可以分析持续生成且永远不结束的数据(即流处理)。
  2. 消息传输层和流处理层
    1. 消息传输层从各种数据源(生产者)采集连续事件产生的数据,并传输给订阅了这些数据的应用程序和服务(消费者)
    2. 流处理层有三个用途:
      1. 持续地将数据在应用程序和系统间移动
      2. 聚合并处理事件
      3. 在本地维持应用程序的状态

    1. 流处理框架的消息传输层需要具备哪些功能呢?
      1. 兼具高性能和持久性,消息传输层的一个作用是作为流处理层上游的安全队列——它相当于缓冲区,可以将事件数据作为短期数据保留起来,以防数据处理过程发生中断。具有持久性的好处之一是消息可以重播。正是由于消息传输层和流处理层相互作用,才使得像Flink 这样的系统有了准确处理和“时空穿梭”(指重新处理数据的能力)的保障
      2. 将生产者和消费者解耦,在Kafka 和MapR Streams 这样的消息传输工具中,数据的生产者和消费者(Flink 应用程序也是其中的一种消费者)是解耦的。到达的消息既可以立刻被使用,也可以稍后被使用。消费者从队列中订阅消息,而不是由生产者向所有消费者广播。在消息到达的时候,消费者不必处于运行状态

    1. 支持微服务架构的流数据
      1. 数据流作为中心数据源

    1. 流的跨地域复制,流处理架构并不是玩具:它被用于具有重要使命的系统,这些系统要求流处理层和消息传输层具备一些特性。许多关键的业务系统依靠跨数据中心的一致性,它们不仅需要高效的流处理层,更需要消息传输层拥有可靠的跨地域复制能力。
  1. Flink用途
    1. 不同类型的正确性,在处理数据时,需要解决这几个问题:我需要什么  我期望什么 我在什么时候需要得到结果
      1. 符合产生数据的自然规律,流处理器(尤其是Flink)的正确性体现在计算窗口的定义符合数据产生的自然规律
      2. 事件时间,流处理架构不常采用事件时间,尽管越来越多的人这样做。Flink 能够完美地做到这一点,这在实现计算的正确性上非常有用。为了获得最佳的计算结果,系统需要能够通过数据找到事件发生的时间,而不是只采用处理时间。
      3. 发生故障后仍保持准确,若想使计算保持准确,就必须跟踪计算状态。如果计算框架本身不能做到这一点,就必须由应用程序的开发人员来完成这个任务。连续的流处理很难跟踪计算状态,因为计算过程没有终点。实际上,对状态的更新是持续进行的。Flink 解决了可能影响正确性的几个问题,包括如何在故障发生之后仍能进行有状态的计算。Flink 所用的技术叫作检查点(checkpoint),第5 章会详细介绍它的原理。在每个检查点,系统都会记录中间计算状态,从而在故障发生时准确地重置。这一方法使系统以低开销的方式拥有了容错能力——当一切正常时,检查点机制对系统的影响非常小。值得注意的是,检查点也是Flink 能够按需重新处理数据的关键所在。毕竟,并不是只有在发生故障之后才会重新处理数据。比如,在运行新模型或者修复bug 时,就可能需要重播并重新处理事件流数据。Flink 成全了这些操作。Flink 的检查点特性在流处理器中是独一无二的,它使得Flink 可以准确地维持状态,并且高效地重新处理数据。
      4. 及时给出所需结果,Flink 能够满足低延迟应用程序的需要
      5. 是开发和运维更轻松
    2. 分阶段采用Flink
  2. 对时间的处理,用流处理器编程和用批处理器编程最关键的区别在于对时间的处理。举一个非常简单的例子:计数。事件流数据(如微博内容、点击数据和交易数据)不断产生,我们需要用key 将事件分组,并且每隔一段时间(比如一小时)就针对每一个key 对应的事件计数。这是众所周知的“大数据”应用,与MapReduce 的词频统计例子相似。
    1. 采用批处理架构和lambda架构计数,用定期运行的批处理作业来实现应用程序的持续性。数据被持续地分割为文件(如以一小时为单位);然后,批处理作业将文件作为输入,以此达到持续处理数据的效果。这种架构完全可以,但是存在以下问题。
      1. 太多独立的部分。为了计算数据中的事件数,这种架构动用了太多系统。每一个系统都有学习成本和管理成本,还可能存在bug

      1. 对时间的处理方法不明确。假设需要改为每30分钟计数一次。这个变动涉及工作流调度逻辑(而不是应用程序代码逻辑),从而使DevOps问题与业务需求混淆
      2. 预警,假设除了每小时计数一次外,还需要尽可能早地收到计数预警(比如在事件数超过10 时预警)。为了做到这一点,可以在定期运行的批处理作业之外,引入Storm 来采集消息流(Kafka 或者MapR Streams)。Storm 实时提供近似的计数,批处理作业每小时提供准确的计数。但是这样一来,就向架构增加了一个系统,以及与之相关的新编程模型。上述架构叫作Lambda 架构,如图所示:Lambda 架构用定期运行的批处理作业来实现应用程序的持续性,并通过流处理器获得预警。流处理器实时提供近似结果;批处理层最终会对近似结果予以纠正
        1. 乱序事件流,在现实世界中,大多数事件流都是乱序的,即事件的实际发生顺序(事件数据在生成时被附上时间戳,如智能手机记录下用户登录应用程序的时间)和数据中心所记录的顺序不一样。这意味着本属于前一批的事件可能被错误地归入当前一批。批处理架构很难解决这个问题,大部分人则选择忽视它。
        2. 批处理作业的界限不清晰

    1. 采用流处理框架计数,事件流由消息传输系统提供,并且只被单一的Flink作业处理,从而以小为单位计数和预警(后者可选)。这种方法直接解决了上一节提到的所有问题。Flink 作业的速度减慢或者吞吐量激增只会导致事件在消息传输系统中堆积。以时间为单位把事件流分割为一批批任务(称作窗口),这种逻辑完全嵌入在Flink 程序的应用逻辑中。预警由同一个程序生成,乱序事件由Flink 自行处理。要从以固定时间分组改为根据产生数据的时间段分组,只需在Flink 程序中修改对窗口的定义即可。此外,如果应用程序的代码有过改动,只需重播Kafka 主题,即可重播应用程序。采用流处理架构,可以大幅减少需要学习、管理和编写代码的系统

      1. 流处理区别于批处理最主要的两点是:流即是流,不必人为地将它分割为文件;时间的定义被明确地写入应用程序代码(如以上代码的时间窗口),而不是与摄取、计算和调度等过程牵扯不清
    1. 流处理系统中的批处理,Storm Trident 是这样实现微批处理的:它先创建一个大的Storm 事件,其中包含固定数量的子事件;然后将这些聚合在一起的子事件用持续运行的Storm 拓扑处理。Spark Streaming 的微批处理架构和批处理架构本质上是一致的,只不过对用户隐藏了前两步(摄取和存储),并将每份微批数据用预写日志(而不是文件)的形式存储在内存中。包括Flink 在内的所有现代流处理器在内部都使用了某种形式的微批处理技术,在shuffle 阶段将含有多个事件的缓冲容器通过网络发送,而不是发送单个事件。这些形式各不相同。
      1. 需要说明的是,流处理系统中的批处理必须符合以下两点要求。
        1. 批处理只作为提高系统性能的机制。批量越大,系统的吞吐量就越大
        2. 为了提高性能而使用的批处理必须完全独立于定义窗口时所用的缓冲,或者为了保证容错性而提交的代码,也不能作为API 的一部分。否则,系统将受到限制,并且变得脆弱且难以使用
      2. 应用程序开发人员和数据处理系统的用户不需要考虑系统是否可以执行微批处理以及如何执行,而是需要考虑系统是否可以处理乱序事件流以及不一致的窗口,是否可以在提供准确的聚合结果之外还提供预警,以及是否可以准确地重播历史数据;还需要考虑系统的性能特征(低延迟和高吞吐),以及如何在发生故障时保证系统持续运行。
    2. 时间概念
      1. 事件时间:,即事件实际发生的时间。更准确地说,每一个事件都有一个与它相关的时间戳,并且时间戳是数据记录的一部分(比如手机或者服务器的记录)。事件时间其实就是时间戳。
      2. 处理时间:即事件被处理的时间。处理时间其实就是处理事件的机器所测量的时间。
      3. 通常还有第3 个时间概念,即摄取时间,也叫作进入时间。它指的是事件进入流处理框架的时间。缺乏真实事件时间的数据会被流处理器附上时间戳,即流处理器第一次看到它的时间(这个操作由source 函数完成,它是程序的第一个处理节点
    3. 窗口,是一种机制,它用于将许多事件按照时间或者其他特征分组,从而将每一组作为整体进行分析(比如求和)。
      1. 时间窗口,是最简单和最有用的一种窗口。它支持滚动和滑动
      2. 计数窗口,Flink 支持的另一种常见窗口叫作计数窗口。采用计数窗口时,分组依据不再是时间戳,而是元素的数量
      3. 会话窗口,会话指的是活动阶段,其前后都是非活动阶段,例如用户与网站进行一系列交互(活动阶段)之后,关闭浏览器或者不再交互(非活动阶段)。会话需要有自己的处理机制,因为它们通常没有固定的持续时间(有些30 秒就结束了,有些则长达一小时),或者没有固定的交互次数(有些可能是3 次点击后购买,另一些可能是40 次点击却没有购买)。在Flink 中,会话窗口由超时时间设定,即希望等待多久才认为会话已经结束
      4. 触发器,Flink 还提供触发机制。触发器控制生成结果的时间,即何时聚合窗口内容并将结果返回给用户。每一个默认窗口都有一个触发器。例如,采用事件时间的时间窗口将在收到水印时被触发。对于用户来说,除了收到水印时生成完整、准确的结果之外,也可以实现自定义的触发器(例如每秒提供一次近似结果)。
      5. 窗口的实现,在Flink 内部,所有类型的窗口都由同一种机制实现。虽然实现细节对于普通用户来说并不重要,但是仍然需要注意以下两点。
        1. 开窗机制与检查点机制完全分离。这意味着窗口时长不依赖于检查点间隔。事实上,窗口完全可以没有“时长”(比如上文中的计数窗口和会话窗口的例子)。
        2. 高级用户可以直接用基本的开窗机制定义更复杂的窗口形式(如某种时间窗口,它可以基于计数结果或某一条记录的值生成中间结果)
    4. 时空穿梭,时空穿梭意味着将数据流倒回至过去的某个时间,重新启动处理程序,直到处理至当前时间为止。像Kafka 和MapR Streams 这样的现代传输层,支持时空穿梭,这使得它们与更早的解决方案有所区别。实时流处理总是在处理最近的数据(即图中“当前时间”的数据),历史流处理则从过去开始,并且可以一直处理至当前时间。
      1. 流处理架构拥有时空穿梭(即重新处理数据)的能力。流处理器支持事件时间,这意味着将数据流“倒带”,用同一组数据重新运行同样的程序,会得到相同的结果

    1. 水印,支持事件时间对于流处理架构而言至关重要,因为事件时间能保证结果正确,并使流处理架构拥有重新处理数据的能力。当计算基于事件时间时,如何判断所有事件是否都到达,以及何时计算和输出窗口的结果呢?换言之,如何追踪事件时间,并知晓输入数据已经流到某个事件时间了呢?为了追踪事件时间,需要依靠由数据驱动的时钟,而不是系统时钟。
      1. 以图4-5 中的一分钟滚动窗口为例。假设第一个窗口从10:00:00 开始(即从10 时0 分0 秒开始),需要计算从10:00:00 到10:01:00 的数值总和。当时间就是记录的一部分时,我们怎么知道10:01:00 已到呢?换句话说,我们怎么知道盖有时间戳10:00:59 的元素还没到呢?Flink 通过水印来推进事件时间。水印是嵌在流中的常规记录,计算程序通过水印获知某个时间点已到。对于上述一分钟滚动窗口,假设水印标记时间为10:01:00(或者其他时间,如10:03:43),那么收到水印的窗口就知道不会再有早于该时间的记录出现,因为所有时间戳小于或等于该时间的事件都已经到达。这时,窗口可以安全地计算并给出结果(总和)。水印使事件时间与处理时间完全无关。迟到的水印(“迟到”是从处理时间的角度而言)并不会影响结果的正确性,而只会影响收到结果的速度。
      2. 水印是如何生存的,在Flink 中,水印由应用程序开发人员生成,这通常需要对相应的领域有一定的了解。完美的水印永远不会错:时间戳小于水印标记时间的事件不会再出现。在特殊情况下(例如非乱序事件流),最近一次事件的时间戳就可能是完美的水印。启发式水印则相反,它只估计时间,因此有可能出错,即迟到的事件(其时间戳小于水印标记时间)晚于水印出现。针对启发式水印,Flink 提供了处理迟到元素的机制。
      3. 水印为以事件时间说明输入数据的完整性提供了一种机制,这种机制可能是启发式的。
    2. 为什么Flink 对事件时间的支持很重要呢?
      1. 有助于准确地识别异常。时间对识别异常很重要。当很多日志事件在同一时间出现时,通常说明可能有错误发生,为了将这些事件正确地分组和归类,考虑他们的真实时间(而不是处理时间)很重要
      2. 有助于采用流处理架构。在流处理架构中,所有的计算都由流处理器完成。升级应用程序的做法是将它们在流处理器中再次执行。用同一种计算运行两次同样的数据,必须得到同样的结果,这只有依靠时间事件操作才能实现
  1. 有状态的计算,流式计算分为无状态和有状态两种情况。无状态计算观察每个独立事件,并根据最后一个事件输出结果。有状态的计算则会基于多个事件输出结果
    1. 第4 章讨论的所有类型的窗口。例如,计算过去一小时的平均温度,就是有状态的计算。
    2. 所有用于复杂事件处理的状态机。例如,若在一分钟内收到两个相差20度以上的温度读数,则发出警告,这是有状态的计算。
    3. 流与流之间的所有关联操作,以及流与静态表或动态表之间的关联操作,都是有状态的计算。
    4. 无状态流处理和有状态流处理的区别,如下图:

    1. 一致性,在流处理中,一致性分为3 个级别:
      1. at-most-once:这其实是没有正确性保障的委婉说法——故障发生之后,计数结果可能丢失。
      2. at-least-once:这表示计数结果可能大于正确值,但绝不会小于正确值。也就是说,计数程序在发生故障后可能多算,但是绝不会少算。
      3. exactly-once:这指的是系统保证在发生故障后得到的计数结果与正确值一致。
      4. at-least-once 非常流行。第一代流处理器(如Storm 和Samza)刚问世时只保证at-least-once,原因有二
        1. 保证exactly-once 的系统实现起来更复杂。这在基础架构层(决定什么代表正确,以及exactly-once 的范围是什么)和实现层都很有挑战性。
        2. 流处理系统的早期用户愿意接受框架的局限性,并在应用层想办法弥补(例如使应用程序具有幂等性,或者用批量计算层再做一遍计算)。
      5. Flink 的一个重大价值在于,它既保证了exactly-once,也具有低延迟和高吞吐的处理能力。
      6. Flink 如何保证exactly-once 呢?它使用一种被称为“检查点”的特性,在出现故障时将系统重置回正确状态。检查点是Flink 最有价值的创新之一,因为它使Flink 可以保证exactly-once,并且不需要牺牲性能。当Flink数据源(在本例中与keyBy算子内联)遇到检查点屏障时,它会将其在输入流中的位置保存到稳定存储中。这让flink可以根据该位置重启输入,检查点屏障像普通记录一样在算子之间流动。当map算子处理完前三条记录并收到检查点屏障时,它们会将状态以异步的方式写入稳定存储,如图:

      1. 位于检查点之前的所有记录([“b”,2]、[“b”,3]、[“c”,1])被map算子处理之后的情况。此时,稳定存储已经备份了检查点屏障在输入流中的位置(备份操作发生在检查点屏障被输入算子处理的时候)。Map算子接着开始处理检查点屏障,并触发将状态异步备份到稳定存储中这个动作。如下图。
      2. 当map算子的状态备份和检查点屏障的位置备份被确认之后,该检查点操作就可以被标记为完成。如图5-6 所示。我们在无须停止或者阻断计算的条件下,在一个逻辑时间点(对应检查点屏障在输入流中的位置)为计算状态拍了快照。通过确保备份的状态和位置指向同一个逻辑时间点,后文将解释如何基于备份恢复计算,从而保证exactly-once。值得注意的是,当没有出现故障时,Flink 检查点的开销极小,检查点操作的速度由稳定存储的可用带宽决定。回顾数珠子的例子:除了因为数错而需要用到皮筋之外,皮筋会被很快地拨过。(Flink 的开发团队正在研究如何只保存状态的变化,而不保存状态的值,这样做可以让开销变得更小。)。
        1. 检查点操作完成,状态和位置均已备份到稳定存储中。输入流中的所有记录都已处理完成。值得注意的是,备份的状态值与实际的状态值是不同的。备份反映的是检查点的状态

        1. 如果检查点操作失败,Flink 会丢弃该检查点并继续正常执行,因为之后的某一个检查点可能会成功。虽然恢复时间可能更长,但是对于状态的保证依旧很有力。只有在一系列连续的检查点操作失败之后,Flink 才会抛出错误,因为这通常预示着发生了严重且持久的错误。如下图。
        2. 在这种情况下,Flink 会重新拓扑(可能会获取新的执行资源),将输入流倒回到上一个检查点,然后恢复状态值并从该处开始继续计算。在本例中,["a",2]、["a",2] 和["c",2] 这几条记录将被重播。图5-8 展示了这一重新处理过程。从上一个检查点开始重新计算,可以保证在剩下的记录被处理之后,得到的map 算子的状态值与没有发生故障时的状态值一致。值得注意的是,输出流会含有重复的数据。具体来说,["a",2]、["a",4] 和["c",3] 会出现两次。如果Flink 将输出流写入特殊的输出系统(比如文件系统或者数据库),那么就可以避免这个问题。Flink 将输入流倒回到上一个检查点屏障的位置,同时恢复map 算子的状态值。然后,Flink 从此处开始重新处理。这样做保证了在记录被处理之后,map 算子的状态值与没有发生故障时的一致

        1. Flink 检查点算法的正式名称是异步屏障快照(asynchronous barrier snapshotting)。该算法大致基于Chandy-Lamport 分布式快照算法。
    1. 保存点:状态版本控制。
      1. 检查点由Flink 自动生成,用来在故障发生时重新处理记录,从而修正状态。Flink 用户还可以通过另一个特性有意识地管理状态版本,这个特性叫作保存点(savepoint)。保存点与检查点的工作方式完全相同,只不过它由用户通过Flink 命令行工具或者Web 控制台手动触发,而不由Flink 自动触发。和检查点一样,保存点也被保存在稳定存储中。用户可以从保存点重启作业,而不用从头开始。保存点可以被视为作业在某一个特定时间点的快照(该时间点即为保存点被触发的时间点)。对保存点的另一种理解是,它在明确的时间点保存应用程序状态的版本。这和用版本控制系统保存应用程序的版本很相似。最简单的例子是在不修改应用程序代码的情况下,每隔固定的时间拍快照,即照原样保存应用程序状态的版本,如图5-9 所示:手动触发的保存点(以圆圈表示)在不同时间捕获正在运行的Flink 应用程序的状态

      1. 在图中,v.0 是某应用程序的一个正在运行的版本。我们分别在t1 时刻和t2时刻触发了保存点。因此,可以在任何时候返回到这两个时间点,并且重启程序。更重要的是,可以从保存点启动被修改过的程序版本。举例来说,可以修改应用程序的代码(假设称新版本为v.1),然后从t1 时刻开始运行改动过的代码。这样一来,v.0 和v.1 这两个版本同时运行,并在之后的时间里获取各自的保存点,如图5-10 所示。使用保存点更新Flink 应用程序的版本。新版本可以从旧版本生成的一个保存点处开始执行

      1. 保存点可用于应对流处理作业在生产环境中遇到的许多挑战。
        1. 应用程序代码升级:假设你在已经处于运行状态的应用程序中发现了一个bug,并且希望之后的事件都可以用修复后的新版本来处理。通过触发保存点并从该保存点处运行新版本,下游的应用程序并不会察觉到不同(当然,被更新的部分除外)。
        2. Flink 版本更新:Flink 自身的更新也变得简单,因为可以针对正在运行的任务触发保存点,并从保存点处用新版本的Flink 重启任务。
        3. 维护和迁移:使用保存点,可以轻松地“暂停和恢复”应用程序。这对于集群维护以及向新集群迁移的作业来说尤其有用。此外,它还有利于开发、测试和调试,因为不需要重播整个事件流。
        4. 假设模拟与恢复:在可控的点上运行其他的应用逻辑,以模拟假设的场景,这样做在很多时候非常有用。
        5. A/B 测试:从同一个保存点开始,并行地运行应用程序的两个版本,有助于进行A/B 测试。
    1. 端到端的一致性和作为数据库的流处理器
      1. 在该应用程序架构中,有状态的Flink 应用程序消费来自消息队列的数据,然后将数据写入输出系统,以供查询。底部的详情图展示了Flink 应用程序的内部情况

      1. 输入数据来自一个分区存储系统(如kafka或者mapR Streams)。图5-11 底部的详情图展示了Flink 拓扑,其中包含3 个算子。source 读取输入数据,根据key 分区,并将数据路由到有状态的算子实例(这既可以是5.2 节提到的map 算子,也可以是窗口聚合算子)。有状态的算子将状态内容(比如前例中的计数结果)或者一些衍生结果写入sink,再由sink 将结果传送到输出存储系统中(例如文件系统或数据库)。接着,查询服务(比如数据库查询API)就可以允许用户对状态进行查询(最简单的例子就是查询计数结果),因为状态已经被写入输出存储系统了。
      2. 在将状态内容传送到输出存储系统的过程中,如何保证exactly-once 呢?这叫作端到端的一致性。本质上有两种实现方法,用哪一种方法则取决于输出存储系统的类型,以及应用程序的需求。
        1. 第一[v1] 种方法是在sink 环节缓冲所有输出,并在sink 收到检查点记录时,将输出“原子提交”到存储系统。这种方法保证输出存储系统中只存在有一致性保障的结果,并且不会出现重复的数据。从本质上说,输出存储系统会参与Flink 的检查点操作。要做到这一点,输出存储系统需要具备“原子提交”的能力。
        2. 第二种方法是急切地将数据写入输出存储系统,同时牢记这些数据可能是“脏”的,而且需要在发生故障时重新处理。如果发生故障,就需要将输出、输入和Flink 作业全部回滚,从而将“脏”数据覆盖,并将已经写入输出的“脏”数据删除。注意,在很多情况下,其实并没有发生删除操作。例如,如果新记录只是覆盖旧纪录(而不是添加到输出中),那么“脏”数据只在检查点之间短暂存在,并且最终会被修正过的新数据覆盖
        3. 这两种方法恰好对应关系数据库系统中的两种为人所熟知的事务隔离级别:已提交读和未提交读。已提交读保证所有读取(查询输出)都只读取已提交的数据,而不会读取中间、传输中或脏的数据。之后的读取可能会返回不同的结果,因为数据可能已被改变。未提交读则允许读取脏数据;换句话说,查询总是看到被处理过的最新版的数据
        4. 利用Flink的可查询状态特性可以简化应用程序架构。对于状态本身就是所需信息的查询来说,直接查询状态可以提升性能。如下图所示:

  1. 批处理:一种特殊的流处理
    1. 无线流处理:输入数据没有尽头;流处理从当前或过去的某一个时间点开始,持续不停地进行
    2. 有限流处理,即从某一个时间点开始处理数据,然后在另一个时间点结束。有限流处理是无限流处理的一种特殊情况,它只不过在某个时间点停止而已。此外,如果计算结果不在执行过程中连续生成,而仅在末尾处生成一次,那就是批处理(分批处理数据)。
    3. 批处理是流处理的一种非常特殊的情况。在流处理中,我们为数据定义滑动窗口或滚动窗口,并且在每次窗口滑动或滚动时生成结果。批处理则不同,我们定义一个全局窗口,所有的记录都属于同一个窗口。
    4. Flink通过一个底层引擎同时支持流处理和批处理
      1. 在流处理引擎之上,Flink有以下机制:
        1. 检查点机制和状态机制:用于实现容错、有状态的处理
        2. 水印机制:用于实现事件时钟
        3. 窗口和触发器:用于限制计算范围,并定义呈现结果的时间
      2. 用于实现高效的批处理机制:
        1. 用于调度和恢复的回溯法
        2. 用于散列和排序的特殊内存数据结构:可以在需要时,将一部分数据从内存溢出到硬盘上
        3. 优化器:尽可能地缩短生成结果的时间

第一章 整体介绍 2 1.1 什么是 Table API 和 Flink SQL 2 1.2 需要引入的依赖 2 1.3 两种 planner(old & blink)的区别 4 第二章 API 调用 5 2.1 基本程序结构 5 2.2 创建表环境 5 2.3 在 Catalog 中注册表 7 2.3.1 表(Table)的概念 7 2.3.2 连接到文件系统(Csv 格式) 7 2.3.3 连接到 Kafka 8 2.4 表的查询 9 2.4.1 Table API 的调用 9 2.4.2 SQL 查询 10 2.5 将 DataStream 转换成表 11 2.5.1 代码表达 11 2.5.2 数据类型与 Table schema 的对应 12 2.6. 创建临时视图(Temporary View) 12 2.7. 输出表 14 2.7.1 输出到文件 14 2.7.2 更新模式(Update Mode) 15 2.7.3 输出到 Kafka 16 2.7.4 输出到 ElasticSearch 16 2.7.5 输出到 MySql 17 2.8 将表转换成 DataStream 18 2.9 Query 的解释和执行 20 1. 优化查询计划 20 2. 解释成 DataStream 或者 DataSet 程序 20 第三章 流处理中的特殊概念 20 3.1 流处理和关系代数(表,及 SQL)的区别 21 3.2 动态表(Dynamic Tables) 21 3.3 流式持续查询的过程 21 3.3.1 将流转换成表(Table) 22 3.3.2 持续查询(Continuous Query) 23 3.3.3 将动态表转换成流 23 3.4 时间特性 25 3.4.1 处理时间(Processing Time) 25 3.4.2 事件时间(Event Time) 27 第四章 窗口(Windows) 30 4.1 分组窗口(Group Windows) 30 4.1.1 滚动窗口 31 4.1.2 滑动窗口 32 4.1.3 会话窗口 32 4.2 Over Windows 33 1) 无界的 over window 33 2) 有界的 over window 34 4.3 SQL 中窗口的定义 34 4.3.1 Group Windows 34 4.3.2 Over Windows 35 4.4 代码练习(以分组滚动窗口为例) 36 第五章 函数(Functions) 38 5.1 系统内置函数 38 5.2 UDF 40 5.2.1 注册用户自定义函数 UDF 40 5.2.2 标量函数(Scalar Functions) 40 5.2.3 表函数(Table Functions) 42 5.2.4 聚合函数(Aggregate Functions) 45 5.2.5 表聚合函数(Table Aggregate Functions) 47
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页