Spark求TopN值、二次排序、三次排序实现

《Spark技术应用》期末考试大作业说明:
1)个性化即在主机名、文件、程序、数据、和表结构等元素上添加自己姓名拼音缩写。
2)提交时间:xxx
3)评分规则:
a)超期提交或者不交者按缺考算,来年重修。
b)P图者0分,来年重修。
c)按个性化点的多少评分,即个性化点数越多,分数越高。
d)须在图片上对个性化点标红。
4)提交方式和内容:在钉钉群上建提交文件夹,以“学号+姓名”格式命名。
5)提交内容:大作业电子文档和源码包。

目 录 2
任务1:求top值程序个性化 2
1.1、编写用于产生随机数据的scala小程序 2
1.2、产生数据并推送到hdfs指定目录进行存储 3
1.3、使用sbt创建eclipse框架结构 3
1.4、导入程序到eclipse 5
1.5、编写TopN程序源代码 6
1.6、运行程序并观察结果 7
1.7、使用spark-submit提交程序 8
任务2:文件排序程序个性化 9
2.1、编写用于产生随机数据的scala小程序 9
2.2、产生数据并推送到本地文件系统指定目录进行存储 10
2.3、使用sbt创建eclipse框架结构 11
2.4、导入程序到eclipse 11
2.5、编写FileSort程序源代码 11
2.6、运行程序并观察结果 12
2.7、使用spark-submit提交程序 14
任务3:二次排序程序个性化 15
3.1、编写用于产生随机数据的scala小程序 16
3.2、产生数据并推送到本地文件系统指定目录进行存储 16
3.3、使用sbt创建eclipse框架结构 16
3.4、导入程序到eclipse 16
3.5、编写thirdSort程序源代码 16
3.6、运行程序并观察结果 17
3.7、程序所有类、程序jar包位置 22
个人总结 23
1、程序所需数据源问题 23
2、TopN 程序个性化思路 23
3、TopN 程序遇到的问题 23
4、FileSort 程序个性化思路 24
5、FileSort 程序遇到的问题 24
6、SecondSort 程序个性化思路 24
7、本文作者整体框架总结 24
特别声明 24

任务1:求top值程序个性化
基于ubuntukylin16.04(16)版本,完成教材141页5.4.1节求top值程序个性化。相关代码和数据参考http://dblab.xmu.edu.cn/blog/1632-2/ 。
(注:本程序已个性化成每行求最大值之后再求Top值)
1.1、编写用于产生随机数据的scala小程序
由于TopN程序需要用到固定格式的若干个文件数据,故写此程序用于自动化产生。
主要功能是:产生2-10个50-100行的数据文件,一半数据每行随机1-7列。
具体代码如图一所示。

图一 TopN随机数据scala程序图一 TopN随机数据scala程序在这里插入图片描述1.2、产生数据并推送到hdfs指定目录进行存储
我们利用之前编写好的scala程序,产生若干文件并推送到hdfs进行存储。为后续我们使用做准备。
具体操作如图二所示。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看以检查产生随机数据的质量,如图三所示。
在这里插入图片描述
1.3、使用sbt创建eclipse框架结构
在安装sbt 插件以后,可以使用 sbt eclipse 命令创建eclipse框架。
具体操作如图四所示。
在这里插入图片描述
在这里插入图片描述
安装插件:
在这里插入图片描述
查询当前sbt版本信息:
在这里插入图片描述
配置两个文件信息:
在这里插入图片描述
在这里插入图片描述
1.4、导入程序到eclipse
我们依次选择文件>导入>已存在的项目,指定项目地址即可导入。
导入示例如图四。
在这里插入图片描述
1.5、编写TopN程序源代码

课本上是求四列数据中第三列的排序。
在自定义程序之后,程序先求得每行的最大值,然后保留。
最后的每行的最大值进行排序,输出前10。
具体代码如图五所示。
在这里插入图片描述
在图六中,主要操作如下:

1.我们创建了一个求两个数最大值的函数用于后面reduce使用。
2.然后对数据进行过滤,去除空行和不等于6列的行。
3.接着对过滤后的数据进行逗号分隔拆分再将其转换为列表。
4.对列表的元素进行转换为Int型之后,进行reduce规约求每行最大值。
5.后面为了使用 sortByKey 函数将数据转化为 (key, value) 的形式。
6.使用 sortByKey 对数据进行排序(大值在上面)。
7.最后提取前10名结果并进行foreach 输出。

1.6、运行程序并观察结果

编写并保存程序之后。
在源代码上右键,点击作为scala程序运行即可提交程序。
运行结果如图六所示。

在这里插入图片描述
1.7、使用spark-submit提交程序

当我们不方便使用eclipse时,还可以将源代码进行 sbt package 打包,
然后使用spark-submit 进行提交运行。
运行结果如图七所示。
在这里插入图片描述
在这里插入图片描述
任务2:文件排序程序个性化
基于ubuntukylin16.04(16)版本,完成教材143页5.4.2节文件排序程序个性化。相关代码和数据参考http://dblab.xmu.edu.cn/blog/1632-2/ 。
(注:本程序已个性化成求文件逆序排序)
2.1、编写用于产生随机数据的scala小程序

由于FileSort程序需要用到固定格式的若干个文件数据,故写此程序用于自动化产生。
主要功能是:产生2-10个50-100行的数据文件,每行只有一个 0-999的随机数字。
具体代码见图八。

在这里插入图片描述
2.2、产生数据并推送到本地文件系统指定目录进行存储
在这里插入图片描述
查看以检查产生随机数据的质量,如图十所示。
在这里插入图片描述
2.3、使用sbt创建eclipse框架结构

使用 sbt eclipse 命令打包程序框架。
这个步骤和上述步骤几乎雷同。
2.4、导入程序到eclipse
2.5、编写FileSort程序源代码
在这里插入图片描述
2.6、运行程序并观察结果
整体结果展示:
在这里插入图片描述
在这里插入图片描述
根据课程要求,代码已进行个性化修改,现程序满足逆向排序。
由于自动化产生的输入数据较多,运行结果仅展示首位如图十五、图十六所示。
图十七是程序写入到文件的结果展示。
在这里插入图片描述
在这里插入图片描述
2.7、使用spark-submit提交程序

当我们不方便使用eclipse时,还可以将源代码进行 sbt package 打包,
然后使用spark-submit 进行提交运行。
运行结果如图十四所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
任务3:二次排序程序个性化
基于ubuntukylin16.04(16)版本,完成教材144页5.4.3节二次排序程序个性化。相关代码和数据参考http://dblab.xmu.edu.cn/blog/1632-2/ 。
(注:本程序已个性化成三次排序)

3.1、编写用于产生随机数据的scala小程序
由于三次排序使用到第三列数据的时候,要求前两列相等,
故为了提高前两列的碰撞率,将数据范围限制在了0-29之间。
具体代码如图十五所示。
在这里插入图片描述3.2、产生数据并推送到本地文件系统指定目录进行存储
在这里插入图片描述
3.3、使用sbt创建eclipse框架结构
Eclipse程序的架构同上
3.4、导入程序到eclipse
Eclipse导入程序的同上
3.5、编写thirdSort程序源代码

原程序是二次排序,在个性化过程中将其转换为了三次排序。
要想实现三次排序,需要构建比如 (thirdSortKey(3,9,1), “3 9 1”) 的键值对,
并使其成为可比较对象。
如此以来,我们便可通过 sortByKey 的方法来达到三次比较的目的。
具体代码实现如图十七和图十八。
在这里插入图片描述
在这里插入图片描述
3.6、运行程序并观察结果

在eclipse中提交程序后,结果图十九。
在这里插入图片描述
下面是eclipse和spark submit之间的运行结果展示对比:
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.7、程序所有类、程序jar包位置
在这里插入图片描述
在这里插入图片描述
个人总结
包括遇到的问题,解决方法,心得体会等一系列内容。

1、程序所需数据源问题
运行程序有数据输入输出才能显式观察程序运行状态。没有数据源就自己造数据源。
三个程序基本上都是以数字为主的数据源,可以利用scala 的scala.util.Random.nextInt 方法来实现随机数的产生,并使用 java.io._ 等方法将其写入文件以备后用。

2、TopN 程序个性化思路
在系统中,我们经常会遇到这样的需求:将大量(比如几十万、甚至上百万)的对象进行排序,然后只需要取出最Top的前N名作为排行榜的数据。
3、TopN 程序遇到的问题

在所有操作之前我们一定要记住开启hadoop + hbase

4、FileSort 程序个性化思路

FileSort 程序主要是排列多行单列单个整数,然后在前面加上索引值。
当我们个性化的时候,我们首先可以考虑逆向排序,也就是本实验报告中实现的那样。其次,你可
考虑在行后加上该整数出现的次数。这个意思就是你先执行wordcount然后排列之后前面加上索引值。
5、FileSort 程序遇到的问题

上传文件的位置一般会弄错。

6、SecondSort 程序个性化思路

SecondarySort 程序是排列两列数据,先按第一列比较,如果相同再比较第二列。
那么问题就简单了,我们可以比较三列甚至更多列。本实验报告实现的是三列,也就是三次排序。
7、本文作者整体框架总结   

那么在最后的总结中呢,我必须要对整体的结构框架做一个总结:
结构框架:1、启动hadoop + hbase
2、整理数据源
3、将数据源cp到Scala Ide for Eclipse指定的工作空间下面
这样做的好处是:
(1)方便对于Eclipse工作空间下面的包进行导入
(2)更有利于我们对于使用Spark Submit时,对程序进行无移位置打包我们前期在上Spark实验课的时候,已经将Eclipse的工作空间放置于/home/zhangaohua/workspace目录下面(以本文作者为例),这次将数据源cp到Scala Ide for Eclipse指定的工作空间下面更是有利
(3)便于记忆
4、在Eclipse中创建Scala进行运行
5、使用sbt对源码文件进行打包成jar包并展示在终端
6、整个流程容易出现的问题:eclipse经常闪退,解决方法:不要对虚拟机进行放大于缩小

特别声明:整个期末大作业我是基于学长的范文做的自己的作业,若有侵权之处还请谅解;由于是借鉴别人的东西,故坑几乎都被学长踏过,本文作者在操作过程中基本没有遇见什么问题

<think>嗯,用户的问题是关于在Spark中使用persist()和cache()来持久化RDD,同时还要统计和输出RDD元素,以及实现分组TopN的操作。首先,我需要回忆一下Spark中RDD持久化的相关知识。记得用户提到过引用[1]和引用[2],里面讲到了持久化的重要性,避免重复计算。所以,用户可能已经知道默认情况下RDD每次操作都会重新计算,但想了解如何正确使用缓存机制。 首先,用户需要定义一个列表创建RDD。这部分应该不难,用SparkContext的parallelize方法就可以。然后使用persist()或cache()进行持久化。cache()实际上是persist()的一个快捷方式,默认存储级别是MEMORY_ONLY,而persist()可以指定其他存储级别,比如MEMORY_AND_DISK。需要提醒用户注意存储级别的选择,根据数据大小和内存情况来决定。 接下来是统计元素个数,用count()方法,然后打印元素用collect()。但要注意collect()会将所有数据拉到驱动节点,如果数据量大的话可能会引起内存问题,所以需要提醒用户谨慎使用。不过用户的需是打印所有元素,所以可能数据量不大,或者只是示例。 然后是分组TopN的问题,比如每个学生的前两名成绩。这里需要用到groupByKey或者更高效的reduceByKey来处理分组。不过groupByKey可能会造成性能问题,因为所有相同键的都会被收集到一个节点,可能导致内存不足。或许应该建议使用reduceByKey结合其他方法,或者先进行映射转换,再分组。不过具体TopN实现,可能需要先按学生分组,然后对每个学生的成绩列表进行排序,取前N个。例如,使用mapValues来处理每个分组内的排序和截取。 在实现步骤中,用户可能需要先将数据转换为键对RDD,比如学生ID作为键,成绩作为。然后分组,之后对每个组内的成绩排序,取前两个。需要注意的是,排序可能是在每个分区内进行,还是全局排序,但分组后每个键对应的数据都在同一个节点上,所以可以局部排序。 另外,用户提到要输出结果,所以最后需要collect()结果打印。但同样要注意数据量的问题。 可能还需要考虑性能优化,比如在分组前进行持久化,避免重复计算。例如,如果多次使用同一个RDD进行不同的操作,持久化可以提高效率,如引用[2]中提到的加速效果。 现在需要把这些步骤具体化,写成代码示例。例如,创建RDD,使用cache()或persist(),然后进行count和collect。在分组TopN时,用groupByKey然后mapValues,或者更高效的方法,比如使用reduceByKey来维护一个TopN的列表,但这样可能比较复杂。另一种方法是使用sortBy然后取前N,但需要考虑分组后的处理。 另外,用户可能对persist()和cache()的区别不太清楚,需要解释清楚。例如,cache()是persist()的一个特例,而persist()可以指定不同的存储级别。在代码示例中,可以展示两者的使用方式,比如rdd.persist(StorageLevel.MEMORY_ONLY)或者直接rdd.cache()。 还需要注意,持久化后需要调用action操作才会真正缓存,比如count(),否则可能不会立即持久化。所以代码中应该在持久化后立即执行一个action,比如count,以触发缓存。 最后,生成的相关问题可能需要围绕持久化的优化、不同存储级别的选择、TopN的其他实现方法,或者如何处理大数据量的情况等。</think>### 在Spark中使用persist()和cache()持久化RDD及分组TopN实现 #### 一、RDD持久化与数据统计 1. **创建RDD与持久化操作** ```python from pyspark import SparkContext, StorageLevel sc = SparkContext("local", "RDD Example") # 定义列表创建RDD data = [("Alice", 85), ("Bob", 92), ("Alice", 78), ("Bob", 89), ("Charlie", 95)] rdd = sc.parallelize(data) # 使用cache()方法(默认MEMORY_ONLY) cached_rdd = rdd.cache() # 使用persist()指定存储级别 persisted_rdd = rdd.persist(StorageLevel.MEMORY_AND_DISK) ``` 2. **统计与打印元素** ```python # 统计元素个数 print("元素总数:", cached_rdd.count()) # 打印所有元素(仅适用于小数据集) print("所有元素:", cached_rdd.collect()) ``` **注意**:`persist()`需显式指定存储级别,`cache()`等价于`persist(StorageLevel.MEMORY_ONLY)`[^3]。持久化后首次触发Action操作时会进行缓存,后续操作直接复用缓存数据[^2]。 #### 二、分组TopN实现 以学生成绩数据为例,获取每个学生分数最高的前2个成绩: ```python # 按学生分组排序Top2 topn_rdd = (rdd.groupByKey() .mapValues(lambda scores: sorted(scores, reverse=True)[:2]) .sortByKey()) # 打印结果 for name, scores in topn_rdd.collect(): print(f"{name}: {scores}") ``` #### 三、性能优化建议 1. **持久化策略选择** - 内存充足时优先使用`MEMORY_ONLY` - 数据较大时使用`MEMORY_AND_DISK` - 避免使用`DISK_ONLY`(性能损失约10倍)[^2] 2. **替代`groupByKey`方案** ```python # 使用reduceByKey优化shuffle def keep_top2(acc, value): return sorted(acc + [value], reverse=True)[:2] topn_optimized = (rdd.map(lambda x: (x[0], [x[1]])) .reduceByKey(keep_top2)) ``` 此方案通过局部聚合减少网络传输量,适用于大规模数据集[^1]。 #### 四、完整示例流程 ```python # 创建RDD持久化 data = [("Alice", 85), ("Bob", 92), ("Alice", 78), ("Bob", 89), ("Charlie", 95)] rdd = sc.parallelize(data).cache() # 统计基础信息 print("总记录数:", rdd.count()) print("原始数据:", rdd.collect()) # 分组Top2 results = (rdd.groupByKey() .mapValues(lambda x: sorted(x, reverse=True)[:2]) .collect()) # 打印结果 for (name, scores) in results: print(f"{name}的最高分:{scores}") ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值