65.9K
CodeProject 正在变化。 阅读更多。
Home

大数据 MapReduce Hadoop Scala 在 Ubuntu Linux 上通过 Maven intellj Idea

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (13投票s)

2017年9月9日

CPOL

8分钟阅读

viewsIcon

32535

downloadIcon

197

本文是最全面的大数据从零到实战的文章。

引言

我想开始在网上浏览大数据相关内容,但我找不到一篇从头到尾解释这个过程的完整文章。每篇文章都只描述了这个巨大概念的一部分。我感到缺乏一篇全面的文章,于是决定写下这篇论文。

如今,我们面临着数据量不断增长的现象。我们希望长期保存所有这些数据,并高速处理和分析它们,这催生了构建良好解决方案的需求。对于数据科学家来说,找到一种合适的替代传统数据库的解决方案,以存储任何类型的结构化和非结构化数据,是最具挑战性的事情。

我选择了一个完整的场景,从第一步到结果,这在互联网上很难找到。我选择了 MapReduce,它是通过 hadoop 和 scala 在 intellij idea 中处理数据,而这一切故事都将在 ubuntu Linux 操作系统下发生。

什么是大数据?

大数据是指海量、庞大的结构化、非结构化或半结构化数据,用传统数据库难以存储和管理。其体积从 TB 到 PB 不等。关系型数据库(如 SQL Server)不适用于存储非结构化数据。正如您在下图中所见,大数据是指所有类型的结构化或非结构化数据的集合,它具有存储、管理、共享、分析等基本要求。

什么是 Hadoop?

事实上,我们对所有数据库都寄予两种期望。首先,我们需要存储数据;其次,我们希望以快速准确的方式正确处理已存储的数据。由于大数据的任意形状和巨大体积,无法将其存储在传统数据库中。我们需要考虑一种新的数据库,它能够同时处理大数据的存储和处理。

Hadoop 是一种革命性的大数据数据库,能够存储任何形状的数据并在节点集群中进行处理。它还极大地降低了数据维护成本。借助 hadoop,我们可以长期存储任何类型的数据,例如所有用户点击。这使得历史分析变得容易。Hadoop 具有分布式存储和分布式处理系统,如 Map Reduce。

正如您在下面的图片中看到的,数据库有两个不同的期望职责。左边是存储,这是开始步骤,然后右边是处理。Hadoop 是一种创新的数据库,与传统和关系型数据库不同。Hadoop 在多个机器的集群中运行,每个集群包含许多节点。

什么是 Hadoop 生态系统?

正如我上面提到的,hadoop 既适合存储非结构化数据库,也适合处理它们。hadoop 生态系统有一个抽象的定义。数据存储在左侧,有两种不同的存储可能性:HDFS 和 HBase。HBase 建立在 HDFS 之上,两者都是用 Java 编写的。

HDFS

  1. Hadoop 分布式文件系统允许在分布式平面文件中存储大数据。
  2. HDFS 适合对数据进行顺序访问。
  3. 它不支持随机实时读/写访问数据。它更适合离线批处理。

HBase

  1. 以键/值对的形式以列式存储数据。
  2. HBase 具有实时读/写的能力。

Hadoop 是用 Java 编写的,但您也可以使用 R、Python、Ruby 实现。

Spark 是一个开源集群计算框架,用 Scala 实现,适合支持分布式计算上的作业迭代。Spark 具有高性能。

Hive、Pig、Sqoop 和 Mahout 是数据访问工具,它们使得对数据库进行查询成为可能。Hive 和 Pig 类似于 SQL;Mahout 用于机器学习。

MapReduce 和 Yarn 都用于处理数据。MapReduce 被设计用于在分布式系统中处理数据。MapReduce 可以处理作业和任务跟踪器、监控和并行执行等所有任务。Yarn,Yet Another Resource Negotiator,是 MapReduce 2.0,具有更好的资源管理和调度能力。

Sqoop 是一个连接器,用于从外部数据库导入和导出数据。它能够以并行方式轻松快速地传输数据。

Hadoop 是如何工作的?

Hadoop 遵循主/从架构模型。对于 HDFS,主节点 NameNode 负责监控并跟踪所有从节点,这些从节点是一组存储集群。

MapReduce 处理涉及两种不同类型的作业。Map 作业将查询发送到集群中的各个节点进行处理。这个作业会被分解成更小的任务。然后 Reduce 作业收集每个节点产生的所有输出,并将它们组合成一个单一的值作为最终结果。

这种架构使 Hadoop 成为一个廉价、快速且可靠的解决方案。它将大的作业分解成小的作业,并将每个任务放在不同的节点上。这个过程可能会让您想起多线程。在多线程中,所有并发进程都通过锁和信号量共享,但 MapReduce 中的数据访问受 HDFS 控制。

准备动手实践

到目前为止,我们已经介绍了 Hadoop 和大数据的抽象含义。现在是时候深入研究并创建一个实际项目了。我们需要准备一些满足我们需求的硬件。

硬件

  1. 内存:8 GB
  2. 硬盘剩余空间:50 GB

软件

  1. 操作系统:Windows 10 - 64 位
  2. Oracle Virtual Machine VirtualBox
  3. Linux-ubuntu 17.04
  4. Jdk-8
  5. Ssh
  6. Hadoop
  7. Hadoop jar
  8. Intellij idea
  9. Maven
  10. 编写 Scala 代码或 wordcount 示例

1. 操作系统:Windows 10 - 64 位

如果您还没有 Win 10 并想升级您的操作系统,请访问以下链接立即获取:

2. Oracle Virtual Machine VirtualBox

请访问 此链接,点击 Windows hosts 并下载最新版本的 virtual box。然后按照以下说明操作:

3. Linux-ubuntu 17.04

请访问 此链接,点击 64 位并下载最新版本的 ubuntu。然后按照以下说明操作:

点击“新建”来为新操作系统(Linux/Ubuntu 64 位)创建一个新的虚拟机。

在下面的图片中,您应该为新操作系统分配内存。

在下面的图片中,您应该为新操作系统分配硬盘。

现在,是时候选择您的 ubuntu 17 了,它是 .iso 格式。请选择“ubuntu-17.04-desktop-amd64”。

现在,双击新创建的 vm 并开始安装。

选择您的语言,然后点击“安装 Ubuntu”。

在下面的图片中,您指定了您的身份,因此这是第一个可以使用 ubuntu 的用户。

sudo apt-get install update

如果您看到以下错误,让我们尝试使用以下两种解决方案之一:

解决方案一

sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock

解决方案二

sudo systemctl stop apt-daily.timer
sudo systemctl start apt-daily.timer

然后再次尝试

sudo apt-get install update

让我们为 hadoop 创建一个新用户和组。

sudo addgroup hadoop 

将用户添加到组

sudo adduser --ingroup hadoop hduser

输入您的详细信息,然后按“y”进行保存。

4. 安装 JDK

sudo apt-get update
java -version
sudo apt-get install default-jre

5. 安装 open-ssh 协议

OpenSSH 通过使用 SSH 协议在网络上提供安全和加密的通信。问题是,为什么我们要使用 openssh?这是因为 hadoop 需要密码才能允许访问其节点。

sudo apt-get install openssh-server

ssh-keygen -t rsa -P ''

运行上述代码后,如果您被要求输入文件名,请将其留空并按 Enter 键。

然后尝试运行

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

如果您遇到“文件或目录不存在”错误,请按照以下说明操作:

运行“cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys” -> 错误:“No such file or directory”

  1. mkdir ~/.ssh
  2. chhmod 700 ~/.ssh
  3. touch ~/.ssh/authorized_keys
  4. chmod 600 ~/.ssh/authorized_keys
  5. touch ~/.ssh/id_rsa.pub
  6. chmod 600 ~/.ssh/id_rsa.pub

6. 安装 Hadoop

首先,您应该使用以下代码下载 hadoop:

wget http://apache.cs.utah.edu/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz

提取 hadoop 文件

tar xzf hadoop-2.7.1.tar.gz 

查找 Java 路径

update-alternatives --config java

/jre 之后的所有内容都是您的 Java 路径。

1. 编辑 ~/.bashrc

nano ~/.bashrc

上面的代码行将打开 addop-ev.sh,滚动到文件末尾,找到 java-home 并以硬编码的 Java 路径输入,该路径您通过“update-alternatives --config java”找到。

然后,在最后,输入以下行:

#HADOOP VARIABLES START
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_INSTALL=/home/mahsa/hadoop-2.7.1
export PATH=$PATH:$HADOOP_INSTALL/bin
export PATH=$PATH:$HADOOP_INSTALL/sbin
export HADOOP_MAPRED_HOME=$HADOOP_INSTALL
export HADOOP_COMMON_HOME=$HADOOP_INSTALL
export HADOOP_HDFS_HOME=$HADOOP_INSTALL
export YARN_HOME=$HADOOP_INSTALL
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_INSTALL/lib/native
export HADOOP_OPTS=”-Djava.library.path= $HADOOP_INSTALL/lib/native”
#HADOOP VARIABLES END

还应硬编码 Java 主目录,例如:

要关闭并保存文件,请按“ctl+X”,当提示保存时按“y”,当提示更改文件名时,只需按“Enter”即可,不要更改文件名。

为了确认您的上述操作,让我们执行:

source ~/.bashrc

2. 编辑 hadoop-env.sh

sudo nano /home/mahsa/hadoop-2.7.1/etc/hadoop/hadoop-env.sh

在文件末尾写入:

<property>
   <name>fs.default.name</name>
   <value>hdfs://:9000</value>
</property>

3. 编辑 yarn-site.xml

sudo nano /home/mahsa/hadoop-2.7.1/etc/hadoop/yarn-site.xml

在文件末尾写入:

<property>
   <name>yarn.nodemanager.aux-services</name>
   <value>mapreduce_shuffle</value>
</property>
<property>
   <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
   <value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>

4. 编辑 mapred-site.xml

cp /home/mahsa/hadoop-2.7.1/etc/hadoop/mapred-site.xml.template 
   /home/mahsa/hadoop-2.7.1/etc/hadoop/mapred-site.xml

sudo nano /home/mahsa/hadoop-2.7.1/etc/hadoop/mapred-site.xml

<property>
   <name>mapreduce.framework.name</name>
   <value>yarn</value>
</property>

5. 编辑 hdfs

mkdir -p /home/mahsa/hadoop_store/hdfs/namenode

mkdir -p /home/mahsa/hadoop_store/hdfs/datanode

sudo nano /home/mahsa/hadoop-2.7.1/etc/hadoop/hdfs-site.xml

<property>
   <name>dfs.replication</name>
   <value>1</value>
</property>
<property>
   <name>dfs.namenode.name.dir</name>
   <value>file:/home/mahsa/hadoop_store/hdfs/namenode</value>
</property>
<property>
   <name>dfs.datanode.data.dir</name>
   <value>file:/home/mahsa/hadoop_store/hdfs/datanode</value>
</property>

6. 格式化

hdfs namenode -format

start-dfs.sh

start-yarn.sh

通过运行“jps”,您可以确保 hadoop 已正确安装。

jps

6. 安装 Intellij Idea

MapReduce 的实现有两种可能性:一种是 scala-sbt,另一种是 maven。我想描述这两种方法。首先是 scala-sbt

7. 安装 Maven

下面的图片中有三个文本文件用于练习 word count。MapReduce 开始将每个文件拆分到节点集群中,正如我在本文开头解释的那样。在 Map 阶段,每个节点负责计算单词。在每个节点上的中间拆分只是同质单词,并且在前一个节点中该特定单词的数量。然后在 Reduce 阶段,每个节点将被求和,并将其自己的结果收集起来以生成单个值。

在下面的弹窗图片中,您必须点击“Enable Auto Import”,它将处理所有库。

转到菜单“Run” -> 选择“Edit Configurations

  1. 选择“Application
  2. 选择 Main Class = “App
  3. 将参数设置为:“input/ output/

您只需要创建一个名为“input”的目录,输出目录将由 intellij 创建。

运行应用程序后,您将看到两个文件:

  1. _SUCCESS
  2. part-r-00000

如果您打开“part-r-00000”,您将看到如下结果:

  • moon 2
  • sun 3
  • day 3
  • night 3

Using the Code

-package bigdata.mahsa;

/**
* wordcount!
*
*/
        import org.apache.hadoop.conf.Configuration;
        import org.apache.hadoop.conf.Configured;
        import org.apache.hadoop.fs.Path;
        import org.apache.hadoop.io.IntWritable;
        import org.apache.hadoop.io.LongWritable;
        import org.apache.hadoop.io.Text;
        import org.apache.hadoop.mapreduce.Job;
        import org.apache.hadoop.mapreduce.Mapper;
        import org.apache.hadoop.mapreduce.Reducer;
        import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
        import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
        import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
        import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
        import org.apache.hadoop.util.Tool;
        import org.apache.hadoop.util.ToolRunner;

        import java.io.IOException;
        import java.util.StringTokenizer;

public class App extends Configured implements Tool {

    public static class Mapper extends Mapper<LongWritable, Text, Text, IntWritable> {
        private static final IntWritable ONE = new IntWritable(1);
        private final transient Text word = new Text();

        @Override public void map
        (final LongWritable key, final Text value, final Context context)
                throws IOException, InterruptedException {
            final String line = value.toString();
            final StringTokenizer tokenizer = new StringTokenizer(line);
            while (tokenizer.hasMoreTokens()) {  //splitting
                   word.set(tokenizer.nextToken());
                context.write(word, ONE);
            }
        }
    }

    public static class Reducer extends Reducer<Text, IntWritable, Text, IntWritable> {

        @Override
        public void reduce(final Text key, final Iterable<IntWritable> values, 
                           final Context context)
                throws IOException, InterruptedException {
            int sumofword = 0;
            for (final IntWritable val : values) {
                sum += val.get();
            }
            context.write(key, new IntWritable(sumofword));
        }
    }

    @Override public int run(final String[] args) throws Exception {
        final Configuration conf = this.getConf();
        final Job job = Job.getInstance(conf, "Word Count");
        job.setJarByClass(WordCount.class);

        job.setMapperClass(Mapper.class);
        job.setReducerClass(Reducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));  // ** get text from input
        FileOutputFormat.setOutputPath(job, new Path(args[1])); // ** write result to output

return job.waitForCompletion(true) ? 0 : 1;
    }

    public static void main(final String[] args) throws Exception {
        final int result = ToolRunner.run(new Configuration(), new App(), args);
        System.exit(result);
    }
}

Pom.xml

<project xmlns="<a data-saferedirecturl="https://www.google.com/url?
hl=en&q=http://maven.apache.org/POM/4.0.0&source=gmail&ust=1505079008271000&
usg=AFQjCNELhZ47SF18clzvYehUc2tFtF4L1Q" href="http://maven.apache.org/POM/4.0.0" 
target="_blank">http://maven.apache.org/POM/4.0.0</a>" 
xmlns:xsi="<a data-saferedirecturl="https://www.google.com/url?
hl=en&q=http://www.w3.org/2001/XMLSchema-instance&source=gmail&
ust=1505079008271000&usg=AFQjCNFD9yHHFr1eQUhTqHt1em3OxoDqEg" 
href="http://www.w3.org/2001/XMLSchema-instance" target="_blank">
http://www.w3.org/2001/XMLSchema-instance</a>"
xsi:schemaLocation="<a data-saferedirecturl="https://www.google.com/url?
hl=en&q=http://maven.apache.org/POM/4.0.0&source=gmail&ust=1505079008271000&
usg=AFQjCNELhZ47SF18clzvYehUc2tFtF4L1Q" href="http://maven.apache.org/POM/4.0.0" 
target="_blank">http://maven.apache.org/POM/4.0.0</a> 
<a data-saferedirecturl="https://www.google.com/url?hl=en&
q=http://maven.apache.org/xsd/maven-4.0.0.xsd&source=gmail&ust=1505079008271000&
usg=AFQjCNF31lT_EYlu0SxGI9EvuhtJcJ9Y0w" href="http://maven.apache.org/xsd/maven-4.0.0.xsd" 
target="_blank">http://maven.apache.org/xsd/maven-4.0.0.xsd</a>">
  <modelVersion>4.0.0</modelVersion>

  <groupId>bigdata.mahsa</groupId>
  <artifactId>App</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>wordcount</name>
  <url><a data-saferedirecturl="https://www.google.com/url?hl=en&
q=http://maven.apache.org&source=gmail&ust=1505079008271000&
usg=AFQjCNHfdU8bl-1WzHoSKompqgsFvDc6cA" href="http://maven.apache.org/" 
target="_blank">http://maven.apache.org</a></url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hadoop.version>2.6.0</hadoop.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>2.7.1</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.pluginsplugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>bigdata.mahsa.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

反馈

请随时对本文发表任何反馈;很高兴看到您的意见和对该代码的**投票**。如果您有任何问题,请随时在此处提问。

历史

  • 2017年9月9日:初始版本
© . All rights reserved.