美文网首页
What is Apache Flink - Applicati

What is Apache Flink - Applicati

作者: 耳边的火 | 来源:发表于2018-12-01 20:02 被阅读7次

    原文翻译如下。


    Apache Flink是一个能在有界与无界数据流上进行有状态计算的框架。Flink在不同层次的抽象上提供了相应的API,并且针对常用的使用场景提供了工具库。

    流应用的基础元素

    基于流处理框架来构建与运行什么样的应用,取决于该应用所选择的框架处理 streamstate以及time的能力。下面我们将会描述流处理应用中这三个基础元素,并解释Flink是如何处理这三者的。

    Streams

    很显然,stream是流处理中的基础概念。然而,流的不同的特性决定了一个流能够并且应该如何被处理。Flink是一个多变的处理框架,能够处理任意类型的流。

    • 有界流无界流: 流可以是无界的,也可以是有界的,如一个固定大小的数据集。Flink提供了精妙的能力来处理无界流,同时提供了高效处理有界流的操作符。
    • 实时流记录流:所有数据都可以看作流。有两种方式来处理这些数据。当数据生成时,实时地进行处理;或者将流持久化到存储系统,如文件系统或对象存储等,然后之后再对数据进行处理。Flink对上述两种类型的流都可以进行处理。

    State

    每一个稍微复杂些的流应用都是有状态的,只有那些仅仅对单个事件进行转化的应用不需要状态。任何一个执行基本业务逻辑的应用都需要保存状态或中间计算结果,以便于在稍后的某个时刻,如下一个事件到达时或经过一段特定时间段后,再获取该状态或结果。


    image

    应用状态在Flink中是最重要的数据。Flink提供了处理state的上下文context,你可以在context提供的特性中印证这一点。

    • 多种状态基元:Flink为不同的数据结构提供了相应的状态基元,例如atomic values, lists及maps。开发者可以基于方法的访问模式来选择最高效的状态基元。
    • 可插拔的状态后端:应用状态是由一个可插拔的状态后端在管理与检查。Flink提供了内存存储或RocksDB两种不同的状态后端,RocksDB是一个高效的,嵌入式的磁盘数据存储。Flink也支持自定义的状态后端。
    • 准确且一致的状态:Flink的检查点算法与恢复算法,保证了应用在遇到故障时,仍能维持应用状态的一致性。因此故障处理不会对应用的正确性造成影响。
    • 非常大的状态:得益于Flink的异步且增量的检查点算法,使得Flink有能力维持TB级别的应用状态。
    • 可扩展的应用:Flink支持有状态应用的横向扩展,只需要将状态重新分发给更多或更少的works即可。

    Time

    Time是流应用中另一个重要概念。大多数的事件流都有其固有的时间属性,这是由于每一个事件都是在某个特定时刻产生的。不仅如此,许多常见的流计算都是基于时间的,例如windows aggregations(对在某时间窗口的所有数据执行聚合操作), sessionization(基于会话session的统计), pattern detection(模式检测), and time-based joins(基于时间的流联接)。一个流应用的重要方面便是该应用如何处理时间,处理何种类型的时间,如event-time(事件时间)或者processing-time(处理时间)。
    Flink提供了一系列丰富的与时间相关的特性:

    • Event-time 模式:应用以Event-time模式来处理流,意味着应用是基于事件的时间戳来进行计算。因此,Event-time模式保证了不管是处理实时数据还是记录数据,都能得到准确且一致的结果。
    • 支持 Watermark(水印):Flink提出Watermark的概念是为了在非理想情况下Event-time模式中的时间更具有完备性(后续文章会有详细介绍,大意是指在真实世界中,总会存在某些数据由于网络等原因而无法按照顺序到达,若不等待该迟到数据,则计算结果不准确,Watermark则表明了某时刻之前的所有数据都已到达,可以执行计算,保证了结果的准确性。Watermark的作用在于在允许延迟时间内,等待尽可能多的迟到数据到达,然后再开始计算,尽量保证结果的完整性)。Watermark提供了一个灵活的机制,在延迟与结果完整性之间做出权衡。
    • 迟到数据处理:当使用Event-time模式以及Watermark处理流数据时,有可能出现这样的情况:在计算完成之后,与该计算相关的某些事件才到达,这样的事件(数据)成为迟到的事件(数据)。Flink提供了多种选择来处理迟到数据,例如通过侧输出将该迟到数据重新路由,并更新之前已经计算完成的结果。
    • Processing-time模式:除了提供Event-time模式之外,Flink还提供了Processing-time模式,该模式根据执行计算的机器的执行时间来进行计算。Processing-time模式适合于特定的应用,这类应用对低延迟有极高的要求并且可以接受近似的结果。

    分层的API

    Flink提供了三层API,每一层API在使用的简易性与表达的丰富性之间做了权衡,以适应不同的使用情况。
    [图片上传失败...(image-b7f7e3-1543665726598)]
    我们简要的展示一下每一层API,并且讨论它们的使用,以及给出一个代码示例。

    ProcessFunction

    ProcessFunction是Flink提供的最具有表达力的函数接口。Flink提供该接口来处理一个或两个输入流中的事件或者处理在window中分组后的事件。ProcessFunction提供了对时间和状态的精细控制。一个ProcessFunction可以根据需要修改状态以及注册一个timer,该timer会在设定好的未来某个时刻触发一个回调函数。因此,ProcessFunction可以按照大多数有状态的事件驱动(event-driven)应用的要求,实现针对每个事件的复杂业务逻辑。
    下面的示例展示了 KeyedProcessFunction ,该函数作用在 KeyedStream 上,用来匹配 START 与 END 事件。当一个START事件到达时,该函数会将START事件的时间戳存储在state中,并且注册一个4小时的timer。如果在4小时内,注册的timer未被触发时,END事件就已经到达,该函数会计算END事件与START事件之间的时间差,清除state并且返回结果。否则,则会触发timer的回调函数,清除state内容。

    /**
     * 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 的表现力,但同时也体现出该API有些繁琐。

    DataStream API

    DataStream API针对大多数常见的流处理操作提供了方法,如:根据时间窗口处理数据(windowing),依次记录转化(record-at-a-time transformations),通过查询其他数据源来丰富事件(enriching events by querying an external data store)。DataStream API对Java与Scala都可用,且提供了如 map(), reduce(), 以及 aggregate()等方法。具体的业务逻辑可以通过实现其方法接口或者使用Java/Scala的lambda表达式。
    下面的示例展示了,在鼠标点击事件流中,如何统计每个会话session中的点击数量。

    // 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无缝的结合使用,且提供了对用户定义的标量(user-defined scalar)、聚合和表值函数(table-valued function)的支持。
    Flink提供的关系型API的设计初衷便是使得数据分析,数据清洗以及构建ETL应用更简单。
    下面的示例展示了如何使用SQL 的 API 在鼠标点击事件流中,查询每个会话session中的点击总数。这与上面DataStream API的使用案例是相同的。

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

    工具库

    Flink针对常见的数据处理使用场景提供了几个工具库。这些工具库一般都内置在API中而不会单独存在。因此,它们能够享受到Flink API提供的便利以及可以与其他工具库集成。

    • 复杂事件处理: 在处理事件流时,模式匹配是一个十分常见的场景。Flink的CEP库提供了API来指定需要匹配的时间的模式(类似于正则表达式或者状态机),CEP库与DataStream API进行了集成,因此这些匹配模式是由DataStream API在数据流上进行匹配。能够使用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继承了DataSet API的可伸缩性以及运算符的健壮性。Gelly提供了内置的算法,例如:标签传播(label propagation,) 三角形枚举法(triangle enumeration), 以及网页排名(page rank),同时,Gelly也提供了Graph API可以很容易的实现自定义的图像算法。

    相关文章

      网友评论

          本文标题:What is Apache Flink - Applicati

          本文链接:https://www.haomeiwen.com/subject/lxjlcqtx.html