这是我参与「第四届青训营 」笔记创作活动的第4天。
1)Shuffle定义
在分布式计算中,用来连接上下游数据交互的过程叫做Shuffle。实际上,分布式计算中所有涉及到上下游衔接的过程(比如对数据进行keyBy操作,再放到不同window里面做聚合的过程,涉及数据分发),都可以理解为Shuffle。
2)Shuffle实现方式
针对不同的分布式计算框架,Shuffle有不同的实现:
①基于文件的Pull Based Shuffle:比如Spark、MR。它的特点是具有较高的容错性,适合较大规模的批处理作业。由于是基于文件的,需要把数据写到文件里(即落盘,可联想Scheduler的ALL_EDGES_BLOCKING模式),它的容错性和稳定性会更好一些。
②基于Pipeline的Push Based Shuffle:比如Flink、Storm、Presto。它的特点是低延迟和高性能,但是因为shuffle数据没有存储下来(可联想Scheduler的ALL_EDGES_PIPELINED模式),如果是batch任务的话,就需要进行重跑恢复。
3)流/批Shuffle的差异
①Shuffle数据的生命周期
流作业的Shuffle数据与Task是绑定的,如果Task销毁了,那么Shuffle数据也没了。
批作业的Shuffle数据与Task是解耦的,如果上游的Task跑完了,会把数据写到文件里,即使上游Task资源释放(q掉了),上游Task产生的Shuffle的生命周期还在。
②Shuffle数据存储介质
流作业的生命周期比较短,为了实时性,Shuffle通常存储在内存中。
批作业因为数据量比较大以及容错的需求,一般存储在磁盘中。
③Shuffle的部署方式
流作业Shuffle服务和计算节点都部署在一起,可以减少网络开销,从而减少延迟。
批作业的Shuffle除了存在本地磁盘中,也可能采取远端存储(Remote Shuffle Service),因为本地机器可能宕机,整个作业就需要重跑了,而大作业重跑的代价很大。Remote Shuffle Service能够在远端将数据多存储几份,提高容错性。
4)统一化|Pluggable Shuffle Service
Flink对于流和批提供两种类型的Shuffle,虽然Streaming和Batch Shuffle在具体策略上存在一定的差异,但本质上都是为了对数据进行Re-Partition(重新分区),因此不同的Shuffle之间是存在一定共性的。
为了提供一套统一的Shuffle架构,Flink实现了Pluggable Shuffle Service框架,抽象出一些公共模块。既可以满足不同Shuffle在策略上的定制,同时还能避免在共性需求上进行重复开发。
①在Streaming和OLAP场景:为了性能的需要,通常使用基于Pipeline的Shuffle模式
②在Batch场景:通常使用基于Blocking的Shuffle模式
5)开源策略支持
对于Shuffle Service,Flink开源社区已经支持:
①Netty Shuffle Service:是Flink内置的Shuffle Service策略,支持pipeline和blocking。如果选择pipeline的Shuffle,数据是不落盘的,会通过Netty连接,直接把数据发到下游。
②Remote Shuffle Service:支持pipeline和blocking,但主要用于Batch的Blocking场景。pipeline如果走Remote Shuffle Service,需要把数据传到远端,相当于多了一层网络传输,性能反而会下降。
个人总结:
重点在于了解流/批Shuffle的差异和Pluggable Shuffle Service框架。