第六次课堂记录|青训营笔记

112 阅读3分钟

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

大数据Shuffle原理与实践

一、Shuffle概述

1.1 MapReduce概述

image.png 在开源实现的MapReduce中,存在Map,Shuffle,Reduce三个阶段

1.2 Shuffle阶段

reduce阶段,堆移动后的数据进行处理,依然是在单机上处理一小份数据。

1.3 Reduce阶段

reduce阶段,对移动后的数据进行处理,依然是在单机上处理一小份数据。

1.4 为什么shuffle对性能非常重要

  • M * R次网络连接
  • 大量的数据移动
  • 数据丢失风险
  • 可能存在大量的排序操作
  • 大量的数据序列化、反序列化操作
  • 数据压缩

总结

在大数据场景下,数据shuffle表示了不同分区数据交换的过程,不同的shuffle策略性能差异较大

目前在各个引擎中Shuufle都是优化的重点,在spark框架中,shuffle是支撑spark进行大规模复杂数据处理的基石。

二、Shuffle算子

2.1 Shuffle算子分类

image.png

Shuffle算子应用

  • Spark源码中RDD的单元测试
  • Spark源码中PairRDDFunctions的单元测试

2.2 Spark中对Shuffle的抽象 宽依赖、窄依赖

image.png

算子内部的依赖关系

image.png

三、Shuffle过程

3.1 Shuffle实现的发展历程

image.png

3.2 Hash Shuffle -写数据

每个partition会映射到一个独立的文件

image.png

Hash Shuffle -写数据优化

每个partition会映射到一个文件片段

image.png

Short Shuffle: 写数据 每个task生成一个包含所有partition数据的文件

image.png

3.3 Shuffle -读数据

每个reduce task分别获取所有map task生成的属于自己的片段

image.png

3.4 Shuffle过程的触发流程

Collect Action -> SubmitJob -> GetDependecies -> RegisterShuffle

3.5 Shuffle Handle 的创建

Register Shuffle时做的最重要的事情时根据不同条件创建不同的Shuffle Handle

image.png

3.6 Shuffle Handle 与 Shuffle Writer的对应关系

image.png

3.7 Writer实现

BypassMergeShuffleWriter

  • 不需要排序,节省时间
  • 写操作的时候会打开大量文件
  • 类似于Hash Shuffle

image.png

UnsafeShuffleWriter

  • 使用类似于内存页储存序列化数据
  • 数据写入后不再反序列化

image.png

  • 只根据partition排序Long Array
  • 数据不移动

image.png

ShortShuffleWriter

  • 支持combine
  • 需要combine时,使用PartitionedAppendOnlyMap,本质是一个HashTable
  • 不需要combine时PartitionedPariBuffer本质时一个array

image.png

3.8 Reader实现

网络时序图

  • 使用基于netty的网络通信框架
  • 位置信息记录在MapOutputTracker中
  • 主要会发送两种类型的请求 OpenBlocks请求 Chunk请求或Stream请求

image.png

ShuffleBlockFetchIterator

image.png

  • 区分local和remote节省网络消耗
  • 防止OOM

External Shuffle Service ESS作为一个存在于每个节点上的agent为所有Shuffle Reader提供服务,从而优化了Spark作业的资源利用率,MapTask在运行结束后可以正常退出

image.png

3.9 Shuffle优化使用的技术

Zero Copy

DMA(Direct Memory Access):直接存储器存取,是指外部设备不通过CPU而直接与系统内存交换数据的接口技术

image.png

Netty Zero Copy

  • 可堆外内存,避免JVM堆内存到堆外内存的数据拷贝
  • CompositeByteBuf、Unpooled.wrappedBuffer、ByteBuf.slice,可以合并、包装、切分数组、避免发生内存拷贝
  • Netty使用FileRegion实现文件传输,FileRegion底层封装了FileChannedl#TransferTo()方法,可以将文件缓冲区的数据直接传输到目标Channel,避免内核缓冲区和用户态缓冲区之间的数据拷贝。

3.10 常见问题

  • 数据存储在本地磁盘无备份
  • IO并发:大量RPC请求
  • IO吞吐:随机读,写放大
  • GC频繁,影响NodeManager

3.11 Shuffle优化

使用broadcast替代join

使用可以map-side预聚合的算子

image.png

3.12 Shuffle参数优化

image.png

3.13 Shuffle倾斜优化

倾斜影响

  • 作业运行时间长
  • Task OOM导致作业失败