大数据词频统计实验报告

文末附github数据及代码,希望各位可以给我提一些建议,也可以对内容展开讨论。

目录

一、实验目标... 2

二、实验设计... 2

1.数据源... 2

2.实验内容... 2

3.代码模块设计... 3

三、实验流程... 3

1.本机配置信息... 3

2.配置过程中的问题... 4

3.数据下载及上传... 4

4.spark配置及spark-shell启动... 5

5.Scala编程实现... 5

6.运算... 7

7.运算结果的本地存储... 7

四、实验结果分析... 8

五、实验心得... 9

 

一、实验目标

1.使用Hadoop或者Spark对多文件数据实现词频统计

2.Hadoop分布式文件系统与本地文件系统的运算速度对比

3.spark在本地模式下不同CPU配置的运算速度对比

二、实验设计

1.数据源

为了满足大数据的要求,笔者从WOS平台上以“big data”为主题关键词搜索,在结果中下载了2000条txt格式的文献信息,作为本实验的数据。

2.实验内容

(1) Hadoop结合Spark尝试大数据统计词频

基于应用趋势,该种架构比较流行,笔者特此将两者结合起来进行实验,另外基于Spark的运算方式更为友好和高效,有Python、Java、Scala三种语言的支持,同时为了学习新的语言使用Scala进行编程实验。

(2) 分布式文件系统与本地文件系统的对比

使用Spark作为计算工具,将数据分别存储在本地和HDFS中,通过完成同样的任务进行比较。其中Spark的配置为“pyspark–master local[*]”,即采用本地模式运行,并且使用本地所有的CPU核心。

(3) spark不同配置下的运算速度对比

在本地模式下,设置CPU个数分别为2,4,8个进行运算速度比较。

3.代码模块设计

(1)多文件路径的遍历和存储模块

取得数据目录下的文件,并将其存储在可迭代的对象中,例如数组等。

(2)数据读取和转换模块

按照路径读取数据,并将所有的数据存储在一个对象中,可通过累加的方式实现。

(3)数据内容统计及存储模块

首先需要通过空格分词,然后使用特殊的类map实现对词频的统计。

(4)计时模块

使用time类实现,通过开始于结束时间的差值得到运算花费时间。

三、实验流程

1.本机配置信息

关于配置过程,厦门大学林子雨教授的流程已经非常详细,其中有问题或者没有说明的部分将在下文指出。笔者主要参考以下两篇博文:

http://dblab.xmu.edu.cn/blog/install-hadoop/

http://dblab.xmu.edu.cn/blog/1307-2/

(1)虚拟机:VMware-player-15.5.2-15785246.exe

地址:http://download3.vmware.com/software/player/file/VMware-player-15.5.2-15785246.exe

(2)Ubuntu: ubuntu-18.04.4-desktop-amd64.iso

地址:https://releases.ubuntu.com/18.04.4/ubuntu-18.04.4-desktop-amd64.iso

(3)Hadoop: hadoop-2.10.0.tar.gz

地址:http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.10.0/hadoop-2.10.0.tar.gz

(4)Spark: spark-3.0.0-preview2-bin-without-hadoop.tgz

地址:https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-3.0.0-preview2/spark-3.0.0-preview2-bin-without-hadoop.tgz

(5)Java: 11.0.7

Linxu下直接下载,此处可参考:http://dblab.xmu.edu.cn/blog/install-hadoop/

2.配置过程中的问题

(1)linux使用vim或者vi时对文件的编辑

  1. 打开文件时,初始模式为“replace”,按键盘上的“Insert”即可类似于word文件编辑模式。
  2. 需要保存和返回时,再按一遍“Insert”返回初始模式,输入“:wq”,表示保存并推出,即可完成。

(2)“Ctrl+shift+c”是linux下的复制,粘贴同理

3.数据下载及上传

使用ubtun系统中自带的火狐浏览器,前往WOS下载数据,将其存储在本地:默认为“Home//Downloads//”,修改为“Home//Downloads//data”文件夹下。同时,启动Hadoop服务,将文件夹上传至HDFS中备用。

(1)连接服务器

ssh localhost

(2)启动Hadoop服务

cd /usr/local/hadoop

./sbin/start-dfs.sh

(3)上传数据

./bin/hdfs dfs -put /usr/local/spark/mycode/wordcount/data

(4)查看数据

./bin/hdfs dfs -ls /user/hadoop/data

4.spark配置及spark-shell启动

(1)配置spark

其中local[4]指的是,使用本地模式并启动4个CPU进行计算,默认情况使用所有CPU。

cd /usr/local/spark

./bin/pyspark --master local[4]

(2)启动spark-shell

./bin/spark-shell

5.Scala编程实现

(1)文件目录的读取

1.本地文件读取较为简单,直接从绝对路径读取即可,但要注意路径的写法。

/*获取文件夹下的所有数据文件路径,返回迭代器*/

    def get_subdirs(dir: File): Iterator[File] = {

        val dir = new File("//user//hadoop//data")

              val d = dir.listFiles.filter(_.isDirectory)

              val f = dir.listFiles.toIterator

              f ++ d.toIterator.flatMap(get_subdirs _)

       }

2.HDFS文件的交互需要设计配置文件系统,才能获得HDFS下的路径。

/*1.配置HDFS文件系统*/

  def getHdfs(path: String) = {

    val conf = new Configuration()

    FileSystem.get(URI.create(path), conf)

  }

  /*2.获取路径*/

  def getFilesAndDirs(path: String): Array[Path] = {

    val fs = getHdfs(path).listStatus(new Path(path))

    FileUtil.stat2Paths(fs)

  }

  /*3.返回目录下的路径*/

  def listFiles(path: String): Array[Path] = {

    getFilesAndDirs(path).filter(getHdfs(path).getFileStatus(_).isFile())

     }

(2)文件数据的读取

为了将其转化为RDD,首先要有“import scala.io.Source”指令。其次要对返回的结果进行遍历读取。

/*读取所有文件的数据*/

    val dir = new Path("t")

    val data = sc.textFile(dir)

    for (e <- file_array){

        val t= e

        data ++ sc.textFile(t.toString)

}

(3)数据的统计

该部分,首先将RDD数据转变为map数据,同时利用空格分隔词汇,将map中的频词值相加,最终得到频词统计结果,但是为了检验结果的正确性,又将其及进行排序,输出前五的词汇,最后将统计结果存储在HDFS中。

/*统计词频*/

    val WordCount = data.

    flatMap(str=>str.split(" ")).

    filter(!_.isEmpty).

    map(word=>(word,1)).

    reduceByKey(_+_)

    /*给数据频词排序并输出*/

    val topWordCount = WordCount.map{case (word, count) => (count, word)}.sortByKey(false)

    println(topWordCount.take(5).foreach(x=>println(x)))

    /*存储数据*/

   WordCount.saveAsTextFile("hdfs://localhost:9000/user/hadoop/wordcount5")

(4)计时模块

/*计时器*/

val startTime: Long = System.currentTimeMillis

【中间程序】

/*运行时间测试*/

val endTime: Long = System.currentTimeMillis

System.out.println("程序运行时间: " + (endTime - startTime) + "ms")

6.运算

(1)scala文件的运行

这里既可以使用Spark-shell直接输入,也可以使用sbt进行运行,但需要另外的配置,笔者对sbt进行了配置,使用独立编程的方式。

(2)本地系统与HDFS系统的对比

该部分选取其中一个文件,本地系统和HDFS系统分别在Spark下进行计算,都采用默认模式。

表 1 不同存储系统处理对比对比

系统

时间(ms)

 

HDFS

3757

2806

2592

 

Local

2988

3242

2487

 

(3)不同CPU配置下的Spark运算对比

表 2 不同CPU运算速度比较

CPU数量

时间(ms)

 

8

1878

3700

1846

 

4

10585

5014

2886

 

2

3929

2049

1870

 

7.运算结果的本地存储

其中“wordcount”为输出路径,“./output”为本地存储路径,注意此时的相对路径。

cd /usr/local/hadoop

./bin/hdfs dfs -get wordcount Home./Downloads/wordscout

 

四、实验结果分析

1.HDFS并未表现出明显的速度

(1)数据量仍然过少

囿于人工下载数据,目前的数据量并没有达到使用该架构能够带来速度提升的数量级,同时还可能受到随机因素的影响(电脑内部计算进程),出现比本地文件系统速度还要慢的情况,如果要看到实际的差异,仍然需要下载大量的数据。

(2)受伪分布式限制

当前伪分布式是将分布式配置运用到机器上,但在实际计算中仍然使用一台机器计算,并没有进行并行计算,因此分布式的存储系统没有表现出高速的特性,反而在存取数据时可能影响速度。

2.CPU个数越多未表现出明显的速度提升

(1)虚拟机环境影响

虚拟机是windows系统中的一个软件,还有大量的其他软件占用CPU,其运行速度一般相比真正的服务器系统慢很多,因此Spark的配置对于结果的影响并不大。

(2)数据量过小

数据量过小的情况下,虚拟机内部并没有占用大量的计算资源,导致效果不明显。

五、实验心得

1.实践与理论之间差距较大

虽然在课堂上已经听老师讲授了各种架构背后的原理,而且网络上有大量的实践资源,但配置系统和进行实验的过程充满了挑战,如何在大量的资料中快速定位资源和学习是一个非常重要的能力,同时通过实践之后加深了对Hadoop和Spark的理解,为以后快速上手这两个大数据工具打下了基础。

2.实际问题与工具的匹配度

本实验体现出数据量与大数据架构工具的匹配性,其实这个现象的背后是实际问题与工具的匹配性,所以解决问题需要从问题实际出发,使用恰当的工具解决问题,尤其是面对技术问题时要既符合实际情况,也要符合资源分配合理的要求。