Spark Broadcast中writeBlocks为啥put两次?

本文详细介绍了Spark的Broadcast机制,包括广播变量的作用、如何实现广播、TorrentBroadcast的工作原理,以及putSingle与putBytes的区别。Broadcast允许在每个节点上缓存只读变量,提高效率。putSingle仅在Driver端缓存,而putBytes将数据分块并通知BlockManagerMaster,使得Executor可以获取。
摘要由CSDN通过智能技术生成


有兄弟在看代码的时候发现一个现象,在TorrentBroadcast广播实现类中为啥wirteBlocks方法中会向BlockManager put两次值呢?
现象如下所示:
在这里插入图片描述

要解释上面的问题,我需要从三个方面做详细描述:

  1. 解释什么是broadcast;
  2. 剖析putSingle与putBytes;
  3. 跑个例子来总结一下具体现象;

1 broadcast

什么是broadcast?
顾名思义,broadcast 就是将数据从一个节点发送到其他各个节点上去。这样的场景很多,比如 driver 上有一张表,其他节点上运行的 task 需要 lookup 这张表,那么 driver 可以先把这张表 copy 到这些节点,这样 task 就可以在本地查表了。
官方定义:

Broadcast variables allow the programmer to keep a read-only variable cached on each machine rather than shipping a copy of it with tasks. They can be used, for example, to give every node a copy of a large input dataset in an efficient manner. Spark also attempts to distribute broadcast variables using efficient broadcast algorithms to reduce communication cost.

先回答下面几个问题就会明白什么是broadcast:
1、在spark什么东西能广播呢?换句话说广播有什么用呢?

Spark中因为算子中的真正逻辑是发送到Executor中去运行的,所以当Executor中需要引用外部变量时,需要使用广播变量。

变量参数可以被广播,比如FileSourceScanExec在构造inputRDD时调用到OrcFileFormat#buildReaderWithPartitionValues内部就会将HadoopConf进行广播,如下图所示:

在这里插入图片描述
– 在提交任务之前会将序列化好的***task可以进行广播***,DAGScheduler#submitMissingTasks,如下图所示:
在这里插入图片描述
2、broadcast 到节点而不是 broadcast 到每个 task?
因为每个 task 是一个线程,而且同在一个进程运行 tasks 都属于同一个 application。因此每个节点(executor)上放一份就可以被所有 task 共享。
3、怎么实现 broadcast?
分发task时先分发的是data的元数据 ? 当调用val bdata= sc.broadcast(data)时就把 data 写入文件夹(Driver 先建一个本地文件夹用以存放需要 broadcast 的 data),同时写入 driver 自己的 blockManger 中(StorageLevel 为MEMORY_AND_DISK**),获得一个 blockId,类型为 BroadcastBlockId。当调用rdd.transformation(func)时,如果 func 用到了 data,那么 driver submitTask() 的时候会将 data 一同 func 进行序列化得到 serialized task,注意序列化的时候不会序列化bdata中包含的 data。

什么时候传送真正的 data?在 executor 反序列化 task 的时候,会同时反序列化 task 中的 bdata 对象,这时候会调用 bdata 的 readObject() 方法。该方法先去本地 blockManager 那里询问 bdata 的 data 在不在 blockManager 里面,如果不在就使用下面TorrentBroadcast** fetch 方式之一去将 data fetch 过来。得到 data 后,将其存放到 blockManager 里面,这样后面运行的 task 如果需要 bdata 就不需要再去 fetch data 了。如果在,就直接拿来用了。

4、TorrentBroadcast是个啥?

TorrentBroadcast,这个类似于大家常用的BitTorrent 技术,基本思想就是将 data 分块成 data blocks,然后假设有 executor fetch 到了一些 data blocks,那么这个 executor 就可以被当作 data server 了,随着 fetch 的 executor 越来越多,有更多的 data server 加入,data 就很快能传播到全部的 executor 那里去了。

在 TorrentBroadcast 里面使用blockManager.getRemote() => NIO ConnectionManager 传数据的方法来传递。
在这里插入图片描述
行了上面哔哔了那么多,很多兄弟肯定看得概念性的东西难受,不多说了,咱们撸一把代码,来点儿真实的,看看细节是如何实现的。

2 剖析putSingle与putBytes

在这里插入图片描述
此方法的来源是什么?当然是Driver端发起,以提交任务为例子来看一下主线流程:
driver-executor-broadcast

Driver端:先把 data 序列化到 byteArray,然后切割成 BLOCK_SIZE(由 spark.broadcast.blockSize = 4MB 设置)大小的 data block,完成分块切割后,就将分块信息(称为 meta 信息)存放到 driver 自己的 blockManager 里面,StorageLevel 为内存+磁盘,同时会通知 driver 自己的 blockManagerMaster 说 meta 信息已经存放好。

blockManager.putSingle(broadcastId, value, MEMORY_AND_DISK, tellMaster = false)
blockManager.putBytes(pieceId, bytes, MEMORY_AND_DISK_SER, tellMaster = true)

代码中tellMaster=true则会通知blockManagerMaster。通知 blockManagerMaster 这一步很重要,因为 blockManagerMaster 可以被 driver 和所有 executor 访问到,信息被存放到 blockManagerMaster 就变成了全局信息。

之后将每个分块 data block 存放到

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值