Spark的TorrentBroadcast:概念和原理
依据Spark 1.4.1源码
SparkContext的broadcast方法
注释
可以用SparkContext将一个变量广播到所有的executor上,使得所有executor都能获取这个变量代表的数据。
SparkContext对于broadcast方法的注释为:
/**
* Broadcast a read-only variable to the cluster, returning a
* [[org.apache.spark.broadcast.Broadcast]] object for reading it in distributed functions.
* The variable will be sent to each cluster only once.
*/
def broadcast[T: ClassTag](value: T): Broadcast[T]
"Broadcast a read-only variable to the cluster",指出了这个变量是只读的。只所以是只读的,我认为是因为每个executor的多个task之间共享一个被广播的变量,所以存在线程安全的问题,但是如果多个线程都“读”一个变量,仍然不能保证读操作是线程安全的,这里或许仍然需要Spark再说明一下。
(以下需要仔细区分“Broadcast变量”和"被broadcast的变量“)
"returning a Broadcast object for reading it in distributed functions",这句指出了Broadcast变量是在被分布执行的函数中使用。而被分布式执行的函数是被包含在Spark的task中分发到各个executor执行的,因此Broadcast变量作为被分发的task的一部分,需要随task一起经过序列化和反序列化的过程。
但是被broadcast的变量可能很大,而分发task的机制不是为了在集群中分发大量数据实现的,所以被broadcast的变量不宜随task一起简单地序列化和反序列化。TorrentBroadcast通过一些巧妙的方法,避免了被广播的数据随分布式执行的函数一起序列化。
总之,Broadcast变量是随task进行序列化反序列化的,而被broadcast的变量则通过另外的手段到达executor。
Broadcast变量实际是被广播变量的容器,使用时需要使用其value方法从中取出被广播的变量,而value方法是broadcast机制实现的关键之一。
调用关系
def broadcast[T: ClassTag](value: T): Broadcast[T] = {
assertNotStopped()
if (classOf[RDD[_]].isAssignableFrom(classTag[T].runtimeClass)) {
// This is a warning instead of an exception in order to avoid breaking user programs that
// might have created RDD broadcast variables but not used them:
logWarning("Can not directly broadcast RDDs; instead, call collect() and "
+ "broadcast the result (see SPARK-5063)")
}
val bc = env.broadcastManager.newBroadcast[T](value, isLocal)
val callSite = getCallSite
logInfo("Created broadcast " + bc.id + " from " + callSite.shortForm)
cleaner.foreach(_.registerBroadcastForCleanup(bc))
bc
}
首先判断一个被广播的是不是一个RDD,因为RDD是distributed,一个RDD变量并不包含有RDD中的数据集,也无法在每个executor直接获取整个RDD的数据(而是应该在driver端collect RDD的数据,然后再广播),所以Spark不支持广播RDD(但实际上可以做得到在广播RDD时,在每个executor上得到RDD中的所有数据,只是Spark没有去实现)。注意,即使广播了RDD也不会抛异常。
然后使用BroadcastManager的newBroadcast方法来生成一个Broadcast变量。而BroadcastManager会去调用BroadcastFactory的newBroadcast方法获取Broadcast变量。
Spark里的BroadcastFactor是可以配置的
val broadcastFactoryClass =
conf.get("spark.broadcast.factory", "org.apache.spark.broadcast.TorrentBroadcastFactory") broadcastFactory =
Class.forName(broadcastFactoryClass).newInstance.asInstanceOf[BroadcastFactory]
默认值即是TorrentBroadcastFactory, 它的newBroadcast方法只是new一个TorrentBroadcast对象。
override def newBroadcast[T: ClassTag](value_ : T, isLocal: Boolean, id: Long): Broadcast[T] = {
new TorrentBroadcast[T](value_, id)
}
所以TorrentBroadcast机制的核心就在TorrentBroadcast类。
TorrentBroadcast的原理
注释
/**
* A BitTorrent-like implementation of [[org.apache.spark.broadcast.Broadcast]].
*
* The mechanism is as follows:
*
* The driver divides the serialized object into small chunks and
* stores those chunks in the BlockManager of the driver.
*
* On each executor, the executor first attempts to fetch the object from its BlockManager. If
* it does not exist, it then uses remote fetches to fetch the small chunks from the driver and/or
* other executors if available. Once it gets the chunks, it puts the chunks in its own
* BlockManager, ready for other executors to fetch from.
*
* This prevents the driver from being the bottleneck in sending out multiple copies of the
* broadcast data (one per executor) as done by the [[org.apache.spark.broadcast.HttpBroadcast]].
*
* When initialized, TorrentBroadcast objects read SparkEnv.get.conf.
*
* @param obj object to broadcast
* @param id A unique identifier for the broadcast variable.
*/
这段注释说明了TorrentBroadcast实现的原理,其中关键的部分在于利用BlockManager的分布式结构来储存和获取数据块。
driver把序列化后的对象(即value)分块很多块,并且把这些块存到driver的BlockManager里。
在executor端,executor首先试图从自己的BlockManager中获取被broadcast变量的块,如果它不存在,就使用远程抓取从driver 以及/或者其它的
executor上获取这个块。当executor获取了一个块,它就把这个块放在自己的BlockManager里,以使得其它的executor可以抓取它。
这防止了被广播的数据只从driver端被拷贝,这样当要拷贝的次数很多的时候(每个executor都会拷贝一次),driver端容易成为瓶颈(就像HttpBroadcast所做的一样).
这段注释时的代词用得不准确,executor是没有专门的机制用于处理Broadcast变量的,所有的魔法都在Broadcast变量本身。可以这么描述:
driver端把数据分块,每个块做为一个block存进driver端的BlockManager,每个executor会试图获取所有的块,来组装成一个被broadcast的变量。“获取块”的方法是首先从executor自身的BlockManager中获取,如果自己的BlockManager中没有这个块,就从别的BlockManager中获取。这样最初的时候,driver是获取这些块的唯一的源,但是随着各个BlockManager从driver端获取了不同的块(TorrentBroadcast会有意避免各个executor以同样的顺序获取这些块),“块”的源就多了起来,每个executor就可能从多个源中的一个,包括driver和其它executor的BlockManager中获取块,这要就使得流量在整个集群中更均匀,而不是由driver作为唯一的源。
原理就是这样啦,但是TorrentBoradcast的实现有很多有意思的细节,可以仔细分析一下。
Spark的TorrentBroadcast:概念和原理的更多相关文章
- Storm概念、原理详解及其应用(一)BaseStorm
本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数“wordcount” ...
- 【转帖】Hadoop — HDFS的概念、原理及基本操作
Hadoop — HDFS的概念.原理及基本操作 https://www.cnblogs.com/swordfall/p/8709025.html 分类: Hadoop undefined 1. HD ...
- Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)
ORACLE集群概念和原理(二) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
- Java中的泛型 (上) - 基本概念和原理
本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...
- Java线程:概念与原理
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- 【转】Bloom Filter布隆过滤器的概念和原理
转自:http://blog.csdn.net/jiaomeng/article/details/1495500 之前看数学之美丽,里面有提到布隆过滤器的过滤垃圾邮件,感觉到何其的牛,竟然有这么高效的 ...
- Spark的TorrentBroadcast:实现
依据Spark 1.4版 序列化和反序列化 前边提到,TorrentBroadcast的关键就在于特殊的序列化和反序列化设置.1.1版的TorrentBroadcast实现了自己的readObject ...
- Java IO学习笔记:概念与原理
Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了 ...
- iptables实用教程(一):基本概念和原理
概述 iptables是linux自带的防火墙软件,用于配置IPv4数据包过滤或NAT(IPv6用ip6tables). 在linux上,防火墙其实是系统内核的一部分,基于Netfilter构架,基本 ...
随机推荐
- TCP/IP——内外网IP+子网掩码作用+PING(网络总结)
目录: 1.如何区分内网IP和外网IP? 保留字段 2.子网掩码是起什么作用的? 将DNS和IP异或,表示哪段起作用 3.ping到底起什么作用? ping本地.ping远程 下面针对上面三个问题分别 ...
- winform中文本框的一些案例
项目中经常看到在输入金额时,会加逗号,最近在复习正则表达式,就联系下,界面如下:
- mysql 强制走索引
查询是数据库技术中最常用的操作.查询操作的过程比较简单,首先从客户端发出查询的SQL语句,数据库服务端在接收到由客户端发来的SQL语句后, 执行这条SQL语句,然后将查询到的结果返回给客户端.虽然过程 ...
- PHP学习笔记 - 进阶篇(11)
PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...
- C# 数据结构--单链表
什么是单链表 这两天看到很多有关单链表的面试题,对单链表都不知道是啥的我.经过学习和整理来分享一下啥是单链表和单链表的一些基本使用方法.最后看些网上有关单链表的面试题代码实例. 啥是单链表? 单链表是 ...
- vim 跳转命令
基本跳转: hjkl:左下上右 HML:当前屏幕顶.中.底部 web:下一单词词首.下一单词词尾.前一单词词首 gg:文件首 G:文件末尾 ngg/nG:第n行 ta:移动到所在行之后第一个字符a ...
- IIS上的错误与解决方案
1.未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序. 解决方案:在IIS上打开该网站应用程序池-->高级设置-->启动32位程序-->选True
- 将Ecshop后台fckeditor升级更改为kindeditor 4.1.10编辑器
ecshop在win8部分电脑上,不管用任何浏览器,都打不开,即使升级到最新版本都不行,问题应该吃在fckeditor兼容上.fckeditor 很久未升级,换掉该编辑器是最佳方法 第一步:下载kin ...
- RCP学习笔记
一些model特征: Trimmed Window: 带最小化最大化的窗体 Perspective Stack: 装载Perspective的容器 Perspective:一个透视,可以直接包含Par ...
- MyEclipse的一些配置
1.配置默认编码 配置整个MyEclipse的默认编码 window--->Preferences-->General-->WorkSpace--->TextFileEncod ...