一个简单的例子
// 需要对名为逗hello.txt地的HDFS文件进行一次map操作,再进行一次reduce操作。也就是说,需要对一份数据执行两次算子操作。
// 错误的做法:对于同一份数据执行多次算子操作时,创建多个RDD。
// 这里执行了两次textFile方法,针对同一个HDFS文件,创建了两个RDD出来,然后分别对每个RDD都执行了一个算子操作。
// 这种情况下,Spark需要从HDFS上两次加载hello.txt文件的内容,并创建两个单独的RDD;第二次加载HDFS文件以及创建RDD的性能开销,很明显是白白浪费掉的。
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd1.map(...)
val rdd2 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd2.reduce(...)
// 正确的用法:对于一份数据执行多次算子操作时,只使用一个RDD。
// 这种写法很明显比上一种写法要好多了,因为我们对于同一份数据只创建了一个RDD,然后对这一个RDD执行了多次算子操作。
// 但是要注意到这里为止优化还没有结束,由于rdd1被执行了两次算子操作,第二次执行reduce操作的时候,还会再次从源头处重新计算一次rdd1的数据,因此还是会有重复计算的性能开销。
// 要彻底解决这个问题,必须结合逗原则三:对多次使用的RDD进行持久化地,才能保证一个RDD被多次使用时只被计算一次。
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd1.map(...)
rdd1.reduce(...)
Spark Core部件解析
应用程序(Application): 基于Spark的用户程序,包含了一个Driver Program
和集群中多个的Executor;
应用程序(Application): 基于Spark的用户程序,包含了一个Driver Program
和集群中多个的Executor;
应用程序(Application): 基于Spark的用户程序,包含了一个Driver Program
和集群中多个的Executor;
集群管理程序(Cluster Manager): 在集群上获取资源的外部服务(例如:
Standalone、Mesos或Yarn);
Spark Core部件解析
操作(Operation):作用于RDD的各种操作分为Transformation和Action
DAGScheduler: 把对Job中的RDD有向无环图根据依赖关系划分为多个
Stage.每一个Stage是一个TaskSet,它还会根据RDD和Stage之间的关系
找出开销最小的调度方法,然后把Stage以TaskSet的形式提交给
TaskScheduler
Stage是一个TaskSet
TaskScheduler维护着所有Task的运行状态,重试失败的Task并把合适的
把Task分发给Worker中的Executor