Spark自定义分区(Partitioner)

我们都知道Spark内部提供了HashPartitionerRangePartitioner两种分区策略(这两种分区的代码解析可以参见:《Spark分区器HashPartitioner和RangePartitioner代码详解》),这两种分区策略在很多情况下都适合我们的场景。但是有些情况下,Spark内部不能符合咱们的需求,这时候我们就可以自定义分区策略。为此,Spark提供了相应的接口,我们只需要扩展Partitioner抽象类,然后实现里面的三个方法:

package org.apache.spark
 
/**
  * An object that defines how the elements in a key-value pair RDD are partitioned by key.
  * Maps each key to a partition ID, from 0 to `numPartitions - 1`.
  */
abstract class Partitioner extends Serializable {
   def numPartitions : Int
   def getPartition(key : Any) : Int
}

  def numPartitions: Int:这个方法需要返回你想要创建分区的个数;
  def getPartition(key: Any): Int:这个函数需要对输入的key做计算,然后返回该key的分区ID,范围一定是0到numPartitions-1
  equals():这个是Java标准的判断相等的函数,之所以要求用户实现这个函数是因为Spark内部会比较两个RDD的分区是否一样。

  假如我们想把来自同一个域名的URL放到一台节点上,比如:https://www.iteblog.comhttps://www.iteblog.com/archives/1368,如果你使用HashPartitioner,这两个URL的Hash值可能不一样,这就使得这两个URL被放到不同的节点上。所以这种情况下我们就需要自定义我们的分区策略,可以如下实现:

package com.iteblog.utils
 
import org.apache.spark.Partitioner
 
/**
  * User: 过往记忆
  * Date: 2015-05-21
  * Time: 下午23:34
  * 过往记忆博客,专注于hadoop、hive、spark、shark、flume的技术博客,大量的干货
  * 过往记忆博客微信公共帐号:iteblog_hadoop
  */
 
class IteblogPartitioner(numParts : Int) extends Partitioner {
   override def numPartitions : Int = numParts
 
   override def getPartition(key : Any) : Int = {
     val domain = new java.net.URL(key.toString).getHost()
     val code = (domain.hashCode % numPartitions)
     if (code < 0 ) {
       code + numPartitions
     } else {
       code
     }
   }
 
   override def equals(other : Any) : Boolean = other match {
     case iteblog : IteblogPartitioner = >
       iteblog.numPartitions == numPartitions
     case _ = >
       false
   }
 
   override def hashCode : Int = numPartitions
}

因为hashCode值可能为负数,所以我们需要对他进行处理。然后我们就可以在partitionBy()方法里面使用我们的分区:

iteblog.partitionBy( new IteblogPartitioner( 20 ))

  类似的,在Java中定义自己的分区策略和Scala类似,只需要继承org.apache.spark.Partitioner,并实现其中的方法即可。

  在Python中,你不需要扩展Partitioner类,我们只需要对iteblog.partitionBy()加上一个额外的hash函数,如下:

import urlparse
 
def iteblog_domain(url):
   return hash (urlparse.urlparse(url).netloc)
 
iteblog.partitionBy( 20 , iteblog_domain)


本文转自https://www.iteblog.com/archives/1368.html,所有权力归原作者所有,侵权请联系删除
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值