Pari RDD --- 转换操作函数☞reduceByKey

 

 

一、再说 RDD

 

        Spark中的RDD虽然统一叫做弹性分布式数据集,但是,RDD的创建方式却是多种多样的,且RDD的数据类型也是有区分的,且RDD的操作分为两种,一种是转换(Transformation)操作,一种是执行(Action)操作

        这里的RDD的操作,我们具体点就是一个完整的Spark计算过程(Driver节点提交任务,多个Worker节点并行执行任务);

        其中RDD的转换操作目的就是为了得到一个或者说是创建一个新的RDD,有可能这个RDD只经过一道转换就直接进行Action操作了,也有可能被转来转去,但是,记住,只要RDD没有执行Action操作,则RDD在整个任务执行过程中的转来转去实际上是没有意义的,也就是RDD【数据集】没有被真正的创建,即内存中是没有任何数据的;

        【这就好比口头协议一样,如果协议最终不落实,你说的再漂亮也是白搭】

        由于上述的特殊性:只有执行Action操作的时候,RDD才会被真正创建,那如何将创建好的RDD缓存起来避免重复转换呢?

        虽然扯的有点多,但是如果不多扯点的话,太不像话了,不像我的风格,哈哈

        缓存的方式有两种: (1)cache  (2)persist

         

(1) cache 【实际上调用的是无参persist()函数,即默认缓存策略方式:MEMORY_ONLY -- 性能最高

 

 

1、创建一个list列表

2、利用parallelize函数,将现有list转换成可以并行计算的RDD,且parallelize函数支持分区【第二个参数指定】

3、缓存RDD

 

(2)persist【可传入持久化存储级别,即方法有好几个重载,默认为:MEMORY_ONLY

 

 

       

 

 

      

二、什么是Pari RDD

 

    

        RDD是一个数据结构,它表示了一组数据的集合,这个数据集是有类型的,如同Java的List和Map一样,有列表集合,也有键值对的集合,RDD也是,有List列表类型的RDD,也有Map键值对类型的RDD,后者我们称作是Pari RDD,即这种类型的RDD可以进行key值的转换操作得到一个新的RDD

        

(1) List RDD

 

        启一个spark-shell

 

 

 

创建一个list类型的RDD,并执行Action操作,遍历打印RDD中的元素【不要忘了,缓存它,待会我们要用

 

 

scala> var list = List("Hadoop","Spark","Java","Spark")
list: List[String] = List(Hadoop, Spark, Java, Spark)

scala> var listRDD = sc.parallelize(list,2)
listRDD: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallel
ize at <console>:26

scala> listRDD.persist()
res0: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize
 at <console>:26

scala> listRDD.foreach(println)
Hadoop
Java
Spark
Spark

 

执行效果

 

 

 

 

(2) Pari RDD

 

        利用上面缓存起来的RDD,我们再进行一次map转换操作得到新的RDD -- mapRDD

 

 

scala> var mapRDD = listRDD.map(word => (word,1))
mapRDD: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[1] at map at
<console>:25

scala> mapRDD.take(10).foreach(println)
(Hadoop,1)
(Spark,1)
(Java,1)
(Spark,1)

 

执行效果:

 

 

map函数不陌生吧,它是一个RDD转换函数,通过key-value的形式,得到一个新的RDD,这个RDD就是一个Pari RDD

 

注意,在对RDD进行遍历操作的时候【Action操作】,如果RDD是本地模式的话,println打印的就是当前机器上的RDD,如果是集群模式的话,则println的结果会显示在RDD所在的worker机器上,而不是当前driver机器上;如果想要在driver节点上打印分布在各个worker节点上的RDD的话,则需要用到collect函数将所有分区上的RDD收集过来,如下:

 

 

【mapRDD.take(10).foreach(println)】

 

 

 

由于我们不知道RDD数据有多少个,其中一个RDD又含有多少个元素;所以直接将收集过来的RDD进行println的话,会存在问题的;如果RDD很大,全部打印元素的话,内存开销会很大甚至可能会爆掉,为了避免这种情况的发生,我们可以有选择性的打印,比如,我只抓取前一个元素:

 

 

 

 

 

 

三、reduceByKey函数怎么用?

 

 

(1)reduce函数我们知道,其是一个Action【执行】函数,对RDD根据某种规则进行元素归并操作的

(2)reduceByKey函数我们就算不知道,也可以通过函数名进行猜测

 

  首先,reduce表示归并元素,那么元素是谁的呢?

  其次,通过ByKey我们知道,归并的元素是由key来决定的,那么什么样类型的RDD才有key呢?

  然后,我们得出来,只有Pari RDD才可以进行reduceByKey函数的操作

  最后,问题来了,reduceByKey是转换函数呢,还是执行函数呢?

 

(3)reduceByKey使用

 

scala> var wordSizeRDD = mapRDD.reduceByKey((a,b) => a+b)
wordSizeRDD: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[2] at reduceB
yKey at <console>:25

 

   执行结果:

 

     

 

 

注意两个地方:

 

 

 

首先,Pari RDD【mapRDD】经过reduceByKey函数后【将key值对应的value值归并求和】得到了一个RDD,注意这个RDD仍然是个Pari RDD【键值对形式】

 

其次,这个RDD是一个ShuffledRDD,what? 这是不是透漏了什么?

 

什么是shuffle呢? 我在之前博文中讲解Hadoop的MapReduce的时候,说过这个,中文单词是洗牌的意思,比如,这里,我们把mapRDD比作是一副扑克

 

 

 

洗牌的过程其实就是按照某种规则【(a,b) => a+b】进行归并操作

OK,既然得到的是一个Pari RDD,则我们可以肯定的说,reduceByKey是一个转换函数,没问题吧

 

 

(4)将" 洗过的牌 "遍历打印一下

 

 

 

 

(5)如果还不过瘾的话,我们对上面的RDD【结果】再进行一次Action操作【得到单词词频最高的value值】

 

  拿到map的第二个元素即value值进行max【两两比较取最大值】执行操作,拿到最终的结果【2】

 

scala> var maxSizeRDD = wordSizeRDD.map(word => word._2).max
maxSizeRDD: Int = 2

 

执行结果:

 

 

 

(6)反过来,拿到词频数最高的value后,我想知道哪些单词出现的频率数等于这个value,我们不妨来试试

 

scala> var maxWordRDD = wordSizeRDD.filter(word => word._2 == 2).collect
maxWordRDD: Array[(String, Int)] = Array((Spark,2))

 

执行结果:

 

 

通过两步,我们知道spark单词出现的频率最高,这意味什么呢【直接联想到 == 商业价值中】?  

可能Spark比较火,感兴趣的人比较多,也有可能Spark很强大,用的人很多....etc

 

 

(7)如果还不过瘾的话,能不能一行代码【一步到位】搞定呢?

 

scala> var maxWordRDD = wordSizeRDD.reduce((a,b) => if(a._2 > b._2 ) a else b)
maxWordRDD: (String, Int) = (Spark,2)

 

执行结果:

 

 

 

 

 

四、reduceByKey能干嘛?

 

     通过上面的例子,我们知道了reduceByKey函数的用法,注意,它是一个转换函数,区别于reduce函数【Action函数】,且函数的作用对象是一个Pari RDD,因为只有键值对形式的RDD才具有key和value值

     最后,它能干什么? 来日方长,自己好好琢磨吧......

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值