本文零散的记录一下自己在学习Spark时候的随笔感悟。
Spark能够进行分布式运算的基础来自于以下几点:
- Spark高性能一定程度上来自于server/driver端采用的Actor异步并发模型。在任务级别上,Spark采用的是多线程模型,而不同于Hadoop MR采用的是多进程模型;
这里的多进程和多线程是指同一个节点上多个任务的运行模式,无论是MapReduce和Spark整体上看都是多进程的:MR应用程序是由多个独立的Task进程组成;Spark应用程序的运行环境是由多个独立的Executor进程构建的临时资源池构成的
多进程模型便于控制每个任务的占用资源,但是会消耗更多的启动时间,可以看看58DP上运行一个JOB,日志记录会很迟钝。而多线程模型适合处理低延迟类型作业。也就是说Spark通节点的上的任务以多线程的方式运行在一个JVM进程中。
可带来以下好处:
任务启动速度快,与之相反的是MapReduce Task进程的慢启动速度,通常需要1s左右;
同节点上所有任务运行在一个进程中,有利于共享内存。这非常适合内存密集型任务,尤其对于那些需要加载大量词典的应用程序,可大大节省内存。
同节点上所有任务可运行在一个JVM进程(Executor)中,且Executor所占资源可连续被多批任务使用,不会在运行部分任务后释放掉,这避免了每个任务重复申请资源带来的时间开销,对于任务数目非常多的应用,可大大降低运行时间。与之对比的是MapReduce中的Task:每个Task单独申请资源,用完后马上释放,不能被其他任务重用,尽管1.0支持JVM重用在一定程度上弥补了该问题,但2.0尚未支持该功能。
尽管Spark的过线程模型带来了很多好处,但同样存在不足,主要有:
由于同节点上所有任务运行在一个进程中,因此,会出现严重的资源争用,难以细粒度控制每个任务占用资源。与之相反的是MapReduce,它允许用户单独为Map Task和Reduce Task设置不同的资源,进而细粒度控制任务占用资源量,有利于大作业的正常平稳运行。
更具体的可以参考资源分配图
RDD是底层数据的逻辑高度抽象,并且含有location指针,所以client端的一份driver程序可以在各个集群中传递。
序列化与反序列化保证了第2点,同时由于序列化过程中并不包含原始类的信息,所以必须将.class文件打包一并传递,而基于Scala的闭包特性,就更适合分布式模型的处理。