Spark大数据处理学习笔记(3.3)掌握RDD分区

news2024/10/7 16:17:31

该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/OmCQ8】


文章目录

  • 一、概念
  • 二、自定义分区器
    • 2.1 提出问题
    • 2.2 解决问题
      • 1. 准备数据文件
      • 2. 新建科目分区器
      • 3. 测试科目分区器
  • 三、课后作业


一、概念

  • 在Spark中,RDD(弹性分布式数据集)是一种基本的数据结构,可以在集群上并行处理数据。RDD的分区(Partition)是数据的逻辑划分单元,它决定了数据在集群中的分布和并行处理的方式。掌握RDD分区的设计和调整对于优化Spark应用程序的性能至关重要。以下是关于RDD分区的一些重要概念和建议:

  • 分区类型:Spark提供了多种分区类型,如Hash分区、Range分区和自定义分区等。Hash分区是最常用的分区策略,它根据键的哈希值将数据均匀分配到不同的分区中。Range分区按照键的范围将数据排序分区,适用于范围查询和排序操作。自定义分区允许开发人员根据自己的需求定义特定的分区策略。

  • 分区数目:RDD的分区数目是决定并行处理程度的重要因素。合理设置分区数目可以充分利用集群资源,提高计算性能。分区数目应该与集群的核心数目和可用内存相匹配,通常建议设置为集群核心数目的两倍或更多。

  • 分区操作:在进行RDD的转换操作时,分区数目可能会发生变化。一些操作(如map、filter和flatMap等)保持原有分区数目不变,而一些操作(如reduceByKey和groupByKey等)会进行重新分区。在转换操作中,需要注意操作的影响,避免出现数据倾斜或不均匀的情况。

  • 分区调整:在某些情况下,可能需要手动调整RDD的分区,以优化数据的分布和并行计算。可以使用repartition和coalesce等操作来重新分区。repartition操作会进行全量的数据洗牌,适用于需要完全重新分区的情况。而coalesce操作只会合并部分分区,适用于减少分区数目而不进行完全洗牌的情况。

  • 数据倾斜处理:在处理大规模数据时,可能会出现数据倾斜(Data Skew)的情况,即某些分区的数据量远大于其他分区。数据倾斜会导致计算不均衡和性能下降。对于数据倾斜的RDD,可以考虑采取一些特殊的处理策略,如使用repartition操作进行重新分区、使用reduceByKey替换groupByKey等。

  • 总的来说,掌握RDD分区的设计和调整是优化Spark应用程序性能的关键。通过合理设置分区数目、选择适当的分区策略、注意分区操作和处理数据倾斜等技巧,可以充分发挥Spark的并行计算能力,提高应用程序的效率和可扩展性。

二、自定义分区器

2.1 提出问题

  • 例如,某学生有以下3科三个月的月考成绩数据。
    在这里插入图片描述
  • 现需要将每一科成绩单独分配到一个分区中,然后将3科成绩输出到HDFS的指定目录(每个分区对应一个结果文件),此时就需要对数据进行自定义分区。

2.2 解决问题

1. 准备数据文件

  • master虚拟机的/home目录里创建marks.txt
    在这里插入图片描述
  • 将数据文件上传到HDFS指定目录
    在这里插入图片描述

2. 新建科目分区器

  • 创建cn.kox.rdd.day04包,在包里创建SubjectPartitioner
    在这里插入图片描述
package cn.kox.rdd.day04

import org.apache.spark.Partitioner
/**
 * @ClassName: SubjectPartitioner
 * @Author: Kox
 * @Data: 2023/6/15
 * @Sketch:
 */
class SubjectPartitioner(partitions: Int) extends Partitioner {
  /**
   * @return 分区数量
   */
  override def numPartitions: Int = partitions

  /**
   * @param key(科目)
   * @return 分区索引
   */
  override def getPartition(key: Any): Int = {
    val partitionIndex = key.toString match {
      case "chinese" => 0
      case "math" => 1
      case "english" => 2
    }
    partitionIndex
  }
}

3. 测试科目分区器

  • cn.kox.rdd.day04包里创建TestSubjectPartitioner单例对象
    在这里插入图片描述
package cn.kox.rdd.day04

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
 * @ClassName: TestSubjectPartitioner
 * @Author: Kox
 * @Data: 2023/6/15
 * @Sketch:
 */
object TestSubjectPartitioner {
  def main(args: Array[String]): Unit = {
    // 创建Spark配置对象
    val conf = new SparkConf()
      .setAppName("TestSubjectPartitioner") // 设置应用名称
      .setMaster("local[*]") // 设置主节点位置(本地调试)
    // 基于Spark配置对象创建Spark容器
    val sc = new SparkContext(conf)
    // 读取HDFS文件,生成RDD
    val lines = sc.textFile("hdfs://master:9000/partition/input/marks.txt")
    // 将每行数据映射成(科目,成绩)二元组
    val data: RDD[(String, Int)] = lines.map(line => {
      val fields = line.split(" ")
      (fields(0), fields(1).toInt) // (科目,成绩)
    })
    // 将数据按科目分区器重新分区
    val partitionData = data.partitionBy(new SubjectPartitioner(3))
    // 在控制台输出分区数据
    partitionData.collect.foreach(println)
    // 保存分区数据到HDFS指定目录
    partitionData.saveAsTextFile("hdfs://master:9000/partition/output")
  }
}

  • 运行程序,查看结果
    在这里插入图片描述
  • 查看HDFS的结果文件
    在这里插入图片描述

三、课后作业

在这里插入图片描述

package cn.kox.rdd.day04

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

/**
 * @ClassName: TestSubjectPartitioner
 * @Author: Kox
 * @Data: 2023/6/15
 * @Sketch:
 */
object TestSubjectPartitioner {
  def main(args: Array[String]): Unit = {
    // 创建Spark配置对象
    val conf = new SparkConf()
      .setAppName("TestSubjectPartitioner") // 设置应用名称
      .setMaster("local[*]") // 设置主节点位置(本地调试)
    // 基于Spark配置对象创建Spark容器
    val sc = new SparkContext(conf)
    // 读取HDFS文件,生成RDD
    val lines = sc.textFile("hdfs://master:9000/partition/input/marks.txt")
    // 将每行数据映射成(科目,成绩)二元组
    val data: RDD[(String, Int)] = lines.map(line => {
      val fields = line.split(" ")
      (fields(0), fields(1).toInt) // (科目,成绩)
    })
    // 将数据按科目分区器重新分区
    val partitionData = data.partitionBy(new SubjectPartitioner(3))
    // 计算每个科目的总分和平均分
    val result = partitionData
      .mapValues(score => (score, 1)) // 将每个成绩映射为(成绩, 1)
      .reduceByKey { case ((score1, count1), (score2, count2)) =>
        (score1 + score2, count1 + count2) // 按科目进行成绩求和和计数
      }
      .map { case (subject, (totalScore, count)) =>
        val average = totalScore.toDouble / count.toDouble // 计算平均分
        val formattedAverage = f"%%.2f".format(average) // 格式化平均分保留两位小数
        (subject, totalScore, formattedAverage)
      }
    // 输出结果
    result.foreach(println)
  }
}


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/650223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

长文|基于Zabbix的可观测性监控

01 可观测性与可观测性监控 02 基于ZABBIX的可观测性监控 03 可观测性监控的探索 ——王小东,多年运维老兵,《nginx应用与运维实战》作者 本文整理自王小东在2022Zabbix峰会演讲分享。ppt可在公众号后台回复“ppt"。 1、可观测性与可观测性监控…

拷贝构造函数

拷贝构造函数 以值传递的方式调用函数时,如果实参为对象,会调用拷贝构造函数。函数以值的方式返回对象时,可能会调用拷贝构造函数(VS会调用,Linux不会,g编译器做了优化) 类似于构造函数和析构函…

Python控制流程盘点及高级用法、神秘技巧大揭秘!

在这篇文章中我们将全面深入地介绍 Python 的控制流程,包括条件语句、循环结构和异常处理等关键部分,尤其会将列表解析、生成器、装饰器等高级用法一网打尽。此外,我还将分享一些独特的见解和研究发现,希望能给你带来新的启发。文…

让你不再疑惑图片翻译怎么弄

你是否曾遇到过在阅读外语文章或资料时,遇到了图片上的文字无法翻译的困扰?别担心,如果你还不知道如何翻译图片上的文字的话,接下来我将教你三种图片翻译的实用小技巧,一起来看看吧。 翻译图片的实用方法一&#xff1a…

Python语法基础01(列表,元组,字典)

Python基础语法 变量的命名与使用 变量名只能包含字母、数字和下划线,只能以字母和下划线为开头不能包含空格不能使用python保留字 列表,元组,字典 列表 定义列表(元素之间可以没有任何关系):[] 例如 fruits["apple&qu…

oracle如何才能卸载干净

windows系统下oracle如何才能卸载干净 1.关闭oracle所有的服务。2.删除注册表中相关信息3.删除注册表中相关Oracle安装信息4.删除注册的oracle事件日志5.删除环境变量path中关于oracle的内容6.重新启动操作系统7.删除Oracle_Home下的所有数据8.删除oracle安装目录。9.删除开始菜…

灰度图像逻辑运算之逻辑或

目录 note code test note out max(x1,x2) code void img_logic_or_fun(uchar& in1, uchar& in2, uchar& out) {out in1 > in2 ? in1 : in2; } void img_logic_or(Mat& src1, Mat& src2, Mat& res) {if (src1.size() ! src2.size()) {retur…

基于html+css的图展示128

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【微信支付】微信v3支付案例,SpringBoot集成IJPay实现微信v3支付

前言 这篇文章主要实现一下通过IJPay来实现微信v3支付案例&#xff0c;本篇文章使用的是JSAPI即小程序支付 IJPay码云仓库&#xff1a;https://gitee.com/javen205/IJPay/tree/dev IJPay官方文档&#xff1a;https://javen205.gitee.io/ijpay/ 准备工作 导入依赖 <depen…

Python学习48:简易英汉字典

类型&#xff1a;字典‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 描述‪‬‪‬…

SpringBoot+Mybatis 实现长字符串保存和更新

数据库字段&#xff0c;写成长字符 插入xml&#xff0c;注意两个点&#xff0c;否则会报错 1、长字符串字段不能写if判断&#xff1a;<if test"name ! null and name ! "> 2、插入的时候做字符串转码&#xff1a;<![CDATA[#{fileCode}]]> <insert …

验证FeignClient类型:FeignClient集成OkHttp

验证FeignClient类型 验证FeignClient类型 验证FeignClient类型 在SynchronousMethodHandler类中查看client类型

【自监督学习1】SimCLR论文阅读

文章目录 一、摘要二、引言三、方法3.1 主要框架3.2 训练一个大的batchsize 四、数据增强4.1 实验一 数据增强的组合对学习好的特征表达非常重要4.2 对比学习需要更多的数据增强 五、一些实验证明5.1 大模型更有利于无监督对比学习5.2 非线性层的预测头增加了特征表示5.3可调节…

字符设备实现内部驱动原理及分步注册流程

字符设备实现内部驱动原理&#xff1a; 应用层&#xff1a;open函数回调到驱动中open操作方法的路线&#xff1a; open&#xff08;&#xff09;--->sys_open()--->struct inode结构体--->struct cdev结构体--->struct file_operations结构体--->mycdev_open()…

RVEA多目标优化

A Reference Vector Guided Evolutionary Algorithm for Many-objective Optimization 目标函数预备知识参考向量引导选择更新参考向量流程整体框架参考向量引导选择参考向量自适应 for Many-objective Optimization) 目标函数 min ⁡ X f ( X ) ( f 1 ( X ) , f 2 ( X ) , . …

游泳耳机买什么牌子好一点?推荐四款出色的游泳耳机

游泳和跑步类似&#xff0c;短距离冲刺时&#xff0c;大脑没什么想法&#xff0c;而中长距离的有氧运动时&#xff0c;肉体是疲惫的&#xff0c;大脑是异常清晰的&#xff0c;时间却是格外难熬的。如何打发时间&#xff0c;让游泳锻炼变得不无聊&#xff0c;这是我从孩子时期就…

从零开始 Spring Boot 41:事件

从零开始 Spring Boot 41&#xff1a;事件 图源&#xff1a;简书 (jianshu.com) Spring 实现了一个简单、实用的事件框架&#xff0c;利用它我们可以在多个组件之间进行松耦合式的通信。 简单示例 让我们从一个简单的示例开始&#xff1a; public record Email(String addr…

sqli-labs靶场通关(21-30)

Less-21 还是adminadmin登录 可以看出uname是base64加密过的&#xff0c;解码得到&#xff1a;admin。 那么本关和less-20相似&#xff0c;只是cookie的uname值经过base64编码了。 抓包看一下也是如此 那么我们只需要上传paylaod的时候base64加密一下就可以了 base64加密工…

多线程-线程的创建的方式3、4:实现Callable与线程池

JDK5.0新增线程创建方式 简要概况&#xff1a; 1. 创建多线程的方式三&#xff1a;实现Callable&#xff08;jdk5.0新增的&#xff09;与之前的方式的对比&#xff1a;与Runnable方式的对比的好处 > call()可以有返回值&#xff0c;更灵活 > call()可以使用throws的方式…

模板模式(十六)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了代理模式(十五), 如果没有看过, 请观看上一章 一. 模板模式 引用 菜鸟教程里面的 模板模式介绍: https://www.runoob.com/design-pattern/template-pattern.html 在模板模式&#xff08;Template Pattern&#xff09;…