序言
大数据运算主要有2个领域:1:流式计算 2:批量计算。在数据操作层面可以看做如下的两类
- 有限数据集:数据大小有限(固定大小,比如固定的文件),用于批处理,
- 无限数据集:数据持续增长(属于无限大小,比如kafka中的日志数据,总是有新数据进入,并且不知道什么时候结束或者是永远不结束),用于流式处理。(Storm就是流式处理的解决方案)
参考文章:
- Apache Flink: Apache Flink 是什么? ------flink官网中文☺
- Flink 入门教程_Vioao's Blog-优快云博客_flink入门
- Flink从入门到入土(详细教程) - Java知音号 - 博客园
数据处理框架
Lambda 架构
Lambda架构是Nathan Marz提出的一个大数据处理框架。该框架的做法是将大数据系统架构拆分成了三层:
-
Batch Layer:该层主要利用分布式处理系统处理大批量的数据,在数据集上预先计算查询函数,并构建查询所对应的Batch View。即所谓的批处理,适合处理离线数据。这一层中常用的框架是 Apache Hadoop这一套,存储一般用 Elephant DB, Apache Impala, SAP HANA 或 Apache Hive
-
Speed Layer :该层的目的是提供低延时的 Real-time View,处理的都是实时的增量数据(即流数据cuiyaonan2000@163.com)。这一层中常用的流数据处理框架有Apache Storm, Apache Spark, Apache Flink. 输出通常是存储在高速的 NoSql 数据库中。存储一般用 Elasticsearch
-
Serving Layer:Serving Layer 用于响应用户的查询请求,它将 Batch Views 和 Real-time Views 的结果进行了合并,得到最后的结果。这一层通常就是使用的 Apache Druid,存储一般用 Apache Cassandra, Apache HBase, MongoDB
Lambda该模型强调多个系统且是独立的,既包含了流数据处理系统,批量数据处理系统。如下图的一个Lambda的简单实现,storm处理流数据,Hadoop处理批量数据。

Kappa 架构
Lambda 架构需要维护两套代码,两套系统(批处理和实时处理);在某些情况下,这是非常不划算且没必要的,为什么实时流数据用后就丢弃,为什么不用流计算系统来进行全量数据处理从而去除Batch Layer这一层?
于是,Jay Kreps 在 2014 提出了Kappa 架构,它可以看做是 Lambda 架构的简化版,就是讲 Lambda 架构中的批处理模块移除,移除后如下:(即去掉了批量处理系统)
其核心思想就是,使用系统( eg. kafka )保存历史消息数据, 然后通过回放数据(这里的回放数据对应kafka就是消费端进行消费cuiyaonan2000@163.com),利用 Real-time Layer 这一层的流处理框架( eg. Flink , Spark Streaming , Storm )来完成业务上的批处理需求。核心步骤如下:
-
数据需要可以被重放(重新处理)。例如, 用 Kafka 来保存数据,你需要几天的数据量就保存几天。
-
用新实例重新处理计算重放的数据。即当需要全量重新计算时,重新起一个流计算实例,从头开始读取数据进行处理,并输出到一个新的结果存储中。------------即保存加工后的kafka数据
-
当新的实例做完后,停止老的流计算实例,并把老的一些结果删除。
Blink
Blink是阿里基于Flink的一个分支。------------------目前阿里收购了Flink的母公司,不知道后来Flink的前景如何。

Flink简介
Apache Flink是一种新一代的数据处理工具,可以处理有限数据集(这也称为批处理)或者可能无限的数据流(流处理)。就它的新功能而言,许多人认为Apache Flink是一款有能力成为规则改变者的软件,未来甚至可以取代Apache Spark。
尽管流处理已经变得越来越普遍,但许多任务仍然需要批处理----------------(批量处理肯定是是需要的,而且很多业务上都是需要的。但是所谓的流数据其实也是批量数据的灵活应用而已。现在的blink分支,就会把批量数据和流量数据在底层给屏蔽了,而让使用者在上层使用Sql stream进行统一的操作,方便了开发。cuiyaonan2000@163.com)
目前主流的流数据处理框架: Storm (Storm Trident)、Spark Streaming、Flink
- Storm:支持低延迟,但是很难实现高吞吐,并且不能保证 exactly-once----------------------实时性高,吞吐量低
- Sparking Streaming ( Storm Trident ):利用微批处理实现的流处理(将连续事件的流数据分割成一系列微小的批量作业),能够实现 exactly-once 语义,但不可能做到完全实时(毕竟还是批处理,不过还是能达到几秒甚至几亚秒的延迟)---------实时性不高,吞吐量高
- Flink:实时流处理,支持低延迟、高吞吐、exactly-once 语义、有状态的计算、基于事件时间的处理----------实时性高,吞吐量高

相对来说,Flink实现了真正的流处理,并且做到了低延迟、高吞吐 和 exactly-once 语义;同时还支持有状态的计算(即使在发生故障时也能准确的处理计算状态) 和 基于事件时间的处理
特点
- Flink 支持以数据并行和流水线方式执行任意流数据程序,Flink 的流水线运行时系统可以执行批处理和流处理程序。此外,Flink 的运行时本身也支持迭代算法的执行。
- Flink 提供高吞吐量、低延迟的流数据处理引擎以及对事件-时间处理和状态管理的支持。
- Flink 应用程序在发生机器故障时具有容错能力,并且支持exactly-once语义。
- Flink 并不提供自己的数据存储系统,但为Amazon Kinesis、Apache Kafka、HDFS、Apache Cassandra和ElasticSearch等系统提供了数据源和接收器 --------------------表示可以从多种存储介质中获取数据
- Flink 可以处理任意数据量级。-----------------------计算框架配合大数据存储HDFS就可以实现大数据计算
-
Flink 可以部署在Yarn,K8s,Mesos多种资源调度框架中。------------------------------------部署运维灵活方便
Flink架构图--------------比较重要

Flink主要有两类进程: JobManager 和 TaskManager
- JobManager(masters): 协调分布式计算、任务调度,协调checkpoints,错误调度等,相当于一个指挥官吧(实际部署时,至少需要一个 JobManager,实际生产环境部署时都会做HA,部署多个JobManager;这个时候,只有一个leader,其他都是standby模式)
- TaskManager(workers):真正执行dataflow的,并对streams进行缓存和交换
总的来说,运行中的 Flink 集群至少有一个 JobManager 进程和一个 TaskManager 进程。如果将客户端也算进去的话,那么还有一个 Client 进程。各个进程一般部署在不同的机子上,不过也可以部署在同一台机子上,就比如说在本地启动一个集群时( Local 模式,通常用于开发调试 ), JobManager 进程和 TaskManager 进程就是跑在同一台服务器上。Flink 是基于 Akka Actor 实现的 JobManager 和 TaskManager,所以JobManager和 TaskManager 以及 Client 之间的信息交互都会通过事件的方式来进行处理的。
一个简单的流程就是,Client 提交任务作业给 JobManager ,JobManager 负责该作业的调度和资源分配(在 Flink 集群中,计算资源被定义为 Task Slot。每个 TaskManager 会拥有一个或多个 Slots),随后将作业分给对应的 TaskManager,TaskManager 收到任务后,启动线程去执行,并向 JobManager 报告任务状态和自身运行状态等。当任务结束后, JobManager 将收到通知,并统计数据后发送给 Client。
数据处理相关
流------即流数据和批量数据
显而易见,(数据)流是流处理的基本要素。然而,流也拥有着多种特征。这些特征决定了流如何以及何时被处理。Flink 是一个能够处理任何类型数据流的强大处理框架。
- 有界 和 无界 的数据流:流可以是无界的;也可以是有界的,例如固定大小的数据集。Flink 在无界的数据流处理上拥有诸多功能强大的特性,同时也针对有界的数据流开发了专用的高效算子。
- 实时 和 历史记录 的数据流:所有的数据都是以流的方式产生,但用户通常会使用两种截然不同的方法处理数据。或是在数据生成时进行实时的处理;亦或是先将数据流持久化到存储系统中——例如文件系统或对象存储,然后再进行批处理。Flink 的应用能够同时支持处理实时以及历史记录数据流。
状态-----------数据、任务被拆分后的状态
只有在每一个单独的事件上进行转换操作的应用才不需要状态,换言之,每一个具有一定复杂度的流处理应用都是有状态的。
任何运行基本业务逻辑的流处理应用都需要在一定时间内存储所接收的事件或中间结果,以供后续的某个时间点(例如收到下一个事件或者经过一段特定时间)进行访问并进行后续处理。-------必须要有状态的原因,除非你算1+1等2.cuiyaonan2000@163.com
应用状态是 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 能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。
时间----------------数据生命=流+状态+时间
时间是流处理应用另一个重要的组成部分。因为事件总是在特定时间点发生,所以大多数的事件流都拥有事件本身所固有的时间语义。进一步而言,许多常见的流计算都基于时间语义,例如窗口聚合、会话计算、模式检测和基于时间的 join。流处理的一个重要方面是应用程序如何衡量时间,即区分事件时间(event-time)和处理时间(processing-time)。
Flink 提供了丰富的时间语义支持。
- 事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。
- Watermark 支持:Flink 引入了 watermark 的概念,用以衡量事件时间进展。Watermark 也是一种平衡处理延时和完整性的灵活机制。
- 迟到数据处理:当以带有 watermark 的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink 提供了多种处理迟到数据的选项,例如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。
- 处理时间模式:除了事件时间模式,Flink 还支持处理时间语义。处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。
API分层
Flink 根据抽象程度分层,提供了三种不同的 API。每一种 API 在简洁性和表达力上有着不同的侧重,并且针对不同的应用场景。

- ProcessFunction:是 Flink 所提供的最具表达力的接口。ProcessFunction 可以处理一或两条输入数据流中的单个事件或者归入一个特定窗口内的多个事件。它提供了对于时间和状态的细粒度控制。
- DataStream API:DataStream API 为许多通用的流处理操作提供了处理原语
- SQL & Table API: 上层应用,Flink 支持两种关系型的 API,Table API 和 SQL。这两个 API 都是批处理和流处理统一的 API
Flink沉没过程

- Enviroment: Job提交到集群
- Source: 获取数据源,并转换成数据流
- Transform:对数据流进行计算并产生新的数据流---------------算子即计算函数,跟java集合stream中的map什么类似
- Sink:存入存储介质。
通常,其处理流程为 Source -> Transformations -> Sink . 其数据流构成一个有向无环图(DAG)。

Source & Sink
Source 为待处理数据的输入地,而 Sink 为处理后的输出地,目前 Flink 支持的 Source 和 Sink 有:

Transform
其中 Transformation Operators 有多种,DataSet API 和 DataStream API 支持的不完全相同,通常支持的有如下几种,更详细的可以参考官方文档;

对时间的处理
一般来说,在流数据处理中,可以将时间分成三类:
- 事件时间:事件实际发生的时间(流记录中本身包含对应的时间戳)
- 处理时间:事件被处理的时间(被流处理器处理的时间)
- 进入时间:事件进入流处理框架的时间(缺乏真实事件时间的数据会被流处理器附上时间戳,即流处理器第一次看到他的时间)
Flink 允许用户根据自己所需来选择三者中的任何一种来定义时间窗口。
那么什么是时间窗口呢??????---------通过如下的描述 窗口可以叫成组, 时间是类型,时间窗口也可以叫时间组。即一组时间区分的时间。
先从窗口说起,窗口是一种机制,其将许多事件按照时间或者其他特征分组,从而将每一组作为整体进行分析。Flink 目前默认支持有时间窗口,计数窗口,会话窗口。用户可根据自己需要的情况选择对应的窗口处理。
时间窗口
时间窗口,应该算是比较常用的一个窗口处理了。比如说,每分钟统计一次某商品的点击数啊;或者每分钟统计一次一个小时内点击数最高的前十个产品之类的需求。只要是按照时间划分的,都可以使用时间窗口。
时间窗口又分为滚动时间窗口和滑动时间窗口两种。


计数窗口
计数窗口和时间窗口类似,只不过分组依据不是时间而是数据个数,同样也分滚动计数窗口和滑动计数窗口
会话窗口-------支持自定义分组数据的接口
像前两种,这个比较特别。需要先理解什么算一个会话: 会话指的是活动阶段,其前后都是非活动阶段,那么这一活动阶段就是一个有效的会话。会话阶段通常需要有自己的处理机制,可以想象,会话的定义比较灵活,很难有固定的会话定义。Fink 也支持一些简单的定义直接使用,RT
时间和watermarks
支持事件时间的流处理器需要明确的知道何时才是事件事件的终止。
就好比一个一小时的时间窗口操作,我们需要知道何时才是真正的结束时间,否则窗口无法被正确的关闭( 因为实际,基于事件时间的事件其由于网络等原因,其到达的顺序并不一定就是其事件发生时间的顺序 )。
另外,在 Kappa 架构中, 流数据处理框架需要支持处理回放的数据,那么同一组数据重新运行同样的程序,需要得到相同的结果,这也需要其支持事件时间,因为如果窗口的设定是根据系统时间而不是事件自带的时间戳,那么每次运行同样的程序,都会得到不同的结果。
可见支持事件时间对于流处理架构而言至关重要,因为事件时间能保证结果正确,并使流处理架构拥有重新处理数据的能力。那么 Flink 是如何做到对事件时间的支持的? 其实际是通过 Watermarks 机制来实现的。

大意就是说,Watermarks 作为数据流中的一部分,包含一个时间戳 t,当处理器处理到这个 Watermark(t) 的时候,就认为所有事件时间小于该水印时间的事件数据都已经到达。
但是即使如此,依然可能会有些事件数据在 Watermark 之后到达,这时 Watermark 机制也无法起到对应的作用,针对这一情况 Flink 支持了 Late Elements 处理,详情查看官网 Allowed-lateness。
最后,如果对于水印还是不明白的,可以阅读下Flink Event Time Processing and Watermarks 和 Streaming System 有个更深的了解
有状态的计算-----凡是涉及分布式计算的都会有状态,所以该机制很重要
流计算一般分为有状态和无状态两种,无状态计算指的是处理过程中不依赖于之前的数据处理结果或其他中间数据;而有状态的计算会维护状态,并基于最新数据和当前状态生成输出结果。

有状态的计算引入了状态,所有引入了状态的分布式系统都会遇到一个数据一致性的问题。流处理或消息系统中,通常将其定义为 “正确性级别”, 通常来说会有三个级别:
- at-most-once: 数据可能会丢失
- at-least-once:数据最少处理一次
- exactly-once:数据均被且只被处理一次
Flink 的话支持 exactly-once 语义,且还能保持低延迟和高吞吐的处理能力,这是 Flink 的一个重大优势。-----这个好牛逼啊,多次提及
Flink 保证 exactly-once 主要是通过他的 checkpoint 和 savepoint 机制。
checkpoint
checkpoint: Flink 自动周期生成,用于用户程序出故障时,使其重置回到正确的状态,主要需做两件事
保存source中流的偏移量( eg. kafka数据的便宜量,以便数据重放)
保存中间的计算状态( 即StateBackend,这个保存的位置可以选择,后面再讲)
Flink 检查点算法的正式名称是异步屏障快照(asynchronous barrier snapshotting)。该算法大致基于Chandy-Lamport 分布式快照算法。
其中,有一个核心的概念:Barrier(屏障)
在数据流中,屏障和普调标记类似;他们都由算子处理,但是不参与计算,而是会触发与检查点相关的行为。当读取输入流的数据源遇到检查点屏障时,它将其在输入流的位置保存到文档存储中(eg. kafka的偏移量)。当算子处理完记录并收到了屏障时,它们会将状态异步保存到稳定存储中,当状态备份和检查点位置备份都被确认后,则认为该检查点已完成。
总结下:
- Souce 遇到屏障保存数据位置
- 算子遇到屏障异步保存状态
- 保存结束后确认检查点完成
savepoint
savepoint: 需要应用自己手动生成,通常用于状态版本控制。依赖于checkpoint机制。
上述流程中涉及到保存状态,Flink 可以支持多种状态存储。大致有以下几种StateBackend
- MemoryStateBackend:快速,但是不稳定,重启就没了。
- RocksDBStateBackend:支持增量,支持大状态长窗口的大数据存储,但是存储和读取时都需要序列化(会耗时)
- FsStateBackend:支持大状态长窗口的大数据存储,但是还是会保存一份在 TaskManager 的 Memory 中,所以状态的大小不能超过 TaskManager 的内存
1526

被折叠的 条评论
为什么被折叠?



