技术分享 | spark之广播变量设计和实现

spark 广播的方式

spark 历史上采用了两种广播的方式

一种是通过 Http 协议传输数据

一种是通过 Torrent 协议来传输数据

但是最新的 spark 版本中, http 的方式已经废弃了(pr 在此https://github.com/apache/spark/pull/10531), spark 是在 spark 1.1 版本中引入了 TorrentBroadcast, 此后就没有更新 HttpBroadcast 和相关文档了, spark2.0 的时候完全可以删除 HttpBroadcast 了, 之后统一把 TorrentBroadcast 作为广播变量的唯一实现方式。 但是代码没有写死, 还是保留了扩展性(BroadcastFactory 作为一个 trait, TorrentBroadcastFactory 只是一种实现方式, 符合依赖倒置原则, 依赖抽象,不依赖具体实现), 万一之后想到了更牛x 的实现方式, 可以方便的加上,但是我估计一时半会应该没有了。本着过时不讲的原则, 我们这里只说 TorrentBroadcast

大家可以到这里看下图

你能看到不同的数据块是来自不同的节点, 多个节点一起组成一个网络,在你下载的同时,你也在上传,所以说在享受别人提供的下载的同时,你也在贡献,最终所有人一起受益。

我们看下 BitTorrent 协议, wiki 定义

BitTorrent协议(简称BT,俗称比特洪流、BT下载)是用在对等网络中文件分享的网络协议程序。和点对点(point-to-point)的协议程序不同,它是用户群对用户群(peer-to-peer),而且用户越多,下载同一文件的人越多,下载该档案的速度越快。且下载后,继续维持上传的状态,就可以“分享”,成为其用户端节点下载的种子文件(.torrent),同时上传及下载。

具体感兴趣的可以看下这个论文

http://www.webpaas.com/usr/uploads/2015/01/52279564.pdf

关键的几个点

下载者要下载文件内容,需要先得到相应的种子文件,然后使用BT客户端软件进行下载。

提供下载的文件虚拟分成大小相等的块, 并把每个块的索引信息和Hash验证码写入种子文件中

有一个 Tracker 负责维护元信息, 所有的客户端都可以通过 Tracker 找到每个快离自己最近的其他下载者

下载时,BT客户端首先解析种子文件得到Tracker地址,然后连接Tracker服务器。Tracker服务器回应下载者的请求,提供下载者其他下载者(包括发布者)的IP。下载者再连接其他下载者,根据种子文件,两者分别告知对方自己已经有的块,然后交换对方所没有的数据。此时不需要其他服务器参与,分散了单个线路上的数据流量,因此减轻了服务器负担。

下载者每得到一个块,需要算出下载块的Hash验证码与种子文件中的对比,如果一样则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容准确性的问题。

针对以上的几个点, spark 是怎么做的, 我们看下:

TorrentBroadcast 底层使用的是 BlockManager, 下载每个数据块先要去 master 去获取 Block 所在的位置 (location)。

在把大变量写到广播变量的时候, 通过 ChunkedByteBufferOutputStream把输入的数据分成多个小块, zipWithIndex 中, 为每个小块加一个唯一标识, 形如 broadcast_broadcastId_pieceId。 作为BlockId, 存储在 BlockManager 中。 而且对每个小的数据块加上一个校验码。

BlockManagerMaster 作为 tracker 维护所有 Block块的元信息, 知道每个数据块所在的 executor和存储级别。 Broadcast 变量中维护属于自己的所有小块的 BlockId

通过 value 方法读取 Boradcast 变量的时候, 取出所有小块的 BlockId, 对于每个 BlockId, 通过BlockManagerMaster 获取了该BlockId的位置的集合, 随机化,位置集合被打乱, 优先找同主机的地址(这样可以走回环),然后从随机的地址集合按顺序取地址一个一个尝试去获取数据,因为随机化了地址,那么executor不只会从Driver去获取数据。分散了driver 上的压力。

取到 Block piece 后, 使用校验码进行校验,看看数据块有没有损坏, 如果没有损坏, 然后按照顺序拼在一起。

大家比较一下, 流程是不是差不多, 基本贯穿了 BitTorrent 的思想原理。

大家看下上面的图, 开始的时候, 大家都是通过 driver 拿数据, 但是一旦其他 executor 上有了数据块之后, 所有的 executor 都是有机会通过别的 executor 来获取数据块, 这样就分散了 driver 的压力。 套用一句话, 下载的 executor 越多, 下载的越快。

spark 广播变量的使用姿势

上面的一个小的 demo 就是把一个 数组通过 broadcast 的方式广播出去, 然后就可以在 task 里面使用数组变量了, 这个数组变量是驻留在 executor上的, 不用每次调度 task运行的时候都得传输一次 数组。

我们可以看到对于 broadcast 的使用, 无非就是 sc.broadcast 定义了一个 广播变量 和 broadcasted.value 使用广播变量的 value 方法,找到真正的数组。

spark context 初始化的时候, sparkEnv 中初始化了一个 broadcastManager,初始化方法里面, 现在默认使用的 TorrentBroadcastFactory, 调用 sc.broadcast 方法, 就会使用工厂模式创建一个 TorrentBroadcast,这时候就会调用写操作, 把数据分成小块写到 BlockManager 中, broadcasted 只是一个 TorrentBroadcast 类型的实例, 并没有数组数据, 这个实例只维护了数据的 元信息, 也就是一组BlockId 信息, 这个实例被序列化被传到 executor上, 在 executor 上调用这个实例的 value 方法,才会触发去 BlockManager 上读真正的数据。

原文发布于微信公众号 - 加米谷大数据(DtinoneBD)

原文发表时间:2018-01-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏自动化测试实战

flask第二十二篇——模板【4】过滤器

2226
来自专栏Vamei实验室

被解放的姜戈03 所谓伊人

在之前的程序中,我们直接生成一个字符串,作为http回复,返回给客户端。这一过程中使用了django.http.HttpResponse()。 在这样的一种回复...

2108
来自专栏ChaMd5安全团队

360春秋杯3道web题的简单分析

360春秋杯3道web题的简单分析 From ChaMd5安全团队核心成员 pcat&香香 where is my cat 这题一开始很坑的,存在着/.git/...

4598
来自专栏java架构师

BAT美团滴滴java面试大纲(带答案版)之三:多线程synchronized

继续面试大纲系列文章。   从这一篇开始,我们进入ava编程中的一个重要领域---多线程!多线程就像武学中对的吸星大法,理解透了用好了可以得道成仙,俯瞰芸芸众生...

30510
来自专栏Jimoer

Java设计模式学习记录-状态模式

状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题。状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象...

1391
来自专栏FreeBuf

一个二进制POC的诞生之旅CVE-2018-0802

背景 在潜伏17年的“噩梦公式”漏洞(CVE-2017-11882)被曝光修补之后,之前的漏洞程序EQNEDT32.EXE在windows 10系统下仍然没有开...

2819
来自专栏DeveWork

(2013.09更新)最新W3School 离线完整版CHM 电子书下载

最近一直很忙,有网友在《(2013.07)最新W3School 离线完整版CHM 电子书下载》一文评论说W3School 已经有更新了,叫我也更新电子书。忙到现...

2097
来自专栏FreeBuf

隐藏在证书文件中的PowerShell(一)

最近,NVISO实验室分析人员开发了某种YARA规则,利用它发现了多种恶意证书文件(.crt),这些证书文件中包含的并不是真正的认证证书,而是一个恶意的Powe...

1703
来自专栏向治洪

蘑菇街Android组件与插件化

插件化的基石 -- apk动态加载 随着我街业务的蓬勃发展,产品和运营随时上新功能新活动的需求越来越强烈,经常可以听到“有个功能我想周x上,行不行”。行么?...

21110
来自专栏mwangblog

机器语言与汇编语言

983

扫码关注云+社区

领取腾讯云代金券