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

    package org.apache.spark

    /**
04
* An object that defines how the elements in a key-value pair RDD are partitioned by key.
05
* Maps each key to a partition ID, from 0 to `numPartitions - 1`.
06
*/ 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放到一台节点上,比如:http://www.iteblog.comhttp://www.iteblog.com/archives/1368,如果你使用HashPartitioner,这两个URL的Hash值可能不一样,这就使得这两个URL被放到不同的节点上。所以这种情况下我们就需要自定义我们的分区策略,可以如下实现:

    package com.iteblog.utils

    import org.apache.spark.Partitioner

    /**
06
* User: 过往记忆
07
* Date: 2015-05-21
08
* Time: 下午23:34
09
* bolg: http://www.iteblog.com
10
* 本文地址:http://www.iteblog.com/archives/1368
11
* 过往记忆博客,专注于hadoop、hive、spark、shark、flume的技术博客,大量的干货
12
* 过往记忆博客微信公共帐号:iteblog_hadoop
13
*/ 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 < ) { 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())

  类似的,在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(, iteblog_domain)

Spark自定义分区(Partitioner)的更多相关文章

  1. spark自定义分区器实现

    在spark中,框架默认使用的事hashPartitioner分区器进行对rdd分区,但是实际生产中,往往使用spark自带的分区器会产生数据倾斜等原因,这个时候就需要我们自定义分区,按照我们指定的字 ...

  2. 大数据入门第二十二天——spark(三)自定义分区、排序与查找

    一.自定义分区 1.概述 默认的是Hash的分区策略,这点和Hadoop是类似的,具体的分区介绍,参见:https://blog.csdn.net/high2011/article/details/6 ...

  3. 自定义实现spark的分区函数

    有时自己的业务需要自己实现spark的分区函数 以下代码是实现一个自定义spark分区的demo 实现的功能是根据key值的最后一位数字,写到不同的文件 例如: 10写入到part-00000 11写 ...

  4. MapReduce之自定义分区器Partitioner

    @ 目录 问题引出 默认Partitioner分区 自定义Partitioner步骤 Partition分区案例实操 分区总结 问题引出 要求将统计结果按照条件输出到不同文件中(分区). 比如:将统计 ...

  5. Spark API--Spark 分区

    一.分区的概念 分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务 ...

  6. 聊聊Spark的分区、并行度 —— 前奏篇

    通过之前的文章[Spark RDD详解],大家应该了解到Spark会通过DAG将一个Spark job中用到的所有RDD划分为不同的stage,每个stage内部都会有很多子任务处理数据,而每个sta ...

  7. kafka 自定义分区器

    package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.Partitioner; import org.a ...

  8. Kafka的接口回调 +自定义分区、拦截器

    一.接口回调+自定义分区 1.接口回调:在使用消费者的send方法时添加Callback回调 producer.send(new ProducerRecord<String, String> ...

  9. [MapReduce_8] MapReduce 中的自定义分区实现

    0. 说明 设置分区数量 && 编写自定义分区代码 1. 设置分区数量 分区(Partition) 分区决定了指定的 Key 进入到哪个 Reduce 中 分区目的:把相同的 Key ...

随机推荐

  1. Matlab学习:读取指定文件夹及其五级子文件夹内的文件

    OpenCV2.4.X版本提供了三个函数来读取指定目录内的文件,它们分别是: (1)GetListFiles:读取指定目录内所有文件,不包含子目录: (2)GetListFilesR:读取指定目录及其 ...

  2. mssqlserver 查询数据库表结构语句

    查询指定表结构的表名.列名.类型.说明.字段长度 select o.name as tableName,c.name as columnName,t.name as columnType,p.valu ...

  3. sqoop安装

    环境:Hadoop 2.3.0 sqoop 1.4.5 1.下载并解压sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz (解压完,名字会很长,可以根据需要自己修改下 ...

  4. centos6.5网络配置问题:ping不通

    遇到的问题:win7网卡ping不通 win7中的VMnet8信息 centos6.5设置: /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 ...

  5. Android开发-Hello World+phonegap(Cordova)

    想着把IOS的程序在Android上实现一下,尝试Android开发,结果发现Android的开发环境也不好弄.接下来记录下整个过程,耳熟能详的操作就不再赘述,重点记录个人特别的经历: 一.安装jav ...

  6. JAVA Socket:文件传输

    客户端:读取文件(FileInputStream),发送文件(OutputStream) 服务器端:接收文件(InputStream),写文件(FileOutputStream) 客户端代码: pac ...

  7. 使用kendoui对grid指定行变色

    关键点在于绑定数据源后进行判断,可直接获取当前绑定对象的属性 dataBound: function () { dataView = this.dataSource.view(); ; i < ...

  8. android 数据存储----文件方式 总结

    在android中的文件放在不同位置,它们的读取方式也有一些不同. 本文对android中对资源文件的读取.数据区文件的读取.SD卡文件的读取及RandomAccessFile的方式和方法进行了整理. ...

  9. C and C++ 如何嵌套使用

    1. 要知道extern "C"的含义: (1) extern是C/C++中表明函数和全局变量作用范围的关键字, 该关键字表明其申明的函数和变量可以在本模块或者其他模块中使用. ( ...

  10. 【转】appium_python_API文档

    1.contextscontexts(self): Returns the contexts within the current session. 返回当前会话中的上下文,使用后可以识别H5页面的控 ...