论宽依赖、窄依赖与shuffle

概念上来说

    Shuffle的含义就是洗牌,将数据打散,父RDD一个分区中的数据如果给了子RDD的多个分区(只要存在这种可能),就是shuffle。Shuffle会有网络传输数据,但是有网络传输,并不意味着就是shuffle。

窄依赖:没有发生shuffle

宽依赖:存在shuffle

    也许大家看了上面的说法只是有个初步的印象,下面我将以join为例进行讲解,相信大家看了这个例子就会对上面的概念有一个更为深刻的理解。

val rdd1=sc.parallelize(List((1,"wzh"),(2,"lly")),2)
val rdd2=sc.parallelize(List((1,"wzh"),(2,"lly")),2)
rdd1.join(rdd2).collect

    普通的join是一个宽依赖,比如rdd1.join(rdd2).collect中,(2个rdd都通过parallelize并行化创建),在这个过程中会产生3个stage。第一个Stage是rdd1(包括形成rdd1过程所进行的转换操作)将中间数据写到磁盘上等待下游来拉取,第二个Stage是rdd2(包括形成rdd2过程所进行的转换操作)将中间数据写到磁盘上等待下游来拉取,第三个Stage就是下游读取磁盘数据。也产生了2个shuffle。

    这里大家也许会困惑,明明2个rdd各有2个分区,4个分区均各有一个数据,在join时并没有出现父rdd的某个分区中的数据跑到子rdd不同分区的情况,也不可能发生(因为单个数据不会拆分),为什么还会出现shuffle?实际上,虽然一个父rdd中的一个分区中的数据并没有被拆开,但是它存在着会发生一个父rdd的一个分区数据分给多个子rdd分区的可能(即不管实际上有多少数据,只要这种模式下存在着这种可能),就会产生shuffle,就是宽依赖,就会划分stage。

    相信通过上面的例子,大家应该对何时发生宽依赖有了比较深的理解了。这里大家可能会疑惑,如果是上面这种说法,那么join不就一定是宽依赖吗?其实还存在着一种特殊的join,见下图:

   

    在先进行grouByKey之后,再进行join,且在这个过程中既没有修改RDD分区的数量,也没有设置新的分区器(默认都是按照hashpartitioner分区),那么这个join就是窄依赖。这里稍微详细的解释一下,因为在上面2个RDD中,在groupByKey之后,会产生shuffle,且按照hashpartitioner进行分区,也就是说2个RDD中的数据会按照同样的分区方式进行分区,从而导致相对应的key所对应的数据都到了同一个分区,因此再进行join时,只要子RDD分区数和分区器(默认还是hashpartitioner)不变,这些相对应的数据还是会跑到同一分区中,因此就不会出现父RDD一个分区中的数据跑到子RDD的多个分区中,因此就是一个窄依赖。

注:在这个过程中也可能发生网络传输,但是并没有发生shuffle,因此有网络传输并不一定就是shuffle。

    这里对上面所述进行一个通俗的总结,如果在进行join之前调用的是宽依赖(存在shuffle)的RDD,两个RDD的分区数量一致,且join之后产生的子RDD的分区数量也一样,那么这个时候的join就是窄依赖。除此之外的,都是宽依赖。

 

 

 

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值