spark_note03_spark计算模型RDD_1

spark计算模型RDD_1.0

(一)什么是RDD

弹性分布式数据集

基于内存

弹性的

自动容错的

内存迭代

(er)RDD的五大属性

  • 1.一个分区列表

    每个RDD都有很多个分区,分区里面才是真正的数据,spark的任务是以分区为单位的,一个分区后期就对应一个spark的task,也就是一个分区就对应一个线程

  • 2.作用在每一个rdd分区中的函数

    举例:val rdd2=rdd1.map(x=>(x,1))

  • 3.RDD之间的依赖关系

    一个rdd会依赖于其它多个rdd,后期spark任务的容错机制就是根据这个特性

  • 4.(可选项) 一个Partitioner,即RDD的分区函数

    对于kv类型的RDD才会有分区函数这个概念(必须要产生shuffle),不是kv类型的RDD分区函数是None

    ​ spark中有两种分区函数:

    • hashPartitioner(默认值),其本质key,hashcode % 分区数 = 分区号

    • RangePartitioner, 是基于一定的范围的分区函数

  • 5.(可选项) 一个列表,存储每个Partition的优先位置(可选项)。

    spark后期再进行任务分配的时候,优先考虑存有数据的worker节点来进行任务的计算

(三)创建RDD

三种方式

  • 1.通过一个已经存在的scala集合或者数组去构建

    scala> val rdd1=sc.parallelize(List(1,2,3,4))
    rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:2
    
    
    scala> val rdd2=sc.parallelize(Array(1,2,3,4))
    rdd2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:24
    
    
  • 2.通过加载外部的数据源去构建

    scala> val rdd3=sc.textFile("/sparkdata/input/word.txt")
    rdd3: org.apache.spark.rdd.RDD[String] = /sparkdata/input/word.txt MapPartitionsRDD[3] at textFile at <console>:24
    
    

//对于文件来说指定最小分区数,取决于hadoop的分片规则
scala> val rdd3=sc.textFile("/sparkdata/input/word.txt",3)

  • 3.通过一个rdd转换之后生成一个新的rdd

    val rdd4=rdd3.flatMap(_.split(" "))
    rdd4: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[4] at flatMap at <console>:26
    
    
     val rdd5=rdd4.map((_,1))
    rdd5: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[5] at map at <console>:28
    
    

(四)RDD编程API

RDD的算子分类

操作描述操作说明
transformation该操作是从已有的数据集创建新的数据集.
action该操作主要是对数据集运行计算后,将运算得到的结果返回给驱动程序

Transformation

操作名称操作描述
map将RDD中的每一个元素传入自定义函数,获取一个新的元素,然后用新的元素组成新的RDD
filter对RDD中的每个元素进行判断,如果返回true,则保留,返回false,则过滤掉
flatMap与map类似,但是对每个元素都可以返回一个或多个新元素
groupByKey根据key进行分组,每个key对应一个iterable
reduceByKey对每个key对应的value进行reduce操作
sortByKey对每个key对应的value进行排序操作
join对两个包含<key,value>对的RDD进行join操作,每个key join上的pair,都会传入自定义函数进行处理
cogroup同join,但是每个key对应的iterable都会传入自定义函数来进行处理

Action

操作名称操作描述
reduce将RDD中的所有元素进行聚合操作.第一个和第二个元素聚合,值与第三个元素聚合,值与第四个元素聚合,以此类推.
collect将RDD中所有元素获取到本地客户端
count获取RDD元素总数
take(n)获取RDD中前n个元素
saveAsTextFile将RDD元素保存到文件中,对每个元素调用toString()方法
countByKey对每个key对应的值进行count计数
foreach遍历RDD中的每个元素.

(五)RDD常用的算子操作

进入spark-shell

[root@node01 ~]# spark-shell --master spark://node01:7077

练1:map filter

scala> val rdd1=sc.parallelize(List(3,4,5,2,7,4,3,8,10))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

scala> val rdd2 = rdd1.map(_*10).sortBy(x=>x,true)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[12] at sortBy at <console>:26

scala> val rdd3=rdd2.filter(_>5)
rdd3: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[13] at filter at <console>:28

scala> rdd3.collect
res2: Array[Int] = Array(20, 30, 30, 40, 40, 50, 70, 80, 100)

scala> 

练2:flatMap

为了看起来清楚 下面例子把很多返回删除了

scala> val rdd1=sc.parallelize(Array("a b c","d e f","h i j"))
scala> val rdd2=rdd1.flatMap(_.split(" "))

scala> rdd2.collect
res3: Array[String] = Array(a, b, c, d, e, f, h, i, j)

scala> 

练3:并集、交集

scala> 

//定义两个rdd集合
scala> val rdd1=sc.parallelize(List(5,6,4,3))
scala> val rdd2=sc.parallelize(List(1,2,3,4))

//求并集,去重
scala> val rdd3=rdd1.union(rdd2)

scala> rdd3.distinct.collect
res0: Array[Int] = Array(4, 1, 5, 6, 2, 3)                                      
//求交集
scala> val rdd4=rdd1.intersection(rdd2)

scala> rdd4.collect
res1: Array[Int] = Array(4, 3)

scala> 

练4:join groupByKey

scala> 

//定义两个rdd列表
scala> val rdd1=sc.parallelize(List(("tom",1),("jerry",3),("kitty",2)))
scala> val rdd2=sc.parallelize(List(("jerry",2),("tom",1),("shuke",2)))

//join (类似于内连接)
scala> val rdd3 = rdd1.join(rdd2)

scala> rdd3.collect
res2: Array[(String, (Int, Int))] = Array((tom,(1,1)), (jerry,(3,2)))

//
scala> val rdd4=rdd1 union rdd2

scala> rdd4.collect
res3: Array[(String, Int)] = Array((tom,1), (jerry,3), (kitty,2), (jerry,2), (tom,1), (shuke,2))

//groupByKey
scala> val rdd5=rdd4.groupByKey
rdd5: org.apache.spark.rdd.RDD[(String, Iterable[Int])] = ShuffledRDD[18] at groupByKey at <console>:30

scala> rdd5.collect
res4: Array[(String, Iterable[Int])] = Array((tom,CompactBuffer(1, 1)), (jerry,CompactBuffer(3, 2)), (shuke,CompactBuffer(2)), (kitty,CompactBuffer(2)))

scala> 

练5:cogroup

scala> 

//定义两个rdd列表
scala> val rdd1=sc.parallelize(List(("tom",1),("tom",2),("jerry",3),("kitty",2))) 
scala> val rdd2=sc.parallelize(List(("jerry",2),("tom",1),("jim",2)))

//cogroup
scala> val rdd3=rdd1.cogroup(rdd2)
rdd3: org.apache.spark.rdd.RDD[(String, (Iterable[Int], Iterable[Int]))] = MapPartitionsRDD[22] at cogroup at <console>:28

scala> rdd3.collect
res5: Array[(String, (Iterable[Int], Iterable[Int]))] = Array((jim,(CompactBuffer(),CompactBuffer(2))), (tom,(CompactBuffer(1, 2),CompactBuffer(1))), (jerry,(CompactBuffer(3),CompactBuffer(2))), (kitty,(CompactBuffer(2),CompactBuffer())))

scala> 

注意groupByKey与cogroup的区别

结果对比

//groupByKey
Array[(String, Iterable[Int])] = Array((tom,CompactBuffer(1, 1)), (jerry,CompactBuffer(3, 2)), (shuke,CompactBuffer(2)), (kitty,CompactBuffer(2)))

//cogroup
Array[(String, (Iterable[Int], Iterable[Int]))] = Array((jim,(CompactBuffer(),CompactBuffer(2))), (tom,(CompactBuffer(1, 2),CompactBuffer(1))), (jerry,(CompactBuffer(3),CompactBuffer(2))), (kitty,(CompactBuffer(2),CompactBuffer())))

练6:reduce

scala> 

scala> val rdd1=sc.parallelize(List(1,2,3,4,5))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[23] at parallelize at <console>:24

scala> val rdd2=rdd1.reduce(_+_) //第一个_表示累加结果
rdd2: Int = 15

scala> 

练7:reduceByKey sortByKey

scala> 

scala> val rdd1=sc.parallelize(List(("tom",1),("jerry",3),("kitty",2),("shuke",1)))
scala> val rdd2=sc.parallelize(List(("jerry",2),("tom",3),("shuke",2),("kitty",5)))

scala> val rdd3=rdd1.union(rdd2)

//按key进行聚合
scala> val rdd4=rdd3.reduceByKey(_+_)
rdd4: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[36] at reduceByKey at <console>:30

scala> rdd4.collect
res6: Array[(String, Int)] = Array((tom,4), (jerry,5), (shuke,3), (kitty,7))

//按value的降序排序
scala> val rdd5 = rdd4.map(t=>(t._2,t._1)).sortByKey(false).map(t=>(t._2,t._1))
rdd5: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[41] at map at <console>:32

scala> rdd5.collect
res7: Array[(String, Int)] = Array((kitty,7), (jerry,5), (tom,4), (shuke,3))    

scala> 

练8:repatition coalesce

//原来三个分区
scala> val rdd1=sc.parallelize(1 to 10,3)

//减少分区
scala> rdd1.repartition(2).partitions.size
res9: Int = 2

//coalesce
scala> val rdd3=rdd1.coalesce(1)
rdd3: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[1] at coalesce at <console>:26

scala> rdd3.partitions.length
res3: Int = 1

scala> 

(六)通过spark实现点击流日志分析案例

1.访问的PV

package cn.itcast.rdd

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object PV {
  def main(args: Array[String]): Unit = {
    //1.创建sparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("PV").setMaster("local[2]")

    //2.创建SparkCotext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3.读取数据文件
    val data: RDD[String] = sc.textFile("F:\\AAAA_HM大数据\\00-课件\\18_spark\\spark\\day02\\资料\\运营商日志\\access.log")

    //4.统计PV   //map---->每一行---->context.write(new Text("PV"),1)  reduce -------> 汇总
    val pv: Long = data.count()
    println("PV:"+pv)

    //5.关闭sc
    sc.stop()

  }

}

/*
  ...
00/00/00 00:50:50 INFO BlockManager: Initialized BlockManager: BlockManagerId(driver, 192.168.239.1, 10323, None)
PV:14622
 */

2.访问的UV

package cn.itcast.rdd

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

//todo:利用spark实现点击流日志数据分析---------UV
object UV {
  def main(args: Array[String]): Unit = {
    //1.创建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("UV").setMaster("local[2]")

    //2.创建SparkContext
    val sc = new SparkContext(sparkConf)

    //3.读取数据文件
    val data: RDD[String] = sc.textFile("F:\\AAAA_HM大数据\\00-课件\\18_spark\\spark\\day02\\资料\\运营商日志\\access.log")

    //4.切分每一行 获取ip地址
    val ipRDD: RDD[String] = data.map(x=>x.split(" ")(0))

    //5.ip地址去重
    val distinctRDD: RDD[String] = ipRDD.distinct()

    //6.统计UV
    val uv: Long = distinctRDD.count()
    println("UV:"+uv)

    //7.关闭
    sc.stop()

  }
}


/*
...
00/00/00 00:28:38 INFO DAGScheduler: Job 0 finished: count at UV.scala:25, took 0.817432 s
UV:1051
00/00/00 00:28:38 INFO ...
 */

3.Top5

package cn.itcast.rdd

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}


//todo:利用spark实现点击流日志数据分析---------TopN
object TopN {
  def main(args: Array[String]): Unit = {
    //1.创建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("TopN").setMaster("local[2]")

    //2.创建SparkContext
    val sc = new SparkContext(sparkConf)

    //3.读取数据文件
    val data: RDD[String] = sc.textFile("F:\\AAAA_HM大数据\\00-课件\\18_spark\\spark\\day02\\资料\\运营商日志\\access.log")

    //4.过滤出一些丢失的字段记录 保留正确的数据 获取URL
    val url: RDD[String] = data.filter(x=>x.split(" ").length>10).map(x=>x.split(" ")(10))

    //5.每个url记为1
    val urlAndOne: RDD[(String, Int)] = url.map(x=>(x,1))

    //6.相同url出现的1累加
    val result: RDD[(String, Int)] = urlAndOne.reduceByKey(_+_)

    //7.按照url出现的次序降序
    val sortedRDD: RDD[(String, Int)] = result.sortBy(x=>x._2,false)

    //8.取出url出现次数最多的前5位
    val top5: Array[(String, Int)] = sortedRDD.take(5)
    top5.foreach(x=>println(x))

    //9.关闭
    sc.stop()
  }

}

/*
  ...
00/00/00 00:43:50 INFO DAGScheduler: Job 1 finished: take at TopN.scala:32, took 0.197640 s
("-",5206)
("http://blog.fens.me/category/hadoop-action/",547)
("http://blog.fens.me/",377)
("http://blog.fens.me/wp-admin/post.php?post=2445&action=edit&message=10",360)
("http://blog.fens.me/r-json-rjson/",274)
00/00/00 00:43:50 INFO SparkUI: Stopped Spark web UI at http://192.168.239.1:4040
   ...
 */


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值