「流/批/OLAP 一体的 Flink 引擎介绍」(上)|青训营笔记

133 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第3天.

前言

Flink引擎的基础介绍,对于制作相关项目有着重要的指导作用。

Flnk概述

为什么会有流式计算的需求,为什么Flink能够脱颖而出,Flink当前的开源生态

Apache Flink的诞生背景

什么是大数据

大数据:无法在一定时间内用常规软件工具对其进行获取、存储、管理和处理的数据集合。

价值化Value 价值密度低,整体价值高

海量化Volumes:规模大

快速化Velocity :数据产生规模和速度快

多样化Variety:数据语言和结构多样

大数据计算架构发展历史

史前阶段~2006

  • 传统数仓
  • Oracle
  • 黑箱使用 Hadoop
  • 分布式
  • Map-Reduce
  • 离线计算

Spark

  • 批处理
  • 流处理
  • SQL高阶API
  • 内存迭代计算

Flink

  • 流计算
  • 实时、更快
  • 流批一体
  • Streaming/Batch SQL

为什么需要流式计算

大数据的实时性带来的价值更大

eg.

  1. 监控场景
  2. 金融风控:实时监测出异常交易的行为,就能及时阻断风险的发生
  3. 实时推荐

大数据实时性的需求,带来了大数据计算架构模式的变化

批式计算

  • 离线计算,非实时
  • 静态数据集
  • 小时/天等周期计算

流式计算

  • 实时计算,快速、低延迟
  • 无限流、动态、无边界
  • 7*24h持续运行
  • 流批一体

为什么Apache Flink会脱颖而出

流式计算引擎发展历程

业内常用的计算框架演化历史(二十年) Storm;MillWheel;Kafka;Cloud Dataflow;Flink;Beam

Why Flink

框架;分布式引擎;支持有状态计算;有边界和无边界

精确一次的计算语义Exactly-Once

状态容错Checkpoint

Dataflow编程模型 Window等高阶需求支持良好

流批一体

Apache Flink开源生态

Flink社区的开源生态

和成熟的数据存储集成

Flink整体架构

Flink当前的整体架构介绍,一个Flink作业如何调度和运行起来,Flink如何做到流批一体

Flink分层架构

Flink各个模块的用途

  1. SDK层:三类,SQL/Table、DataStream、Python
  2. 执行引擎层(Runtime层):执行引擎层提供了统一的DAG,用来描述数据处理的Pipeline,不管是流还是批,都会转化为DAG图,调度层再把DAG转化成分布式环境下的Task,Task之间通过Shuffle传输数据
  3. 状态存储层:负责存储算子的状态信息
  4. 资源调度层:目前Flink可以支持部署在多种环境

Flink总体架构

Mater/Slave架构、JobManager/TaskManager

一个Flink集群。主要包含以下两个核心组件:

  1. JobManager(JM):负责整个任务的协调工作,包括:调度task、触发协调Task做Checkpoint、协调容错恢复等 JobManager(JM) 主要职责: (1)Dispatcher: 接收作业,拉起 JobManager 来执行作业,并在 JobMaster 挂掉之后恢复作业; (2)JobMaster: 管理一个 Job 的整个生命周期,会向 ResourceManager 申请 Slot ,并将 Task 调度到对应 TM 上; (3)ResourceManager: 负责 Slot 资源的管理与调度, TaskManager 拉起之后会向 RM 注册。
  2. TaskManager(TM):负责执行一个DataFlowGraph的各个task以及data streams的buffer和数据交换

Flink作业示例

一个Fink作业在Flink中的处理流程、DataFlow Model设计思想

流式 WordCount 示例,从 Kafka 中读取一个实时数据流,每 10s 统计一次单词出现次数, DataStream 实现代码如下:

DataStream<String> lines = env.addSourse(new FlinkKafkaConsumer<>(...));

//Transformation
DataStream<String> events = lines.map((line) -> parse(line));
DataStream<Statistics> stats = events.keyBy(event -> event.id)
    .timeWindow(Time.seconds(10)).apply(new myWindowAggregationFunction());
    
//Sink
stats.addSink(new BucketingSink(path));