十月
简直是醍醐罐体!斯巴克公司的例子我愿称之为神比喻
2022-03-30
1
淡C
这是我极客时间收获最大的一篇专栏,自己作为一个刚入门大数据的实习生,在学习大数据的过程想要选择一个组件进行深耕,很高兴遇到这篇专栏,这篇专栏每一节我都会看个几遍,每次看都有不同的收获,代码部分我每次跟着一起敲(虽然streaming有些还没运行出来),希望好好吸收这边专栏然后看spark性能调优,到时候的自己也可以说自己熟悉掌握spark这个组件了吧
2022-06-08
5
Ebdaoli
吴老师的spark讲的太好了,在项目中碰到spark 调优相关的知识后,去知乎喵到了吴老师一篇文章,感觉就是我想要的,没想到无意中在极客时间又相遇了,果断把入门和性能调优两篇专栏买来学习。
学习过程中看到评论区各种有意思的东西,真的视野大开,从头撸一遍之后在项目中就很少会再无厘头的google 、百度了,真心感谢!
最后可以提一个小建议吗?可以在相关的图片下加上对应的源码吗,希望能跟着吴老师学一遍源码,有了源码的知识,感觉对于spark才算真正入门了
作者回复:感谢老弟的认可!很好的建议,后面抽空把跟原理对应的源码附上~ 不过课程的安排,并不是按照源码本来的组织进行的,所以即便贴上源码,也难免混乱,我在考虑,后面要不要找个机会,系统地讲讲源码,主要是没有想好怎么讲才能更有趣,而不会让大家觉得枯燥、乏味
2022-02-24
哇塞
牛逼 例子很形象啊!!!
作者回复:哈哈,老弟喜欢就好~
2021-12-08
Geek_5d2c69
感谢吴老师!new grad刚毕业 入职了湾区一家公司,开始onboarding的第一个project就是用pyspark做offline ML model然后转线上。遇到了很多spark上面的问题和code bug,希望上这门课可以帮我更加熟悉spark!
作者回复:首先恭喜老弟~ 希望这门课对老弟的职业发展有所帮助,一起加油~
2021-11-03
1
路人丁
置顶
老师好!讲解很精彩!
为了帮助大家理解,还是要说说 standalone 模式下的 主从选举过程,三个节点怎么互相找到并选出主从。另外,standalone 模式下的 master 和 worker,与前面进程模型里说的 Driver 和 executor,二组之间的对应关系,也要讲讲。只要能简单串起来就可以了。让大家获得一个即便简单、但却完成的理解模型。
作者回复:感谢老弟,问题提得很好~
先说说选主,这个其实比较简单,Standalone部署模式下,Master与Worker角色,这个是我们通过配置文件,事先配置好的,所以说,哪台是Master,哪台是Worker,这个配置文件里面都有。在Standalone部署下,先启动Master,然后启动Worker,由于配置中有Master的连接地址,所以Worker启动的时候,会自动去连接Master,然后双方建立心跳机制,随后集群进入ready状态。
接下来说Master、Worker与Driver、Executors的关系。首先,这4个“家伙”,都是JVM进程。不过呢,他们的定位和角色,是完全不一样的。Master、Worker用来做资源的调度与分配,你可以这样理解,这两个家伙,只负责维护集群中可用硬件资源的状态。换句话说,Worker记录着每个计算节点可用CPU cores、可用内存,等等。而Master从Worker收集并汇总所有集群中节点的可用计算资源。
Driver和Executors的角色,那就纯是Spark应用级别的进程了。这个咱们课程有介绍,就不赘述了。Driver、Executors的计算资源,全部来自于Master的调度。一般来说,Driver会占用Master所在节点的资源;而Executors一般占用Worker所在节点的计算资源。一旦Driver、Executors从Master、Worker那里申请到资源之后,Driver、Executors就不再“鸟”Master和Worker了,因为资源已经到手了,后续就是任务调度的范畴。任务调度课程中也有详细的介绍,老弟可以关注下~
大概其就是这么些关系,不知道对老弟是否有所帮助~
2021-11-08
20
bian
这章真的是将执行流程讲的棒极了
作者回复:喜欢就好哈~
2021-10-22
2
Geek_2dfa9a
MemoryStore这块涉及大量的nio,看得我头皮发麻。简单点讲,里面有个核心的常量LinkedHashMap,作为LRU缓存,存储所有Block。
putBytes()这个方法主要用来写数据,方法入参分别是blockId(数据块的标识),size(数据块长度),memoryMode(存放在堆上还是堆外),
_bytes(具体内存分配的闭包),具体实现逻辑是,先检查blockId对应的数据块是否已缓存,然后通过memoryManager(1.6以前是StaticMemoryManager,
不能支持堆外内存,1.6以后默认UnifiedMemoryManager,可以通过spark.memory.useLegacyMode指定)确认内存是否够缓存,在后通过
_bytes把数据拷贝到DirectByteBuffer,如果数据本来就在堆外的话就省略这个逻辑,最后把blockId作为key,ChunkedByteBuffer
(就是一个DirectByteBuffer数组,里面是要缓存的数据)作为SerializedMemoryEntry存到LinkedHashMap里,这里注意,
为了保证线程安全,LinkedHashMap需要加锁,这里是一个细粒度锁加到少部分代码上减少开销。
上面的是缓存序列化块的逻辑,putIterator既可以缓存序列化的值(堆内/堆外),也可以直接缓存对象(只能存放在堆内),具体逻辑和LinkedHashMap
不太相关了,篇幅有限就不分析了。
作为一个LRU缓存,Spark肯定还要有一个容量满后的清除操作,触发点在put时校验空间是否足够,具体逻辑在evictBlocksToFreeSpace,
入参有三个blockId(失效后需要缓存的block),space(需要缓存的block的长度),memoryMode。缓存失效这块影响比较大,需要加两个锁,
在外层给memoryManager加锁,之后再给LinkedHashMap加锁,因为put的时候memoryManager没加锁,如果正在put的时候清理缓存会发生数据竞争,
因此LinkedHashMap也需要加锁,保证同一时间LinkedHashMap只能有一个操作,之后的操作就简单了,拿到LinkedHashMap的迭代器,
从第一个Entry开始判断,如果可以失效()的话就记录下blockId并在blockInfoManager针对blockId加锁,
一直到释放的内存达到space。接下来判断如果清理这些失效的block能否拿到需要的space,不能的话就返回0,表示不能清理出所需空间,如果能拿到的话,
就开始dropBlock(),有些block可能同时在磁盘和内存缓存,如果只清除一处的话blockInfo无需删除解锁即可,如果磁盘和内存都没有了则需删除blockInfo,
如果清理过程中发生异常,则把还没清理的blockInfo解锁(这块逻辑放在finally里,并且作为一个编程技巧注释出来)。
另外有一点值得注意,Spark为了避免MaxDirectMemorySize的限制,使用了反射拿到了DirectByteBuffer的私有构造方法
private DirectByteBuffer(long addr, int cap),这样就避开了allocateDirect方法里面Bits.reserveMemory的限制。
作者回复:分析得很透彻,memoryStore缓存数据、evict数据的过程说得很清楚~ 赞👍!!!
2021-10-12
10
Joey
说起来spark太有感觉了,毕业后的第一家公司就是负责spark、hbase相关的开发;后来跳槽了就主要做实时kafka、flink这一块了,已经两年没写过spark相关的代码了。再来重温一下spark,重温当时倔强的自己哈哈...
作者回复:欢迎归来~
2021-09-30
1
Jordan·李威
总公司和分公司的工作任务和人力资源分配调度的例子太匹配了。
作者回复:喜欢就好~
2021-09-20
4
编辑推荐
讲师的其他课程
包含这门课的学习路径
机器学习工程师
13门课程 37.6w人学习
看过的人还看了