Apache Flink 简述

Apache Flink 简述

Introduction to Apache Flink一书的读书笔记

Stateful computations over streams


什么是流

流,分为有限数据流与无限数据流,unbounded stream是有始无终的数据流,即无限数据流;而 bounded stream 是限定大小的有始有终的数据集合,即有限数据流,二者的区别在于无限数据流的数据会随时间的推演而持续增加,计算持续进行且不存在结束的状态,相对的有限数据流数据大小固定,计算最终会完成并处于结束的状态。

目前开源大数据计算引擎有很多选择,流计算如 Storm、Samza、Flink、Kafka Stream 等,批处理如 Spark、Hive、Pig、Flink 等。而同时支持流处理和批处理的计算引擎,只有两种选择:一个是 Apache Spark, 一个是 Apache Flink。从技术,生态等各方面的综合考虑,首先,Spark 的技术理念是基于批来模拟流的计算。而 Flink 则完全相反,它采用的是基于流计算来模拟批计算。

Flink技术栈



左侧是Flink的技术栈的组成部分,最为核心的是Flink Runtime,它解析用户的流式处理代码,并能够以容错的方式执行在一个或者多个节点上。在Runtime之上构建了易用的专为批处理开发的DataSet API以及流处理DataStream API,这两个API独立,暂时不能混合使用。在这之上是更高级的不同应用,如复杂事件处理API, 机器学习API等。

流式处理应用通常由以下两部分组成: 


消息传输层(message transport)用来传输从不同消息来源收集到的事件(event),并且提供消息订阅服务。消息的来源可以是应用中的埋点,用户的点击,数据库的更新等;消息传输层通常会持久化消息因此可以进行消息重放(replay),不同订阅者可以订阅相同的消息队列,这些订阅者收到不同的消息。比较流行的有Kafka和MapR。

消息处理器: 用来订阅并处理消息,通常要求低延迟高吞吐,并且对一致性(consistency)有一定要求,通常在流式处理中有以下3种一致性语义:

至多一次(at most once): 消息至多被处理一次,在出现失败(failures)的情况下,消息可能被丢失。比如在计数的情况下,计数可能会偏低。

至少一次(at least once): 消息至少被处理一次,在出现失败的情况下,消息可能被重复处理。比如在计数的情况下,计数可能会偏高。

正好一次(exactly once):消息正好被处理一次, 这种语义保证在出现失败的情况下的处理结果和没有失败情况下的结果一致,也就是说计数始终正确。在流处理语境下,实际上正好一次的语义是从结果上来看的,消息正好处理了一次,实际上考虑在错误恢复下消息实际上可能会被处理多次。

在exactly once出现之前,往往采用at least once,不允许消息丢失但允许消息重复,因为我们可以构建幂等系统或者使用批处理方式来重新处理数据方式解决。Flink通过Checkpoint机制高效地提供了exactly once的处理语义。

我们可以通过模块间添加数据流的方式很容易地拓展这种架构,因此也很适合微服务,不同模块通过流来传递数据并使用Flink处理。

为什么要流处理

我们举一个计数的例子,假设我们从站点收集了用户的点击,转发,评论等行为数据,需要统计每隔一段时间(比如1小时)不同行为的次数。采用传统方式如左下图所示: 


利用类似Flume的工具,收集传输并将一段时间内的数据写入到文件中,比如HDFS文件,然后有个调度工具,间隔地调度批处理任务,如MapReduce,分析和计算文件内的数据,最终将结果写人到存储系统中,供外界查询;批处理有T+1的时间延迟,当前小时的结果只能在下一个小时才能获得,因此会额外增加实时处理组件,来处理当前时间段内的数据,查询服务将批处理和流处理结果聚合,提供最新的数据。

上述的架构是传统的Lambda架构,如下图所示 


All data entering the system is dispatched to both the batch layer and the speed layer for processing.

The batch layer has two functions:

Manage the master dataset, an immutable, append-only set of raw data.

Pre-compute the batch views.

The serving layer indexes the batch views so that they can be queried in low-latency, ad-hoc way.

The speed layer compensates for the high latency of updates to the serving layer and deals with recent data only, providing real-time views.

Any incoming query can be answered by merging results from batch views and real-time views

上述架构有以下几个缺点:

这种方式混合了多种系统,批处理和流处理需要使用不用的API书写相同的业务逻辑,且不同系统间需要同步,因而容易出错,不易维护,比如我们需要修改时间间隔,数据收集及任务调度都需要修改。

无序事件(out-of-order events)不能正常处理。比如在1:59:00产生的事件,如果存在网络延迟或者系统延迟,事件在2:00:01才到达,那么这个事件处理就会被归到2点的时间段内,计算产生不正确的结果。

没有一套完善的出错处理及故障快速恢复的机制,此外整个系统不能保证exactly-once处理语义以及事件的划分方式不灵活。

Flink解决了以上问题,使用Flink架构将大大简化: Flink接收并处理消息并将结果写入到存储系统中,右侧是代码示意图。 


核心概念

Time

在流处理中,有以下几种时间概念:

事件时间(event time):指真实事件发生的时间,通常为时间戳,由业务端收集并作为消息的一部分。

处理时间(processing time): 流处理系统内部时间,通常是系统处理消息时的时间。

收集时间(ingestion time):指的是消息进入到流处理系统中的时间。

通常我们关注时间时间和处理时间,在真实环境下,处理时间并不等于事件时间,并且事件并不一定会按照事件时间有序的到来,如下图所示 


由于网络或者系统的原因,事件进入到流处理器中可能是乱序的(out-of-order), 对于很多应用来说,基于事件时间尤为重要,比如金融里面欺诈分析,异常日志分析等。

Windows

窗口(windows)是一种将事件按照时间(Time)或者其他特性进行分组,然后对窗口中的数据进行分析计算的机制,Flink支持以下几种窗口

时间窗口(Time Windows)是根据时间将数据流进行分组的,可以是tumbling或者sliding windows, 比如统计一分钟内数据的和如下所示


计数窗口(Count Windows)是根据元素个数对数据流进行分组的,比如定义为4的窗口,流处理器在接收到4个消息后进行处理,基于时间的窗口总是可以被关闭的,等到时间一过,窗口就收集好了数据,但是基于元素个数的窗口可能永远也关闭不了,比如定义了100,但实际上只有90个事件,Flink提供了基于超时的触发器机制。

会话窗口(Session Windows) 当我们需要分析用户的一段交互的行为事件时,通常的想法是将用户的事件流按照session来分组。session是指一段持续活跃的期间,由活跃间隙分隔开。通俗一点说,消息之间的间隔小于超时阈值(sessionGap)的,则被分配到同一个窗口,间隔大于阈值的,则被分配到不同的窗口,如下图所示。 


除上面之外,Flink也支持自定义Window。

Trigger

Window定义了数据分组的机制,触发器(trigger)则定义了什么时候触发计算,也就是数据的落地的时间。

Watermarks

Flink支持基于event time进行数据处理,也就是乱序处理,那么它如何确定所有的事件都已经到了,当前时间窗口不会再有其他数据,也就是什么时间点触发计算逻辑?假设我们定义了1分钟的基于事件时间的窗口并且第一个窗口开始时间为10:00:00,对每一个消息,Flink从中抽取事件时间,如果当前事件的事件时间为10:01:00,那么我们是否可以安全地关闭这个窗口并进行处理?也就是说在这之后能够确保10:00:59的消息不会再出现?Flink通过Watermarks机制解决这一问题,Watermarks是带着时间戳的特殊的事件,规定在Watermarks之后的事件其事件时间不会小于当前Watermarks的时间,这样的话如果我们遇到了Watermarks,我们就能够安全的关闭在Watermarks时间前的窗口并开始计算。Watermarks由应用开发者产生(因为Watermarks的产生需要领域知识,而Flink只是框架),Flink框架负责将其嵌入到流中并检测触发窗口的关闭及计算。 


通常需要有领域知识来产生Watermarks。比如我们知道事件可能会延迟,但是延迟不会超过5s,这时候我们产生Watermarks的时间戳就可以是当前遇到最大事件时间减去5s,当然我们也可以通过建模依据过往的数据对时间进行预估。

Watermarks的产生可能过快也可能过慢。如果太慢,那么延迟就会大,Flink支持结果预产出;如果太快,窗口等不及所有的数据收集完就会被关闭并被计算,而计算的结果会不正确;这种情况下系统会遇到迟到的事件(late event),Flink对迟到事件有专门的处理机制。

Stateful Computation 

Flink 的一个优势是支持有状态的计算。如果处理一个事件(或着一条数据)的结果只跟事件本身的内容有关,称为无状态处理;反之结果还和之前处理过的事件有关,称为有状态处理,比如sum操作。


State

状态(State)是计算过程中产出的数据,在容错恢复和 Checkpoint 中有重要的作用,流计算在本质上是 Incremental Processing,因此需要不断查询保持状态;另外,为了确保 Exactly-once 语义,需要的数据能够写入到状态中并持久化存储;持久化存储,能够保证在整个分布式系统运行失败或者挂掉的情况下做到 exactly-once,这是状态的另外一个价值。 这些状态被存储到Memory或者基于磁盘的本地RocksDB中,一个Flink集群有多个实例,多个实例的本地存储共同构建了Flink内部的存储系统。这些本地存储通常是数据处理所在的实例上。

Checkpoint

分布式一致性的快照,提供了 exactly-once 处理的语义。Checkpoint 是 Flink 实现容错机制的核心,它周期性的记录计算过程中操作符(Operator)的状态,并生成快照持久化存储。当 Flink 作业发生故障崩溃时,可以有选择的从 Checkpoint 中恢复,保证了计算的一致性。

比如统计英文字母出现次数的伪代码如下:


输入流是(字母,次数)对,有两个操作符keyBy及mapWithState,keyBy操作符对输入数据按照第一个字段也就是字母进行分组并转发相应的消息到mapWithState操作符中,mapWithState操作符是个有状态的操作符,它接收每个消息并对字母次数进行累加,更新结果到本地存储中。

图1-a显示了初始状态,共有6个消息,ckpt是Flink自动插入的Checkpoint屏障(barriers)消息,操作符在遇到屏障后会进行相应的操作。图中上面一个map操作符处理字母a,中间处理b,下面处理c,初始值都为0。Checkpoint是一种特殊的消息,不参与计算,只是用来触发操作符的Checkpoint。

如图1-b显示了当Flink数据源遇到处理完第一个消息后遇到Checkpoint屏障,会记录当前的数据处理位置到外部稳定的存储系统中,以便故障出现后从记录的位置处重新处理消息流,这个过程是个异步过程。图1-c展示了map操作符遇到Checkpoint屏障之后,会将当前的状态异步地存到稳定存储中,注意到当前的状态跟备份的状态值不一样。当所有的操作符都处理完Checkpoint屏障之后,Checkpoint就算完成,存储系统里面存的值反应了Checkpoint那一时刻整个系统的快照。

图1-d显示了一个节点由于某种原因不正常了,这时候如图1-e Flink会从外部系统中读取备份数据,并重新将系统重置到最近一次Checkpoint的状态,然后继续处理,就好像没有发生过失败一样。 


Savepoint

Checkpoint是Flink内部数据备份机制,有系统自动触发,而savepoint由外部触发,用来主动备份,其实现类似于Checkpoint。

Queryable State

Flink的计算结果保存在State中,也就是本地存储系统中,通常我们需要使用不同的sink将数据导出到外部系统中,以便提供查询服务,如下左图所示。 Flink提供了queryable state 查询服务,可以直接从本地存储系统中查询数据,从而避免了状态结果的同步(数据一致性问题),降低数据延迟,提高了查询效率。 


流处理框架比较

*来自参考文献1

参考文献

https://yq.aliyun.com/articles/62637

https://yq.aliyun.com/articles/68210

https://zhuanlan.zhihu.com/p/26983736

https://www.digitale-technologien.de/DT/Redaktion/DE/Downloads/Publikation/smart-data-boden-introduction-flink.pdf?__blob=publicationFile&v=3

https://flink.apache.org/

https://cdn2.hubspot.net/hubfs/4757017/Ververica/Docs/Introduction_to_Apache_Flink_book_9781491998809.pdf

https://alitech-private.oss-cn-beijing.aliyuncs.com/1543409877893/Apache%20Flink.pdf?Expires=1580033078&OSSAccessKeyId=LTAIqKGWQyF6Vd3W&Signature=PWvvwWTEbLehC06BDsfQoWMktPI%3D

你可能感兴趣的:(Apache Flink 简述)