大数据的实时性带来价值更大,部分业务场景甚至无法接受延迟在分钟级以上的批处理计算,比如:
因此大数据计算架构逐渐从批式计算发展为流式计算:
Mini-Batch:将流处理转化为针对特别小的批进行批处理
一致性:
Statefull:引擎自己是否支持状态在两次数据处理之间保留、传递
ApacheFlink在开源生态上的能力比较强大,可以支持:
一个Flink集群主要包含以下两个核心组件:
计算架构图【重点】:
Flink程序中的Client端只会生成程序的逻辑执行图,将其提交给JM后,由JM生成具体的、实际的物理执行图,并据此把真正的Task分发给TM来执行。
流式的WordCount示例(Flink版Helloworld),从kafka中读取个实时数据流,每10s统计一次单词出现次数。
使用DataStreamAPI编写的代码如下:
注:
在Flink中,应用程序由用户自定义算子转换而来的流式dataflows所组成。这些流式dataflows形成了有向图,以一个或多个源(source)开始,并以一个或多个汇(sink)结束。
这段代码对应的DataFlowGraph(DAG):
ExecutionGraph的生成过程:
flowchartLRs1["DataStreamAPICode"]-->s2[JobGraph]-->s3["ExecutionGraph(Parallelized)"]Flink程序本质上是分布式并行程序。在程序执行期间,一个流有一个或多个流分区(StreamPartition),每个算子有一个或多个算子子任务(OperatorSubtask)。每个子任务彼此独立,并在不同的线程中运行,或在不同的计算机或容器中运行。
算子的并行度:该算子的子任务数。在同一程序中,不同算子也可能具有不同的并行度。
以sink的并行度=1,其余Operator的并行度=2为例:
JM会将DataFlowGraph转化为如下图下方所示的ParallelDataflow(内部称为ExecutionGraph):
Stream可以在两个Operator之间传输数据,传输方式有以下两种:
为了更高效地分布式执行,Flink会尽可能地将算子的子任务链接(chain)成任务(task),也称为构成算子链(Operatorchain)。
由于每个任务只在一个线程中执行,尽可能多地构成算子链就可以:
如下图的Source和map()可以链接在一起。
最后将上面的任务调度到具体的TaskManager中的slot中执行,一个slot只能运行同一个任务的各个子任务。
Slot不会对CPU隔离,内存隔离也仅是有限部分的隔离。
Ref:
一些业务场景,除了实时的数据统计需求,为了确认运营或产品的效果,用户同时还需要和历史数据做比较(比如,抖音一些直播数据的统计),这里给一个传统的流批分离版本的解决方案:
这种架构有一些痛点:
流和批业务场景的特点如下表:
Flink的设计思路:批式计算是流式计算的特例,EverythingisStreams。
因此,理论上我们是可以用一套引擎架构来解决上述两种场景,只不过需要对不同场景支持相应的扩展性、并允许做不同的优化策略。
Flink对批数据的处理架构:
ApacheFlink主要从以下几个模块来做流批一体:
Scheduler主要负责将作业的DAG转化为在分布式环境中可以执行的Task。
在1.12之前的Flink版本,Flink支持两种调度模式:
在最新的Flink版本中还提供了名为PipelineRegion的调度机制。
这种机制下会把所有的任务分割成若干个流水线区域(region)。对于包含多个region的流作业,在开始部署任务之前,它不再等待所有任务获取slot。取而代之的是,一旦一个region获得了足够的任务slot就可以部署它。本质上,不管是流作业还是批作业,都是按照PipelineRegion粒度来申请资源和调度任务。
可以看到这种机制的性能与资源需求介于EAGER模式和LAZY模式之间。
PipelineRegion调度机制可以定制分割流水线区域的策略,实现自定义调度细粒度,以其中最极端的两种策略为例:
Shuffle:在分布式计算中,用来连接上下游数据交互的过程叫做Shuffle。实际上,分布式计算中所有涉及到上下游衔接的过程,都可以理解为Shuffle。
Shuffle分类:
流和批Shuffle之间的差异:
各个Shuffle策略的常见使用场景:
虽然Streaming和BatchShuffle在具体的策略上存在一定的差异,但本质上都是为了对数据进行重新分区,因此不同的Shufle之间是存在一定的共性的。所以Flink的目标是提供一套统一的Shuffle架构,既可以满足不同Shufle在策略上的定制,同时还能避免在共性需求上进行重复开发。
因此,Flink实现了一个Pluggable的ShuffleService框架,抽象出一些公共模块。
对于ShufleService,Flink开源社区已经支持:
字节内部是基于一种名为CSS的ShufleService来实现的RemoteShuffleService。
典型场景:
三种业务场景的特点:
三种业务场景面临的挑战:
Flink对OLAP的处理架构:
Batch场景需求:流批一体支持
OLAP场景需求:短查询作业场景
架构与功能模块:
作业管理及部署模块:
资源管理及计算任务调度:
其他:
最终的演进总体架构:
抖音电商业务原有的离线和实时数仓架构如下图:
目前电商业务数据分为离线数仓和实时数仓建设,离线和实时数据源,计算引擎和业务代码没有统一,在开发相同需求的时候经常需要离线和实时对齐口径,同时,由于需要维护两套计算路径,对运维也带来压力。
随着Flink发展(逐步发展为流批一体引擎):
演进目标:从数据源,业务逻辑,计算引擎完成统一,提高开发和运维效率。