【大数据学习】之 Spark-RDD core2

一、RDD的两种创建方式
Resilient Distributed Datasets (RDDs)
弹性   分布式      数据集
RDDS就是:弹性分布式数据集

参考:http://cwiki.apachecn.org/pages/viewpage.action?pageId=2885920
Spark 主要以一个弹性分布式数据集(RDD)的概念为中心,它是一个容错且可以执行并行操作的元素的集合。有两种方法可以创建 RDD : 在你的 driverprogram(驱动程序)中 parallelizing 一个已存在的集合,或者在外部存储系统中引用一个数据集,例如,一个共享文件系统,HDFS,HBase,或者提供 Hadoop InputFormat 的任何数据源。

第一种方法创建RDD:是在您的 driver program(驱动程序)中已存在的集合上通过调用  SparkContext 的 parallelize 方法来创建并行集合。
val rdd=sc.parallelize(Array(1,2,3,4,5))  //这句话的意思就是把该集合转化成rdd ,因为Spark不认集合,只认rdd,所以要转成RDD
rdd.collect().foreach(println) //collect返回的就是字符串类型,foreach()就是对集合里面的每一个元素做同一个事情,这里指打印print

第二种方法创建RDD: 可以使用 SparkContext 的 textFile 方法来创建文本文件的 RDD。此方法需要一个文件的 URI(计算机上的本地路径 ,hdfs://,s3n:// 等等的 URI),并且读取它们作为一个 lines(行)的集合
val rdd=sc.textFile("file:///e:/word.txt")
rdd.collect().foreach(println)

二、Spark-Shell
1、使用方法
在$SPARK_HOME目录的bin目录下
 
查看一下如何使用
[hadoop@hadoop001 bin]$ ./spark-shell --help
Usage: ./bin/spark-shell [options]

Options:
  --master MASTER_URL         spark://host:port, mesos://host:port, yarn,
                              k8s://https://host:port, or local (Default: local[*]).
  --deploy-mode DEPLOY_MODE   Whether to launch the driver program locally ("client") or
                              on one of the worker machines inside the cluster ("cluster")
                              (Default: client).
  --class CLASS_NAME          Your application's main class (for Java / Scala apps).
  --name NAME                 A name of your application.
  --jars JARS                 Comma-separated list of jars to include on the driver
                              and executor classpaths.
  --packages                  Comma-separated list of maven coordinates of jars to include
                              on the driver and executor classpaths. Will search the local
                              maven repo, then maven central and any additional remote
                              repositories given by --repositories. The format for the
                              coordinates should be groupId:artifactId:version.
  --exclude-packages          Comma-separated list of groupId:artifactId, to exclude while
                              resolving the dependencies provided in --packages to avoid
                              dependency conflicts.
  --repositories              Comma-separated list of additional remote repositories to
                              search for the maven coordinates given with --packages.
  --py-files PY_FILES         Comma-separated list of .zip, .egg, or .py files to place
                              on the PYTHONPATH for Python apps.
  --files FILES               Comma-separated list of files to be placed in the working
                              directory of each executor. File paths of these files
                              in executors can be accessed via SparkFiles.get(fileName).

  --conf PROP=VALUE           Arbitrary Spark configuration property.
  --properties-file FILE      Path to a file from which to load extra properties. If not
                              specified, this will look for conf/spark-defaults.conf.

  --driver-memory MEM         Memory for driver (e.g. 1000M, 2G) (Default: 1024M).
  --driver-java-options       Extra Java options to pass to the driver.
  --driver-library-path       Extra library path entries to pass to the driver.
  --driver-class-path         Extra class path entries to pass to the driver. Note that
                              jars added with --jars are automatically included in the
                              classpath.

  --executor-memory MEM       Memory per executor (e.g. 1000M, 2G) (Default: 1G).

  --proxy-user NAME           User to impersonate when submitting the application.
                              This argument does not work with --principal / --keytab.

  --help, -h                  Show this help message and exit.
  --verbose, -v               Print additional debug output.
  --version,                  Print the version of current Spark.

 Cluster deploy mode only:
  --driver-cores NUM          Number of cores used by the driver, only in cluster mode
                              (Default: 1).

 Spark standalone or Mesos with cluster deploy mode only:
  --supervise                 If given, restarts the driver on failure.
  --kill SUBMISSION_ID        If given, kills the driver specified.
  --status SUBMISSION_ID      If given, requests the status of the driver specified.

 Spark standalone and Mesos only:
  --total-executor-cores NUM  Total cores for all executors.

 Spark standalone and YARN only:
  --executor-cores NUM        Number of cores per executor. (Default: 1 in YARN mode,
                              or all available cores on the worker in standalone mode)

 YARN-only:
  --queue QUEUE_NAME          The YARN queue to submit to (Default: "default").
  --num-executors NUM         Number of executors to launch (Default: 2).
                              If dynamic allocation is enabled, the initial number of
                              executors will be at least NUM.
  --archives ARCHIVES         Comma separated list of archives to be extracted into the
                              working directory of each executor.
  --principal PRINCIPAL       Principal to be used to login to KDC, while running on
                              secure HDFS.
  --keytab KEYTAB             The full path to the file that contains the keytab for the
                              principal specified above. This keytab will be copied to
                              the node running the Application Master via the Secure
                              Distributed Cache, for renewing the login tickets and the
                              delegation tokens periodically.

2、shell的使用
[hadoop@hadoop001 bin]$  ./spark-shell --master local[2]
18/12/30 13:02:31 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Spark context Web UI available at http://hadoop001:4040
Spark context available as 'sc' (master = local[2], app id = local-1546146228136).
Spark session available as 'spark'.
启动后,试试通过parallelize读取并行集合
 

webui界面看到是2/2,是因为local[2],表示两个task,如果调整local[4],那么就有4个task
 
 
试试从外部文件读取数据
scala> sc.textFile("file:///home/hadoop/data/emp.txt").collect
 
读取hdfs上的文件
 
使用 Spark 来读取文件的一些注意事项 : 
a. 如果使用本地文件系统的路径,所工作节点的相同访问路径下该文件必须可以访问。复制文件到所有工作节点上,或着使用共享的网络挂载文件系统。
b. 所有 Spark 中基于文件的输入方法,包括 textFile(文本文件),支持目录,压缩文件,或者通配符来操作。例如,您可以用 textFile("/my/directory"),textFile("/my/directory/*.txt") 和 textFile("/my/directory/*.gz")。
c. textFile 方法也可以通过第二个可选的参数来控制该文件的分区数量。默认情况下,Spark 为文件的每一个 block(块)创建的一个分区(HDFS 中块大小默认是 128M),当然你也可以通过传递一个较大的值来要求一个较高的分区数量。请注意,分区的数量不能够小于块的数量。

三、RDD的操作
有了rdd后,就会有相应的操作,主要有两大类
(1)、transformations(转换):在一个已存在的 dataset 上创建一个新的 dataset。
(2)、actions(动作): 将在 dataset 上运行的计算结果返回到驱动程序。
Spark 中的所有 transformations 都是 lazy(懒加载的),因此它不会立刻计算出结果。相反,他们只记得应用于一些基本数据集(例如 : 文件)的转换。只有当需要返回结果给驱动程序时,transformations 才开始计算。这种设计使 Spark 的运行更高效。
默认情况下,每次你在 RDD 运行一个 action 的时, 每个 transformed RDD 都会被重新计算。但是,您也可用 persist (或 cache) 方法将 RDD persist(持久化)到内存中;在这种情况下,Spark 为了下次查询时可以更快地访问,会把数据保存在集群上。此外,还支持持续持久化 RDDs 到磁盘,或复制到多个结点。
例子的应用:
1、transformations的简单运用
filter
 
scala> val a =sc.parallelize(1 to 10)
a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[20] at parallelize at <console>:24
scala> a.filter(_%2==0)
res18: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[21] at filter at <console>:26
scala> a.filter(_%2==0).collect
res19: Array[Int] = Array(2, 4, 6, 8, 10)
scala> a.filter(_<5).collect
res20: Array[Int] = Array(1, 2, 3, 4)

map
 
scala> a.map(_*2).collect
res22: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala> a.map(_*2).filter(_>5).collect
res23: Array[Int] = Array(6, 8, 10, 12, 14, 16, 18, 20)

flatMap
 
scala> a.flatMap(x=>x.split("\t")).collect
res30: Array[String] = Array(hello, world, hello, hello, world, welcome)
scala> a.flatMap(x=>x.split("\t")).map((_,1)).collect
res31: Array[(String, Int)] = Array((hello,1), (world,1), (hello,1), (hello,1), (world,1), (welcome,1))
scala> a.flatMap(x=>x.split("\t")).map((_,1)).mapValues("x:"+ _).collect
res32: Array[(String, String)] = Array((hello,x:1), (world,x:1), (hello,x:1), (hello,x:1), (world,x:1), (welcome,x:1))

2、action的简单运用
对于很大的结果集,不要用collect算子。如果由必要看的话,可以考虑把结果存放到hdfs上,在hdfs上进行查看。或者用take算子取前几条来看。
scala> val a =sc.parallelize(1 to 10)
a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[38] at parallelize at <console>:24
scala> a.take(4)
res33: Array[Int] = Array(1, 2, 3, 4)
scala> a.count
res34: Long = 10
scala> a.reduce(_+_)
res35: Int = 55
scala> a.first
res36: Int = 1
scala> a.top(3)
res38: Array[Int] = Array(10, 9, 8)
scala> a.foreach(println)
6
7
8
9
10
1
2
3
4
5
scala> a.sortBy(x=>x).collect
res40: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)                        
scala> a.sortBy(x=>x,false).collect
res41: Array[Int] = Array(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

案列
1.    统计每个域名的流量和
//step 1
val sparkConf=new SparkConf().setMaster("local[2]").setAppName("SparkContextApp") //必须要设置URL和名字
//step 2
val sc=new SparkContext(sparkConf)
//TODO....step 3
//需求1:统计每个域名的流量和,就要获取域名和流量这2个字段
val lines=sc.textFile("file:///E:/data.txt")
lines.map(x=>{
  val temp=x.split("\t")
  val domain=temp(0)
  var response=0L
  try{
    response=temp(2).toLong
  }catch {
    case e:Exception=>println("......")
  }
  (domain,response) //这里是指返回值
}).reduceByKey(_+_).collect().foreach(println)
//step 4
sc.stop()
2、访问次数最多的URL
//step 1
val sparkConf=new SparkConf().setMaster("local[2]").setAppName("SparkContextApp") //必须要设置URL和名字

//step 2
val sc=new SparkContext(sparkConf)

//需求2:访问次数最多的url
val lines=sc.textFile("file:///E:/data.txt")
lines.map(x=>{
  val temp=x.split("\t")
  val domain=temp(0)
  var response=0L
  try{
    response=temp(2).toLong
  }catch {
    case e:Exception=>println("......")
  }
  (domain,response) //这里是指返回值
}).reduceByKey(_+_).sortBy(_._2,false).take(10).foreach(println)
//step 4
sc.stop()

3、如何在服务器上提交
/*
* 域名0 ,流量2
* 输入:args(0)
* 输出:args(1)
* */

object LogServerApp {
  //RDD编程的模型:第一步是创建sparkConf,第二步创建sparkContext,然后吧sparkConf传到sparkContext,第三业务代码,第四是关闭
  def main(args: Array[String]): Unit = {
    //最好就是在SparkContext创建之前,就创建sparkConf,跟着把sparkConf传到SparkContext
    //step 1
    val sparkConf=new SparkConf().setMaster("local[2]").setAppName("SparkContextApp") //必须要设置URL和名字

    //step 2
    val sc=new SparkContext(sparkConf)

    //TODO....step 3
    //需求1:统计每个域名的流量和,就要获取域名和流量这2个字段
    //需求2:访问次数最多的url

    val lines=sc.textFile(args(0)) //第一个参数作为输入
    lines.map(x=>{
      val temp=x.split("\t")
      val domain=temp(0)
      var response=0L
      try{
        response=temp(2).toLong
      }catch {
        case e:Exception=>println("......")
      }
      (domain,response) //这里是指返回值
    }).reduceByKey(_+_).saveAsTextFile(args(1))
    //step 4
    sc.stop()
  }
}
代码写完后,跟着
(1)打包IDEA中的代码
 


 
可能会下载。。。

最后打包完,会显示成功,和可以看到生成的jar包目录

(2)提交。来到Spark的官网,进入Overview下的Submitting Applications
 
或者在$SPARK_HOME/bin里面查查spark-submit的用法
 
a.将打包的路径E:\ruozedata_workspace\g5-spark\target\g5-spark-1.0.jar用命令rz上传到Lunux(服务器)上,
 
b.在hdfs上创建输入目录
hadoop fs -mkdir  -p /logs/input
上传数据到/logs/input
 
c.运行脚本
./spark-submit \
--master local[2] \
--class com.ruozedata.bigdata.core02.LogServerApp \
--name LogServerApp \
/home/hadoop/lib/g5-spark-1.0.jar \
hdfs://hadoop001:9000/logs/input/ hdfs://hadoop001:9000/logs/output/
 
在hdfs查看一下结果,都正常

d.在工作中我们一般都封装脚本来执行的
${SPARK_HOME}/bin/spark-submit \
--master local[2] \
--class com.ruozedata.bigdata.core02.LogServerApp \
--name LogServerApp \
/home/hadoop/lib/g5-spark-1.0.jar \
hdfs://hadoop001:9000/logs/input/ hdfs://hadoop001:9000/logs/output/
然后把它保存到~shell/log.sh里面,修改一下执行权限,再执行即可。
chmod +x ./log.sh
./log.sh

(3)解决输出路径重复的问题
def main(args: Array[String]): Unit = {
  //最好就是在SparkContext创建之前,就创建sparkConf,跟着把sparkConf传到SparkContext

  //step 1
  val sparkConf=new SparkConf().setMaster("local[2]").setAppName("SparkContextApp") //必须要设置URL和名字

  //step 2
  val sc=new SparkContext(sparkConf)

  val uri=new URI("hdfs://hadoop001:9000")
  val fileSystem=FileSystem.get(uri,sc.hadoopConfiguration)
  if (fileSystem.exists(new Path(args(1)))){   //如果存在就删掉
    fileSystem.delete(new Path(args(1)),true)
  }

  //TODO....step 3
  //需求1:统计每个域名的流量和,就要获取域名和流量这2个字段
  //需求2:访问次数最多的url
  val lines=sc.textFile(args(0)) //第一个参数作为输入
  lines.map(x=>{
    val temp=x.split("\t")
    val domain=temp(0)
    var response=0L
    try{
      response=temp(2).toLong
    }catch {
      case e:Exception=>println("......")
    }
    (domain,response) //这里是指返回值
  }).reduceByKey(_+_).saveAsTextFile(args(1))
  //step 4
  sc.stop()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值