大数据Shuffle原理与实践|青训营笔记

148 阅读4分钟

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

  • Shuffle概述
    • MapReduce
      • Map
        • 在单机上对一小块数据进行计算的过程
      • Shuffle
        • map的基础上,进行数据移动,为后续的reduce阶段做准备
      • Reduce
        • 对移动后的数据进行处理,依然是在单机上处理一小份数据
    • Shuffle对性能的影响
      • MxR次网络连接
      • 大量的数据移动
      • 数据丢失风险
      • 可能存在大量的排序操作
      • 大量的数据序列化、反序列化操作
      • 数据压缩
    • 总结
      • 在大数据场景下,数据Shuffle表示了不同分区数据交换的过程,不同的Shuffle策略性能差异较大,目前在各个引擎中Shuffle都是优化的重点,在Spark框架中,Shuffle是支持Spark进行大规模复杂数据处理的基石
  • Shuffle算子
    • Spark中会产生Shuffle的算子大概可以分为4类
      • Repartition
        • coalesce
        • repartition
      • ByKey
        • groupByKey
        • reduceByKey
        • aggregateByKey
        • combineByKey
        • sortByKey
        • sortBy
      • Join
        • cogroup
        • join
        • leftOuterJoin
        • intersection
        • subtract
        • subtractByKey
      • Distinct
        • distinct
      • 当出现一个宽依赖时,Spark将其划分为两个stage,两个stage间会产生Shuffle操作
    • Shuffle Dependency构造
      • Partitioner
        • 负责将key映射成一个数字,这个数字就代表一个分区
        • HashPartitioner
      • Aggregator
        • 提前做一部分reduce
  • Shuffle过程
    • Hash Shuffle
      • 写数据
        • 每个partition会映射到一个独立的文件
      • 写数据优化
        • 每个partition会映射到一个文件片段
    • Sort Shuffle
      • 写数据
        • 每个task生成一个包含所有partition数据的文件
    • 读数据
      • 每个reduce task分别获取所有map task生成的属于自己的片段
    • Shuffle过程的触发流程
      • Collect Action->SubmitJob->GetDependencies->RegisterShuffle
    • Shuffle Handle的创建
      • Register Shuffle做的最重要的事情是根据不同条件创建不同的Shuffle Handle
    • Writer实现
      • BypassMergeShuffleWriter
        • 不需要排序,节省时间
        • 写操作的时候会打开大量文件
        • 类似Hash Shuffle
      • UnsafeShuffleWriter
        • 使用类似内存页储存序列化数据
        • 数据写入后不再反序列化
      • SortShuffleWriter
        • 支持combine
        • 需要combine时,使用PartitionedAppendOnlyMap,本质是个HashTable
        • 不需要combine时,使用partitionedPairBuffer,本质是个array
    • Reader实现
      • 网络时序图
        • 使用基于netty的网络通信框架
        • 位置信息记录在MapOutputTracker
        • 主要会发送两种类型的请求
          • OpenBlocks请求
          • Chunk请求或者Stream请求
      • ShuffleBlockFetchIterator
        • 区分localremote节省网络消耗
        • 防止OOM
          • maxBytesFlight
          • maxReqsInFlight
          • maxBlocksInFlightPerAddress
          • maxReqSizeShuffleToMem
          • maxAttemptsOnNettyOOM
      • Externel Shuffle Service
        • ESS作为一个存在于每个节点上的agent为所有Shuffle Reader提供服务,从而优化了Spark作业的资源利用率,MapTask在运行结束后可以正常退出
      • 优化
        • Zero Copy
          • DMA(Direct Memory Access)
            • 直接存储器存取,是指外部设备不通过CPU而直接与系统内存交换数据的接口技术
          • sendfile
          • sendfile+DMA gather copy
          • 可以用于合并文件以及发送文件时
        • Netty Zero Copy
          • 可堆外内存,避免JVM堆内存到堆外内存的数据拷贝
          • CompositeByteBuf、Unpooled.wrappedBuffer、ByteBuf.slice,可以合并、包装、切分数组,避免发生内存拷贝
          • Netty使用FileRegion实现文件传输,FileRegion底层封装了FileChannel#transferTo()方法,可以将文件缓冲区的数据直接传输到目标Channel,避免内核缓冲区和用户缓冲区之间的数据拷贝
        • 避免Shuffle
          • 使用broadcast代替join
        • 使用可以map-side预聚合的算子
        • 参数优化
        • Shuffle倾斜优化
          • 倾斜影响
            • 作业运行时间变长
            • Task OOM导致作业失败
          • 提高并行度
            • 优点:足够简单
            • 缺点:只缓解、不根治
          • Spark AQE Skew Join
            • AQE根据Shuffle文件统计数据自动检测倾斜数据,将那些倾斜的分区打散成小的子分区,然后各自进行join
    • 常见问题
      • 数据存储在本地磁盘,没有备份
      • IO并发:大量RPC请求(MxR)
      • IO吞吐:随机读、写放大(3X)
      • GC频繁,影响NodeManager- Push Shuffle
  • Magnet
    • Spark driver组件,协调整体的Shuffle操作
    • map任务的Shuffle write过程完成后,增加了一个额外的操作push-merge,将数据复制一份推到远程Shuffle服务上
    • magnet shuffle service是一个强化版的ESS,将隶属于同一个Shuffle partitionblock,会在远程传输到magnet后被merge到一个文件中
    • reduce任务从magnet shuffle service接收合并好的Shuffle数据
    • 实现细节
      • bitmap
        • 存储已mergemapper id,防止重复merge
      • position offset
        • 如果本次block没有正常merge,可以恢复到上一个block的位置
      • currentMapId
        • 标识当前正在appendblock,保证不同mapperblock能依次append
    • 本质上,维护了两份的Shuffle数据的副本
  • Cloud Shuffle Service
    • IO聚合
      • 所有mapper的同一个partition数据都远程写道同一个文件(或者多个文件)
    • 备份
      • HDFS太重,使用双磁盘副本
    • 写入速度
      • 主从InMemory副本,异步刷盘,极小的失败几率去换取高速写入速度