spark 学习(二) RDD及共享变量

声明:本文基于spark的programming guide,并融合自己的相关理解整理而成

 

     Spark应用程序总是包含着一个driver program(驱动程序),它执行着用户的main方法,并且执行大量的并行操作(parallel operations)在集群上.

概述

 
    Spark最主要的抽象就是RDD(resilient distributed dataset) 弹性分布式数据集,RDD  就是分割元素的集合,他被分发在集群的各个节点上,并且能够进行并行操作.
    RDD的创建有三种方式:
  • HDFS,HBase 或者其他任何能够提供Hadoop输入格式的数据源;          
  • 驱动程序中已存在的Scala集合;
  • 其他的RDD的转换
RDD能够持久化到内存中以重复使用加速计算速度, RDD能够自动从失败的节点中恢复(血统设计).
 
    Spark中的另一个抽象就是能够被用于并行计算的共享变量. 默认的情况下, Spark并行运行一个函数是作为一组tasks在不同的节点上同时计算的, 这种情况下,他是通过分发每一个变量的拷贝到每个task中的. 有时候,我们需要某些变量在tasks之间进行共享. 这里Spark支持两种共享变量:
  1.  broadcast variables, 被用于持久化变量在每个node的内存中;
  2.  accumulators,  这个变量只能够被累加,

    

RDD操作

 
     操作主要包括两种,分别是transformations 和 action
     transformation : 将一个已经存在的RDD中转换成一个新的RDD,所有的转换操作都是lazy执行的,即只是记下了执行的动作,只有当driver程序需要结果的时候才会进行计算. 
 
 
action:一般用于对RDD中的元素进行实际的计算,然后返回相应的值,例如reduce操作,collect操作,count操作等等.这中action之后返回的就不在是RDD了
 
RDD基本操作的几个例子以及自己的理解:
[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. val conf = new SparkConf().setAppName("BasicRDDApp").setMaster("local[4]")  
  2.    //spark://host:port  
  3.    val sc = new SparkContext(conf)  
  4.   
  5.    /** 
  6.     *  parallelized collections 
  7.     *  将scala的集合数据,并行化成为能够并行计算的分布式数据集 
  8.     */  
  9.    val data = 1 to 1000 toArray  
  10.    val distData = sc.parallelize(data,10)  
  11.    //后面的数字是表示将集合切分成多少个块 ,通常是一个CPU 2-4块,通常spark可以自动帮你切分  
  12.   
  13.    val sum =  distData.reduce((a, b) => a+b )  
  14.    //在reduce的时候才开始真正的执行,driver将任务分布到各个机器上,然后每个机器单独执行,将计算的结果返回到driver程序  
  15.    println("sum " + sum)  
  16.   
  17.    /** 
  18.     * 读取外部的数据源 
  19.     * 1.Hadoop支持的数据源 ,例如HDFS,Cassandra,HBase ,Amazon S3 
  20.     * ##如果文件地址是本地地址的话,那么他应该在集群的每个节点上都能够被访问(即:每个节点上都应该有同样的文件) 
  21.     * ##textFile的第二个参数控制文件被切割的大小默认为64MB ,可以设置更大的但是不能设置更小的 
  22.     */  
  23.   
  24.    val distFile = sc.textFile("file:///usr/local/spark/README.md")  
  25.   
  26.    //接下来就可以进行相关的操作了  
  27.    distFile.persist()//持久化  
  28.   
  29.    val len = distFile.map(s => 1).reduce((a, b) => a+b)  
  30.    println(len)  
  31.   
  32.    val words = distFile.flatMap(l => l.split(" ")).map(w => (w,1)).reduceByKey((a,b) => a+b)  
  33.    //w => (v1+v2+v3+...)  
  34.    //map => 1->1 , flatMap => 1 -> 0..n  
  35.   
  36.   
  37.    print(words.count())  
  38.    words foreach println  
  39.   
  40.    val twords = distFile.flatMap(l => l.split(" ")).map(w => (w,1)).groupByKey()  
  41.    //分组 w => (v1, v2, v3 ...)  
  42.   
  43.    twords foreach println  
  44.    //.map(w => (w,1)).foreach(w => w._1);  
 

 

RDD的持久化

 
  1. 用法: 使用persist()或者cache()方法,其中cache()方法默认持久化到内存,persist可以自己选择持久化的层次,在shuffle操作中,spark会自动保存中间计算结果,例如reduceBykey
  2. 作用:  RDD的持久化会将会使得每个节点保存相应的计算部分,以便再次使用该数据集时可以直接使用,加快计算速度
  3. 如何选择持久化层次: 如果RDDs 在MEMORY_ONLY下表现良好的话,就选这个层次,这样CPU效率最高
    其次MEMORY_ONLY_SER ,其他情况http://spark.apache.org/docs/latest/programming-guide.html 

     


共享变量

 
1. broadcast 变量, 只读的共享变量 每个节点上都有一个拷贝, 用法
     val broadcastVar = sc.broadcast("string test")
     broadcastVar.value
2.accumulator 变量,做累加器用,类似与counter或者是sum
[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. val broadcastVar = sc.broadcast("string test")//broadcast variable is readonly  
  2.   
  3. val v = broadcastVar.value  
  4. println(v)  
  5.   
  6. val accum = sc.accumulator(0, "My Accumulator")//value and name  
  7.   
  8. sc.parallelize(1 to 1000000).foreach(x => accum+= 1)  
  9.   
  10. println(accum.name + ":" + accum.value)  
posted @ 2016-06-30 21:48  XGogo  阅读(799)  评论(0编辑  收藏  举报