一行Spark代码的诞生记(深度剖析Spark架构)
大家好,我是一行Spark代码,我叫小小小蕉,不知道为毛,我爸爸大蕉和我妈妈大大蕉把我生的又瘦又长。长这样。
val sssjiao = new SparkContext(new SparkConf().setAppName("sssjiao").setMaster("yarn-cluster")).parallelize(Array(""));
我真的,不知道怎么说,好长好长啊。。总有小伙伴对着我说:
问君何不乘风起 扶摇直上九万里。
说出来不怕吓着你,其实我一个字都看不懂。
作为一行普通的代码,我也开始思考码生的三大问题,我是谁,我从哪里来,要到哪里去。
我从我从哪里来,开始讲我的故事吧。
我从哪里来?
这有什么好说的,出自我爸爸大大蕉之手,就酱。
本文终。
当当当,你以为就这样结束了吗?不可能的。我长得这么细这么长,其实我是由三个部分组成的。分别是SparkConf,SparkContext,RDD[String],从代码层面来说,就是定义了一个SparkConf的配置,来生成一个SparkContext上下文,然后用这个SparkContext来对数组进行序列化,我就被产生出来啦。
但是我今天不仅仅是想介绍这么浅层的来源,毕竟爸比妈咪生得我那么辛苦是吧?
(要开始Spark on yarn的深度剖析了)
大大蕉:yarn兄,我要生一个儿子,oh不我要产生一个Spark任务了,能帮忙拨 点行政资源不?
yarn :啥玩意,你想干啥?要尊贵的cluster模式还是平民的client模式?
大大蕉:这两个有啥差别?我头胎。
yarn :client就你用你自己粗糙的Driver,cluster模式就我给你分配一个高配置又漂亮的Driver。
大大蕉:那行,给我来个尊贵的cluster吧。
yarn :等着。
yarn :歪,ResourceManager吗(管资源的,下面简称RM)?你那边不是在管资源吗?咱这有货吗?赶紧给我空运一个高配的机器,嗯对,用来跑Driver和ApplicationMaster的,嗯对对对,我们这边有人快生了。对,急急急,这辈子就这要一次最急。
RM :知道了(一脸嫌弃懒洋洋)。
过了0.00001ms,对于CPU来说过了好久了
RM :NodeManage(每台机器的管家,下面简称NM),歪,根据记录你那里的配置恰好够用,你那里的Container1容器我征用了,就这样。
NM :我R。。。
RM :yarn老哥,给你那个名字为container-1的容器吧,他的地址和配置信息(CPU,内存)在这,你收好了。
yarn的最小分配单位为Container
yarn :好的,非常感谢,后面有事情还麻烦你。
yarn :大大蕉吗?Container拿到了,就是Container1,自己去看看怎么生吧。
大大蕉:好的。掰。
大大蕉:(自言自语)根据说明书,先启动一个ApplicationMaster,名字叫做sssjiao,用来管理这个Job和Container。再先启动一个Driver,来管理DAGScheduler(有向无环图管理)和TaskScheduler(任务调度管理),BlockManagerMaster(数据块管理的Master)。咦,那我去哪跑任务呢?还差一些Worker工作站啊。
Spark将一个大的任务拆成一个有向无环图,来表示依赖关系。
大大蕉:歪。yarn吗?嗯是我。我这好像还差点东西啊。。我还需要一些Container来做我的Worker啊,不然我儿子生完往哪放啊?
yarn :知道了知道了,不会一次说完吗?真讨厌。
大大蕉:我。。。我™也不知道需要这个啊。
yarn :歪。RM吗?嗯又是我。我需要一批Container。嗯对高配那种。对,急急急,这辈子就这一次最急。
RM :知道了。(不耐烦)
RM :NM-A,NM-B,NM-C,NM-D,你们几个的资源我都征用了。
NM界一脸懵逼,都感觉自己被抢劫了。。
RM :歪,yarn老哥吗?资源都ok了。ContainerA,ContainerB,ContainerC,ContainerD。
yarn :好嘞。
yarn :大大蕉。资源拿到了,信息我装在信封里了,你拿好吧。
大大蕉:嗯,我还想问一下,后面的(电话那头传来嘟嘟嘟挂断的声音)。步、骤、要、怎、么、走。算了还是自己看说明书吧。
首先在Container里面启动一个或者多个Executor,然后启动一些jvm和BlockManager。好了现在Driver、Master和Worker都有了,完事具备,只欠东西南北风了。
到这里,SparkContext算是初始化完了。
大大蕉抓着头发,一脸茫然地看着面前这堆玩意,要怎么玩。。。
诶,再看看说明书吧,看看有没有说怎么玩。(大蕉自言自语道)
突然空气中响起了旁白:切分、分配、切分、分配。
对!这个job可以先用DAGScheduler进行stage切分。
切分完然后用TaskScheduler进行任务调度分配。所以一个Job就被切分成很多个stage,封装成很多个TaskSet,然后每次Executor来请求任务的时候,就给他们分配一个,所有的Executor执行完成后又向TaskScheduler报告进度。
Task失败了?报告TaskScheduler。从头开始重新跑。
Task太慢了?TaskSchduler找多一个Executor并行跑,谁先跑完就用谁(好残忍)
Stage挂了?TaskScheduler报告DAGScheduler重新进行Stage拆分,看看是从当前开始重跑还是要用从父stage重跑。
好了到现在,小小小蕉我,还没有被产生出来。。
然后SparkContext就我的前辈Array("")进行序列化,然后根据key,也就是每个字符串进行分区,分区完之后把分区信息和对应的Executor保存起来。然后呢根据分区信息把数据发送到Executor那边去。所以我的本体RDD是在Driver的,但是我被分成很多份很小份很小份放在Exector里面的。
我是谁?
我是一个RDD。全名 RDD(Reilient Distributed DataSets)弹性分布式数据集。
我要到哪里去?
我后面的任务就是进行具体程序的执行,一个job一个job,一个stage一个stage。
这里再深入,就是从编译完的.class文件,用JVM的ClassLoader类加载器,加载完变成一个真正的类,然后再又JVM编译成机器码,在堆里开辟一点内存初始化一个String对象,在栈里开辟一点内存初始化一个指针。
然而跑完之后呢,我又将何去何从呢?
然后10M以下的就直接放在结果返回给TaskScheduler啦。
如果在10M以上的,就放到某个BlockManage,只返回BlockId了。
通知TaskScheduler说跑完啦。
然后TaskScheduler就通知DAGScheduler说跑完啦。
然后DAGScheduler就通知SparkContext说跑完啦。
然后SparkContext就通知Driver跑完啦。
然后SparkContext就准备要stop了。
大大蕉 :歪,yarn吗?我儿子生完了,资源都还给你把。
yarn :好。
yarn :歪。RM吗?刚刚申请的资源用完了,你把它们标记为可用把。
虚拟机 :这行又瘦又长的叫sssjiao的代码是谁啊。。好像被人丢在这了,诶当垃圾回收了吧,然后就给小小小蕉脸上盖上了一个待回收的印子♻️。
过了不久,小小小蕉就被GC(Garbage Collection)回收了,但是它脸上洋溢着笑容,它,是快乐的。
这就是小小小蕉快快乐乐的一生。
- 零基础学编程012:画出复利曲线图
- OpenAI发布高度优化的GPU计算内核—块稀疏GPU内核
- SQL SERVER 原来还可以这样玩 FOR XML PATH
- 零基础学编程011:复利数据表问题(总结)
- 一个小程序引发的思考
- 深入内核:DUMP Block的数据读取与脏数据写入影响
- 零基础学编程010:最终可以输出完整的复利数据表了
- 在C#使用文件监控对象FileSystemWatcher 实现数据同步
- 零基础学编程018:条件语句
- 零基础学编程022:函数的世界
- 帝国cms如何调用指定id的文章到首页?
- C 语言 static、extern与指针函数介绍
- 2017最流行的十大Python库
- 笔记:mysql升序排列asc,降序排列desc
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解Android Service 使用时的注意事项
- Android自定义View实现QQ运动积分转盘抽奖功能
- 请简述Spring JDBC是如何进行配置的
- Java高频面试题 -- 静态
- 2020Java核心面试题--基础题
- 一日一技:在网页上如何获取鼠标当前指向的元素
- B树和B+树
- 根据CCDS数据库信息拿到全部外显子坐标
- 查找算法其实不简单
- 一日一技:如何防止 Homebrew 自动升级和自动清理过期程序
- 吐血整理--史上最全排序算法Python实现
- 2020数据库最新面试题常考汇总
- [剑指Offer]面试题25: 合并两个排序的链表
- 环形链表
- 二十年前做科研你只需要检测一些基因在一些癌症细胞系表达量情况即可