Hadoop安装以及基本操作

Hadoop安装以及基本操作

一,Hadoop的安裝(Mac)

下載Hadoop https://archive.apache.org/dist/hadoop/core/到自定義目錄下 ,我這邊下載的是hadoop-2.4.0版本,下載到/usr/local/目錄下。

1.1環境配置

先通過 .bash_profile添加環境變量

sudo vim ~/.bash_profile

# hadoop
export HADOOP_HOME=/usr/local/hadoop-2.4.0
export HADOOP_INSTALL=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib"
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin

然後使添加的環境變量生效

source ~/.bash_profile

此時就可以通過Hadoop命令查看版本信息:

hadoop version

1.2 修改配置環境

需要修改的 Hadoop 配置文件都在/usr/local/hadoop-2.4.0/etc/hadoop/`下,包括:

  • hadoop-env.sh
  • core-site.xml
  • hdfs-site.xml
  • mapred-site.xml
  • yarn-site.xml

1.2.1 hadoop-env.sh

修改hadoop-env.sh文件主要是為了配置java路徑

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/

1.2.2 core-site.xml

​ 默认情况下,Hadoop 将数据保存在/tmp 下,当重启系统时,/tmp 中的内容将被自动清空, 所以我们需要制定自己的一个 Hadoop 的目录,用来存放数据。另外需要配置 Hadoop 所使用的默认文件系统,以及 Namenode 进程所在的主机。

修改core-site.xml,在configuration標籤內添加屬性:

<property>
     <name>fs.defaultFS</name>
     <value>hdfs://localhost:9000</value>
  </property>
  <!--用来指定hadoop运行时产生文件的存放目录  自己创建-->
  <property>
     <name>hadoop.tmp.dir</name>
     <value>file://usr/local/hadoop-2.4.0/tmp</value>
  </property>
  <property>
     <name>fs.trash.interval</name>
     <value>1440</value>
  </property>

1.2.3 hdfs-site.xml

​ 该文件指定与 HDFS 相关的配置信息。需要修改 HDFS 默认的块的副本属性,因为 HDFS 默认 情况下每个数据块保存 3 个副本,而在伪分布式模式下运行时,由于只有一个数据节点,所 以需要将副本个数改为 1;否则 Hadoop 程序会报错。

​ 修改hdfs-site.xml,在configuration標籤內添加屬性:

<property>
     <name>dfs.replication</name>
     <value>1</value>
  </property>
  <!--不是root用户也可以写文件到hdfs-->
  <property>
     <name>dfs.permissions</name>
     <value>false</value>    <!--关闭防火墙-->
  </property>
  <!-- name node 存放 name table 的目录 -->
  <property>
     <name>dfs.namenode.name.dir</name>
     <value>file:/usr/local/hadoop-2.4.0/tmp/dfs/name</value>
  </property>
  <!-- data node 存放数据 block 的目录 -->
  <property>
     <name>dfs.datanode.data.dir</name>
     <value>file:/usr/local/hadoop-2.4.0/tmp/dfs/data</value>
  </property>

1.2.4 mapred-site.xml

​ 在该配置文件中指定与 MapReduce 作业相关的配置属性,需要指定 JobTracker 运行的主机 文件夹中并没有 mapred-site.xml 文件,但提供了模板 mapred-site.xml.template 将其copy另存为 mapred-site.xml 即可

cp mapred-site.xml.template mapred-site.xml

然後再修改mapred-site.xml,在configuration標籤內添加屬性:

<property>
      <!--指定mapreduce运行在yarn上-->
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
</property>

1.2.5 yarn-site.xml

修改mapred-site.xml,在configuration標籤內添加屬性:

<!-- Site specific YARN configuration properties -->
<property>
<!-- mapreduce 执行 shuffle 时获取数据的方式 -->
      <name>yarn.nodemanager.aux-services</name>
      <value>mapreduce_shuffle</value>
</property>
<property>
      <name>yarn.resourcemanager.address</name>
      <value>localhost:18040</value>
</property>
<property>
      <name>yarn.resourcemanager.scheduler.address</name>
      <value>localhost:18030</value>
</property>
<property>
       <name>yarn.resourcemanager.resource-tracker.address</name>
       <value>localhost:18025</value>
</property>
<property>
       <name>yarn.resourcemanager.admin.address</name>
       <value>localhost:18141</value>
</property>
<property>
       <name>yarn.resourcemanager.webapp.address</name>
       <value>localhost:18088</value>
</property>

配置完畢後,在控制台執行 hdfs namenode -format 成功则会看到”successfully formatted”和”Exitting with status 0”的提示,若为 “Exitting with status 1” 则是出错。

1.3 測試

1.3.1 查看進程是否啟動

在 Hadoop 的终端执行 jps 命令,在打印结果中会看到 5 个进程,分别是 namenode、 secondarynamenode、datanode、resourcemanager、nodemanager, 如下图所示。 如果出现 了这 5 个进程表示主节点进程启动成功:

  • ResourceManager
  • NameNode
  • RemoteMavenServer
  • DataNode
  • Launcher
  • SecondaryNameNode
  • NodeManager

Web UI 查看集群是否成功启动,浏览器中打开http://localhost:50070/,以及http://localhost:18088/;检查 namenode 和 datanode 是否正常,检查 Yarn 是否正常。

二,Hadoop案例(WordCount)

創建模塊 hadoop-test,將要統計的英文文件存放到resources目錄下,命名為input.txt。

2.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>lmc-user</artifactId>
        <groupId>com.lmc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hadoop-test</artifactId>

    <dependencies>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>1.2.1</version>
        </dependency>

    </dependencies>


</project>

2.2 MapClass.java

package com.lmc.example.wordcount;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

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

/**
 * @ClassName: MapClass
 * @author: Leemon
 * @Description: TODO 本操作主要是进行map的数据处理,MapClass把 <k1,v1>通過map轉化為<k2,v2>
 * @date: 2021/1/28 17:10
 * @version: 1.0
 */
public class MapClass extends Mapper<LongWritable, Text, Text, IntWritable> {

    //每一个单词最终生成的保存个数是1
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    /**
     * 轉化類
     * @param key k1變量
     * @param value v1變量
     * @param context
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void map(LongWritable key, Text value,
                       Context context)
            throws IOException, InterruptedException {
        // 默认情况下是取得每行的数据,所以每行的数据里面都会存在有空格,按照空格进行拆分,每当出现一个单词就做一个统计的1

        //取出每行的数据
        String line = value.toString();
        //进行每行数据的拆分
        StringTokenizer st = new StringTokenizer(line," ");
        //循环每个单词而后进行数据的生成
        while(st.hasMoreTokens()){
            word.set(st.nextToken());
            //word:k2變量,one:v2變量
            context.write(word,one);
        }

    }
}

2.3 ReduceClass.java

package com.lmc.example.wordcount;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;
import java.util.Iterator;

/**
 * @ClassName: ReduceClass
 * @author: Leemon
 * @Description: TODO 本操作主要是进行reduce的数据处理,进行合并后数据的最终统计
 * @date: 2021/1/28 17:12
 * @version: 1.0
 */
public class ReduceClass extends Reducer<Text, IntWritable, Text, IntWritable> {

    protected void reduce(Text key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException {
        //保存每个单词出现的总次数
        int sum = 0;
        
        /**
         * 对于此处的foreach循环,官网上找到的解释,此时传入Reduce的数据已经是<key, (list of values)>的结构,
         * 所以Map函数循环对每个可以值进行处理,
         * 对每个key值的value list进行循环加和统计。
         * 官网http://hadoop.apache.org/docs/current/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html
         * In this phase the reduce(WritableComparable, Iterable<Writable>, Context)
         * method is called for each <key, (list of values)> pair in the grouped inputs.
         */
        for (IntWritable count: values) {
            sum += count.get();
        }

        context.write(key, new IntWritable(sum));
    }
}

2.4 WordCount.java

package com.lmc.example.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.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
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;

/**
 * @ClassName: WordCount
 * @author: Leemon
 * @Description: TODO
 * @date: 2021/1/28 17:13
 * @version: 1.0
 */
public class WordCount extends Configured implements Tool{

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

    public int run(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.printf("Usage: %s needs two arguments, input and output files\n", getClass().getSimpleName());
            return -1;
        }

        //进行相关的配置使用
        Configuration conf = new Configuration();

        // 定义一个名为WordCounter的作业
        Job job = new Job(conf);
        job.setJobName("wordCounter1");
        // 设置执行的jar文件程序类
        job.setJarByClass(WordCount.class);

        //设置输入输出路径
        FileInputFormat.addInputPath(job, new Path("hadoop-test/src/main/resources/input.txt"));
        FileOutputFormat.setOutputPath(job, new Path("hadoop-test/src/main/resources/output"));

        // 指定Mapper的处理类
        job.setMapperClass(MapClass.class);
        // 设置Reduce的处理类
        job.setReducerClass(ReduceClass.class);

        // 最终输出Key信息,设置为文本
        job.setOutputKeyClass(Text.class);
        // 最终输出Value内容设置为一个整型数据
        job.setOutputValueClass(IntWritable.class);
        job.setOutputFormatClass(TextOutputFormat.class);

//        if(job.isSuccessful()) {
//            System.out.println("Job was successful");
//        } else if(!job.isSuccessful()) {
//            System.out.println("Job was not successful");
//        }

        // 执行完后退出
        int returnValue = job.waitForCompletion(true) ? 0:1;

        return returnValue;
    }
}

2.4 java基本類型的Writable封裝

目前Java基本类型对应的Writable封装如下表所示。所有这些Writable类都继承自WritableComparable。也就是说,它们是可比较的。同时,它们都有get()和set()方法,用于获得和设置封装的值。

Java基本类型对应的Writable封装

Java基本类型Writable序列化后长度
布尔型(boolean)BooleanWritable1
字节型(byte)ByteWritable1
整型(int)IntWritable4
VIntWritable1~5
浮点型(float)FloatWritable4
长整型(long)LongWritable8
VLongWritable1~9
双精度浮点型(double)DoubleWritable8

注意:在表中,对整型(int和long)进行编码的时候,有固定长度格式(IntWritable和LongWritable)和可变长度格式(VIntWritable和VLongWritable)两种选择。固定长度格式的整型,序列化后的数据是定长的,而可变长度格式则使用一种比较灵活的编码方式,对于数值比较小的整型,它们往往比较节省空间。同时,由于VIntWritable和VLongWritable的编码规则是一样的,所以VIntWritable的输出可以用VLongWritable读入。

三,Hadoop之HDFS

3.1 文件系統

fs 和 dfs区别:

(1) fs是文件系统, dfs是分布式文件系统。
(2) fs > dfs。
(3) 分布式环境情况下,fs与dfs无区别。
(4) 本地环境中,fs就是本地文件,dfs就不能用了。
(5) fs涉及到一个通用的文件系统,可以指向任何的文件系统如local,HDFS等。但是dfs仅是针对HDFS的。

命令區別:

  1. hadoop fs:
    该命令可以用于其他文件系统,不止是hdfs文件系统内,也就是说该命令的使用范围更广
  2. hadoop dfs
    专门针对hdfs分布式文件系统
  3. hdfs dfs
    和上面的命令作用相同,相比于上面的命令更为推荐,并且当使用hadoop dfs时内部会被转为hdfs dfs命令

hadoop shell常用命令:

命令使用方法描述
mkdirhadoop fs -mkdir 接受路径指定的uri作为参数,创建这些目录。其行为类似于Unix的mkdir -p,它会创建路径中的各级父目录。
lshadoop fs -ls 如果是文件,则返回文件信息;如果是目录,则返回它直接子文件的一个列表
lsrhadoop fs -lsr ls命令的递归版本。类似于Unix中的ls -R
mvhadoop fs -mv URI [URI …] 将文件从源路径移动到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。不允许在不同的文件系统间移动文件。
cphadoop fs -cp URI [URI …] 将文件从源路径复制到目标路径。这个命令允许有多个源路径,此时目标路径必须是一个目录。
gethadoop fs -get [-ignorecrc] [-crc] 复制文件到本地文件系统。可用-ignorecrc选项复制CRC校验失败的文件。使用-crc选项复制文件以及CRC信息。
puthadoop fs -put … 从本地文件系统中复制单个或多个源路径到目标文件系统。也支持从标准输入中读取输入写入目标文件系统。

以上的命令,執行成功返回0,失敗返回-1

3.2 在java使用HDFS

3.2.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>lmc-user</artifactId>
        <groupId>com.lmc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hadoop-test</artifactId>

    <dependencies>

<!--        <dependency>-->
<!--            <groupId>org.apache.hadoop</groupId>-->
<!--            <artifactId>hadoop-core</artifactId>-->
<!--            <version>1.2.1</version>-->
<!--        </dependency>-->

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.5.1</version>
        </dependency>

    </dependencies>

</project>

3.2.2 HDFSAction.java

package com.lmc.example.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;

import java.io.*;

/**
 * @ClassName: HDFSAction
 * @author: Leemon
 * @Description: TODO
 * @date: 2021/1/30 9:33
 * @version: 1.0
 */
public class HDFSAction {

    public static void main(String[] args) {
        try {
            Configuration conf = new Configuration();
            conf.set("fs.defaultFS", "hdfs://10.197.29.203:9000");
            FileSystem fs = FileSystem.get(conf);
            //列出目录
//            list(fs, "/");
            //创建目录
            //mkdir(fs, "/test2");
            //刪除
//            delete(fs, "/test2");
            //寫文件
//            write(fs, "/test1/write.txt");
            //讀文件
            read(fs, "/wordCount/input/input.txt");
            //從本地拷貝文件到hdfs
//            copyLocalToHDFS(fs, "hadoop-test/src/main/resources/input.txt", "/wordCount/input/input.txt");

            fs.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 讀文件
     * @param fs
     * @param fileName
     * @throws IOException
     */
    public static void read(FileSystem fs, String fileName) throws IOException {
        //read
        Path path = new Path(fileName);
        FSDataInputStream fin = fs.open(path);
        byte[] buff = new byte[128];
        int len = 0 ;

        while( (len = fin.read(buff,0,128))  != -1 ) {
            System.out.print(new String(buff,0,len));
        }
    }

    /**
     * 寫文件
     * @param fs
     * @param fileName
     * @throws IOException
     */
    public static void write(FileSystem fs, String fileName) throws IOException {
        Path path = new Path(fileName);
        FSDataOutputStream fout = fs.create(path);
        byte[] bWrite = "hello hadoop distribute file system \n".getBytes();
        fout.write(bWrite); //写入字节数组
        fout.flush(); //flush提供了一种将缓冲区的数据强制刷新到文件系统的方法
        fout.close(); //关闭写出流
    }

    public static void copyLocalToHDFS(FileSystem fs, String source, String target) throws IOException {
        Path s = new Path(source);
        Path t = new Path(target);
        fs.copyFromLocalFile(s, t);
    }

    /**
     * 列出HDFS目錄
     * @param fs
     * @throws IOException
     */
    public static void list(FileSystem fs, String path) throws IOException {
        //列出目录
        FileStatus[]  paths = fs.listStatus(new Path(path));
        for (int i = 0 ; i < paths.length ;++i) {
            System.out.println(paths[i].toString());
            System.out.println(paths[i].getLen());
            System.out.println(paths[i].getPath().getName());
        }
    }

    /**
     * 创建目录
     * @param fs
     * @param dictory
     * @throws IOException
     */
    public static void mkdir(FileSystem fs, String dictory) throws IOException {
        //创建目录
        if(fs.mkdirs(new Path(dictory))) {
            System.out.println("mkdir " + dictory + " success ");
        }
    }

    /**
     * 刪除
     * @param fs
     * @param dictory
     * @throws IOException
     */
    public static void delete(FileSystem fs, String dictory) throws IOException {
        //删除
        if(fs.delete(new Path(dictory), true)){
            System.out.println("delete " + dictory + " /import ");
        }
    }

}

3.3 修改WordCount.java為HDFS

先將input文件上傳至HDFS上

HDFSAction.copyLocalToHDFS(fs, "hadoop-test/src/main/resources/input.txt", "/wordCount/input/input.txt");

再做好相關配置:

		//进行相关的配置使用
        String HDFS_PATH = "hdfs://10.197.29.203:9000";
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", HDFS_PATH);

然後修改輸入輸出路徑:

        //设置输入输出路径
//        FileInputFormat.addInputPath(job, new Path("hadoop-test/src/main/resources/input.txt"));
//        FileOutputFormat.setOutputPath(job, new Path("hadoop-test/src/main/resources/output"));

        FileInputFormat.addInputPath(job, new Path("/wordCount/input/input.txt"));
        FileOutputFormat.setOutputPath(job, new Path("/wordCount/output"));

最後,運行測試。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值