Apache Flink
概述
先来看看Flink官网的介绍:
Apache Flink is a framework and distributed processing engine for stateful computations over
unbounded and bounded data streams.
其中提到了几个关键词,首先是framework和distributed,可以看出Flink是一个分布式的处理框架,然后stateful
代表了Flink支持数据处理过程中各种状态的管理与维持,最后的unbounded and bounded表示Flink既支持有界
的数据源也支持无界的数据流。
基础概念
从低级到高级的API
SQL/Table API - 高级接口,可以像操作关系型数据库那样操作数据
DataStream API - 流、窗口相关,数据源支持无界的stream和有界的set
ProcessFunction - 事件、状态、时间相关操作
API越高级,代码量越少,反之越低级所需要的代码细节就越多
有状态计算的支持
计算可以分为有状态和无状态的,无状态的例子比如我要实现消息的过滤,把一些带关键字的消息给拦截下来发给
下游存储,那么过来一条消息Flink就判断一下,是不需要保存任何状态状态的,即每次计算结果不依赖上一条消
息,这叫无状态计算。
有状态计算,就比如我现在要计算每小时里商城里卖出了哪些衣服,这时候每一个小时的窗口里就会保存着这一个
小时内卖出的衣服,每小时结束的时候就会把结果给统计出来,这里需要保存的具体衣服就是状态。
Flink 为了让用户在编程时能够更轻松、更容易地去管理状态,引入了托管状态(managed state)并提供了 API
接口,让用户使用起来感觉就像在用 Java 的集合类一样(比如Keyed State中提供的ValueState、ListState、
ReducingState、FoldingState、MapState)。
Checkpoint机制
下面要用到,先说下这个,Checkpoint由Flink自动生成,用来在故障发生时重新处理记录,从而修正状态。
这是 Flink 最重要的一个特性。Flink 基于 Chandy-Lamport 算法实现了分布式一致性的快照,从而提供了
exactly-once 的语义。在 Flink 之前的流计算系统(如 Strom,Samza)都没有很好地解决 exactly-once 的问
题。
它可以在出现故障时将系统重置回正确的状态,就类似快照这样的一个功能,他的核心作用是确保状态正确,即使
遇到程序中断,也要正确。
Flink检查点算法的正式名称是异步屏障快照(asynchronous barrier snapshotting),默认情况下,checkpoint
不会被保留,取消程序时即会删除他们。
Savepoint
上面说了Checkpoint就再看下这个,没怎么多了解,这个也相当于备份的一个东西,但是和Checkpoint是有区别的。
Checkpoint的生命周期由Flink管理,即Flink创建,拥有和发布Checkpoint - 无需用户交互。
Savepoints由用户创建,拥有和删除。
用白话说就像是一个是程序自动备份,一个是我们手动备份,前者为了防止意外的情况,后者是我们出于安全考虑进行的备份,
丰富的状态持久化策略
上面说的状态的使用在平时的业务场景中用的还是比较多的,但是Flink默认是将state放在内存中的,这样如果数
据量太大或者窗口太大就会导致状态的存储空间不足,Flink提供了三种状态保存方式:
MemoryStateBackend
默认使用MemoryStateBackend,将数据保存在java的堆里。
当进行checkpoints的时候,这种策略会对状态做快照,然后将快照作为checkpoint acknowledgement的一
部分发送给JobManager,JM也将其保存在堆中。
MemoryStateBackend可以使用异步的方式进行快照,我们也鼓励使用异步的方式,避免阻塞,现在默认就
是异步。如果不希望异步,可以在构造的时候传入false。
适合:本地开发和调试、状态比较少的job
FsStateBackend
FsStateBackend通过文件系统的URL来设置,比如“hdfs://namenode:40010/flink/checkpoints”或
者“file:///data/flink/checkpoints”。
保持数据在TM的内存中,当做checkpointing的时候,会将状态快照写入文件,保存在文件系统或本地目
录。少量的元数据会保存在JM的内存中。
默认使用异步的方式进行快照,同样,取消异步需要传递false
适合:状态或窗口比较大、需要做HA的场景
RocksDBStateBackend
RocksDBStateBackend通过文件系统的URL来设置,例如“hdfs://namenode:40010/flink/checkpoints”或
者“file:///data/flink/checkpoints”。
保存数据在一个叫做RocksDB的数据库中,这个数据库保存在TM的数据目录中。当做checkpointing时,整
个数据库会被写入文件系统和目录。少量的元信息会保存在JM的内存中。
这种策略只支持异步快照。
能够持有的状态的多少只取决于可使用的磁盘大小,相比较FsStateBackend将状态保存在内存中,这会允许
使用非常大的状态。但这也同时意味着,这个策略的吞吐量会受限。
RocksDBStateBackend是目前唯一支持incremental的checkpoints的策略。
适合:非常大的状态和窗口、需要HA的场景
Flink的流结构
Source
Source: 数据源,Flink 在流处理和批处理上的 source 大概有 4 类:基于本地集合的 source、基于文件的
source、基于网络套接字的 source、自定义的 source。自定义的 source 常见的有 Apache kafka、Amazon
Kinesis Streams、RabbitMQ、Twitter Streaming API、Apache NiFi 等,当然你也可以定义自己的 source。
Transformation
Transformation:数据转换的各种操作,有 Map / FlatMap / Filter / KeyBy / Reduce / Fold / Aggregations /
Window / WindowAll / Union / Window join / Split / Select / Project 等,操作很多,可以将数据转换计算成你想
要的数据。
Sink
Sink:接收器,Flink 将转换计算后的数据发送的地点 ,你可能需要存储下来,Flink 常见的 Sink 大概有如下几
类:写入文件、打印出来、写入 socket 、自定义的 sink 。自定义的 sink 常见的有 Apache kafka、RabbitMQ、
MySQL、ElasticSearch、Apache Cassandra、Hadoop FileSystem 等,同理你也可以定义自己的 sink。
Tip:什么是算子?
在流处理、交互式查询中有个常用的概念是“算子”,在英文中被成为“Operation”,在数学上可以解释为一个函数
空间到函数空间上的映射O:X->X,其实就是一个处理单元,往往是指一个函数,在使用算子时往往会有输入和输
出,算子则完成相应数据的转化,比如:Group、Map等都是算子。
Flink的分布式架构
Program Code
我们编写的 Flink 应用程序代码
Job Client
Job Client 不是 Flink 程序执行的内部部分,但它是任务执行的起点。 Job Client 负责接受用户的程序代码,然后
创建数据流,将数据流提交给 Job Manager 以便进一步执行。 执行完成后,Job Client 将结果返回给用户。
Job Manager
主进程(也称为作业管理器)协调和管理程序的执行。 它的主要职责包括安排任务,管理checkpoint ,故障恢复
等。机器集群中至少要有一个 master,master 负责调度 task,协调 checkpoints 和容灾,高可用设置的话可以
有多个 master,但要保证一个是 leader, 其他是 standby; Job Manager 包含 Actor system、Scheduler、Check
pointing 三个重要的组件。
Task Manager
从 Job Manager 处接收需要部署的 Task。Task Manager 是在 JVM 中的一个或多个线程中执行任务的工作节点。
任务执行的并行性由每个 Task Manager 上可用的任务槽决定。 每个任务代表分配给任务槽的一组资源。 例如,
如果 Task Manager 有四个插槽,那么它将为每个插槽分配 25% 的内存。 可以在任务槽中运行一个或多个线程。
同一插槽中的线程共享相同的 JVM。 同一 JVM 中的任务共享 TCP 连接和心跳消息。Task Manager 的一个 Slot 代
表一个可用线程,该线程具有固定的内存,注意 Slot 只对内存隔离,没有对 CPU 隔离。默认情况下,Flink 允许
子任务共享 Slot,即使它们是不同 task 的 subtask,只要它们来自相同的 job。这种共享可以有更好的资源利用
率。