流式计算的演进与Flink流式计算的特点

1 流处理的演变

      (1)传统数据处理架构
在这里插入图片描述

图1 传统事务处理架构(OLTP)
      在传统事务处理架构中,主要面向的对象是业务系统。首先,事件触发每个业务应用;然后,业务应用读写远程事务型数据库;最后,业务应用计算结果并做出响应。需要注意的是:事务处理架构并不适用于大规模数据场景。

在这里插入图片描述

图2 传统分析处理架构(OLAP)

      为了适用于大规模数据场景,采用ETL方式将传统事务性数据库管理系统的数据复制到数仓中,再进行分析和查询。需要注意的是:该架构下的离线数仓应用不适用于实时数据场景。
      (2)第一代流处理(代表有Storm)

在这里插入图片描述

图3 有状态的流式处理架构

      为了能更好地实时处理大规模数据,提出了有状态的流式处理架构。在该架构中,每来一条数据就会进行处理,并将处理结果存在Local State中,为了数据的安全性,将Local State中的数据进行周期性checkpoint。需要注意的是:该架构并不适用于高并发场景和分布式场景,但时延低。高并发场景下数据的无序性和分布式场景下数据的不一致性会导致数据处理的不准确。
      (3)微批次流处理(代表有Spark)
      为了提高并发场景下,数据处理的准确性,提出了微批次流处理。这里以Spark Streaming微批次流处理架构为例进行说明,如图:

在这里插入图片描述

图4 Spark Streaming的微批次处理架构

      在微批次处理模型中,每隔一段时间进行数据处理。因此,在一定程度上,缓解了数据的无序性问题,从而保证了数据计算的准确性。需要注意的是:该架构在实时性方面有时不能满足用户需求。
      (4)lambda架构
      为了满足实时性要求,将第一代流处理架构(延迟低,不适用于高并发和分布式场景)和微批次流处理架构(适用于高并发场景,延迟较高)结合,提出了lambda架构,如图:

在这里插入图片描述

图5 lambda架构

      需要注意的是:该架构需要同时维护两个不同的系统,维护成本极大。例如:若一个系统的逻辑发生改变,而另一个系统未进行同步改变,则很容易出现两个系统处理不一致的问题。
      (5)事件驱动流处理(代表有Flink)
      为进一步满足用户需求,事件驱动型流处理架构被提出。事件驱动型应用是一类具有状态的应用,它是从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其它外部动作,如图:

在这里插入图片描述

图6 事件驱动型流处理

      事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。
      以Flink为例,阐述如下:有状态的 Flink 程序针对本地状态访问进行了优化。任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中。任务通过访问本地(通常在内存中)状态来进行所有的计算,从而产生非常低的处理延迟。Flink 通过定期和异步地对本地状态进行持久化存储来保证故障场景下精确一次的状态一致性。
在这里插入图片描述

图7 Flink内存计算

      通过以上说明,可以对流处理的演变进行总结,如图:

在这里插入图片描述

图8 流处理的演变

2 流处理应用的基本组件

      可以由流处理框架构建和执行的应用程序类型是由框架对 流、状态、时间 的支持程度来决定的。

2.1 流

      显而易见,(数据)流是流处理的基本要素。然而,流也拥有着多种特征。这些特征决定了流如何以及何时被处理。Flink是一个能够处理任何类型数据流的强大处理框架。
      有界和无界的数据流:流可以是无界的;也可以是有界的,例如固定大小的数据集。Flink 在无界的数据流处理上拥有诸多功能强大的特性,同时也针对有界的数据流开发了专用的高效算子。
      实时和历史记录的数据流:所有的数据都是以流的方式产生,但用户通常会使用两种截然不同的方法处理数据。或是在数据生成时进行实时的处理;亦或是先将数据流持久化到存储系统中——例如文件系统或对象存储,然后再进行批处理。Flink的应用能够同时支持处理实时以及历史记录数据流。

2.2 状态

      只有在每一个单独的事件上进行转换操作的应用才不需要状态,换言之,每一个具有一定复杂度的流处理应用都是有状态的。任何运行基本业务逻辑的流处理应用都需要在一定时间内存储所接收的事件或中间结果,以供后续的某个时间点(例如收到下一个事件或者经过一段特定时间)进行访问并进行后续处理。
在这里插入图片描述

图9 流处理中的状态

      应用状态是Flink中的一等公民,Flink提供了许多状态管理相关的特性支持,其中包括:
      多种状态基础类型:Flink 为多种不同的数据结构提供了相对应的状态基础类型,例如原子值(value),列表(list)以及映射(map)。开发者可以基于处理函数对状态的访问方式,选择最高效、最适合的状态基础类型。
      插件化的State Backend:State Backend负责管理应用程序状态,并在需要的时候进行 checkpoint。Flink支持多种state backend,可以将状态存在内存或者 RocksDB。RocksDB是一种高效的嵌入式、持久化键值存储引擎。Flink 也支持插件式的自定义state backend进行状态存储。
      精确一次语义:Flink的checkpoint和故障恢复算法保证了故障发生后应用状态的一致性。因此,Flink 能够在应用程序发生故障时,对应用程序透明,不造成正确性的影响。
      超大数据量状态:Flink能够利用其异步以及增量式的checkpoint算法,存储数TB级别的应用状态。
      可弹性伸缩的应用:Flink能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。

2.3 时间

      时间是流处理应用另一个重要的组成部分。因为事件总是在特定时间点发生,所以大多数的事件流都拥有事件本身所固有的时间语义。进一步而言,许多常见的流计算都基于时间语义,例如窗口聚合、会话计算、模式检测和基于时间的join。流处理的一个重要方面是应用程序如何衡量时间,即区分事件时间(event-time)和处理时间(processing-time)。
      Flink 提供了丰富的时间语义支持。
      事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。
      Watermark支持:Flink引入了watermark的概念,用以衡量事件时间进展。Watermark 也是一种平衡处理延时和完整性的灵活机制。
      迟到数据处理:当以带有watermark的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink提供了多种处理迟到数据的选项,例如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。
      处理时间模式:除了事件时间模式,Flink还支持处理时间语义。处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。

3 分层API

      Flink 根据抽象程度分层,提供了三种不同的 API。每一种 API 在简洁性和表达力上有着不同的侧重,并且针对不同的应用场景。

在这里插入图片描述

图10 分层API

      (1)ProcessFunction
      ProcessFunction是Flink所提供的最具表达力的接口。ProcessFunction可以处理一或两条输入数据流中的单个事件或者归入一个特定窗口内的多个事件。它提供了对于时间和状态的细粒度控制。开发者可以在其中任意地修改状态,也能够注册定时器用以在未来的某一时刻触发回调函数。因此,你可以利用ProcessFunction实现许多有状态的事件驱动应用所需要的基于单个事件的复杂业务逻辑。
      (2)DataStream API
      DataStream API为许多通用的流处理操作提供了处理原语。这些操作包括窗口、逐条记录的转换操作,在处理事件时进行外部数据库查询等。DataStream API支持 Java和 Scala 语言,预先定义了例如map()、reduce()、aggregate()等函数。你可以通过扩展实现预定义接口或使用Java、Scala的lambda表达式实现自定义的函数。
      (3)SQL & Table API
      Flink 支持两种关系型的 API,Table API 和 SQL。这两个 API 都是批处理和流处理统一的API,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型API会以相同的语义执行查询,并产生相同的结果。Table API和SQL借助了Apache Calcite来进行查询的解析,校验以及优化。它们可以与DataStream和DataSet API无缝集成,并支持用户自定义的标量函数,聚合函数以及表值函数。

4 库

      Flink 具有数个适用于常见数据处理应用场景的扩展库。这些库通常嵌入在 API 中,且并不完全独立于其它 API。它们也因此可以受益于 API 的所有特性,并与其他库集成。
      复杂事件处理(CEP):模式检测是事件流处理中的一个非常常见的用例。Flink的CEP 库提供了API,使用户能够以例如正则表达式或状态机的方式指定事件模式。CEP库与Flink 的DataStream API集成,以便在DataStream上评估模式。CEP库的应用包括网络入侵检测,业务流程监控和欺诈检测。
      DataSet API:DataSet API是Flink用于批处理应用程序的核心API。DataSet API所提供的基础算子包括map、reduce、(outer) join、co-group、iterate等。所有算子都有相应的算法和数据结构支持,对内存中的序列化数据进行操作。如果数据大小超过预留内存,则过量数据将存储到磁盘。Flink的DataSet API的数据处理算法借鉴了传统数据库算法的实现,例如混合散列连接(hybrid hash-join)和外部归并排序(external merge-sort)。
      Gelly: Gelly是一个可扩展的图形处理和分析库。Gelly是在DataSet API之上实现的,并与DataSet API集成。因此,它能够受益于其可扩展且健壮的操作符。Gelly提供了内置算法,如label propagation、triangle enumeration和page rank算法,也提供了一个简化自定义图算法实现的Graph API。

5 Spark vs Flink

      (1)流与微批
      批处理的特点是有界、持久、大量,非常适合需要访问全套记录才能完成的计算工作,一般用于离线统计。
      流处理的特点是无界、实时,无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作,一般用于实时统计。
      在Spark的世界观中,一切都是由批次组成的,离线数据是一个大批次,而实时数据是由一个一个无限的小批次组成的。
      而在Flink的世界观中,一切都是由流组成的,离线数据是有界限的流,实时数据是一个无界限的流,这就是所谓额有界流和无界流。
      无界流:有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
      有界流:有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理。

在这里插入图片描述

图11 有界流与无界流

      这种以流为世界观的架构,获得的最大好处就是具有极低的延迟。
      (2)数据模型
      Spark采用RDD模型,Spark Streaming的DStream实际上也就是一组小批数据RDD的集合。
      Flink基本数据模型是数据流,以及事件(Event)序列。
      (3)运行时架构
      Spark是批计算模式,将DAG划分为不同的Stage,一个Stage完成后才可以计算下一个Stage。
      Flink是标准的流执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理。

6 Flink应用场景

      Flink的应用场景主要分为三部分:事件驱动型应用、数据分析应用和数据管道应用。具体内容这里不再赘述,详见官网

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值