hadoop学习笔记

hadoop学习笔记

Scroll Down

1、hadoop是什么

在这里插入图片描述

2、HDFS

数据块: 数据块是抽象块而非整个文件作为存储单元,块的默认大小为64M,一般设置为128M,备份X3







3、利用shell命令与HDFS进行交互

(1)目录操作

1】目录操作

hdfs dfs –mkdir –p /user/hadoop

该命令中表示在HDFS中创建一个“/user/hadoop”目录,“–mkdir”是创建目录的操作,“-p”表示如果是多级目录,则父目录和子目录一起创建,这里“/user/hadoop”就是一个多级目录,因此必须使用参数“-p”,否则会出错。

2】查看目录下面的内容

hdfs dfs -ls /user/hadoop

3】如果要列出HDFS上的所有目录,可以使用如下命令:

hdfs dfs -ls /

4】删除目录

root@namenode1:~# hdfs dfs -rm -r /user/hadoop/output
19/08/03 09:27:24 INFO fs.TrashPolicyDefault: Namenode trash configuration: Deletion interval = 0 minutes, Emptier interval = 0 minutes.
Deleted /user/hadoop/output
root@namenode1:~# 

上面命令中,“-r”参数表示如果删除“/input”目录及其子目录下的所有内容,如果要删除的一个目录包含了子目录,则必须使用“-r”参数,否则会执行失败。

(2)文件操作

1】上传文件到hdfs文件系统

将当前目录的文件hadoop-2.7.1.tar.gz上传到hdfs
root@namenode1:/usr/local# hdfs dfs -put hadoop-2.7.1.tar.gz /user/hadoop/input
root@namenode1:/usr/local# hdfs dfs -ls /user/hadoop/input
Found 1 items
-rw-r--r--   2 root supergroup  210606807 2019-08-03 09:32 /user/hadoop/input/hadoop-2.7.1.tar.gz

其它节点也可以上传文件

root@datanode1:~# hdfs dfs -put datanode1file.txt /user/hadoop/input
root@datanode1:~# hdfs dfs -ls /user/hadoop/input
Found 2 items
-rw-r--r--   2 root supergroup         23 2019-08-03 09:39 /user/hadoop/input/datanode1file.txt
-rw-r--r--   2 root supergroup  210606807 2019-08-03 09:32 /user/hadoop/input/hadoop-2.7.1.tar.gz

2】从Hdfs上下载文件

root@namenode1:~# hdfs dfs -get /user/hadoop/input/datanode1file.txt ~
19/08/03 09:42:22 WARN hdfs.DFSClient: DFSInputStream has been closed already
root@namenode1:~# ls
datanode1file.txt  vmware-tools-distrib  公共的  模板  视频  图片  文档  下载  音乐  桌面
root@namenode1:~# 

3】移动、拷贝hdfs上的文件

移动mv 拷贝 cp
root@namenode1:~# hdfs dfs -mv /user/hadoop/input/datanode1file.txt /user/hadoop
root@namenode1:~# hdfs dfs -ls /user/hadoop/
Found 2 items
-rw-r--r--   2 root supergroup         23 2019-08-03 09:39 /user/hadoop/datanode1file.txt
drwxr-xr-x   - root supergroup          0 2019-08-03 09:44 /user/hadoop/input
root@namenode1:~# 

4、利用Web界面管理HDFS

Overview 'namenode1:9000' (active)

Started:Sat Aug 03 09:20:14 CST 2019
Version:2.7.1, r15ecc87ccf4a0228f35af08fc56de536e6ce657a
Compiled:2015-06-29T06:04Z by jenkins from (detached from 15ecc87)
Cluster ID:CID-ba9cbb91-7c7a-4e86-a04c-c248be36c50d
Block Pool ID:BP-1454062026-192.168.80.90-1564714086384

Summary

Security is off.

Safemode is off.

190 files and directories, 148 blocks = 338 total filesystem object(s).

Heap Memory used 102.45 MB of 151 MB Heap Memory. Max Heap Memory is 889 MB.

Non Heap Memory used 46.75 MB of 47.94 MB Commited Non Heap Memory. Max Non Heap Memory is -1 B.

Configured Capacity:72.52 GB
DFS Used:426.46 MB (0.57%)
Non DFS Used:17.27 GB
DFS Remaining:54.84 GB (75.61%)
Block Pool Used:426.46 MB (0.57%)
DataNodes usages% (Min/Median/Max/stdDev):0.57% / 0.57% / 0.57% / 0.00%
Live Nodes2 (Decommissioned: 0)
Dead Nodes0 (Decommissioned: 0)
Decommissioning Nodes0
Total Datanode Volume Failures0 (0 B)
Number of Under-Replicated Blocks18
Number of Blocks Pending Deletion0
Block Deletion Start Time2019/8/3 上午9:20:14

5、利用Java API与HDFS进行交互

1】为了编写一个能够与HDFS交互的Java应用程序,一般需要向Java工程中添加以下JAR包:(可以将jar包复制到本地)
(1)”/usr/local/hadoop/share/hadoop/common”目录下的hadoop-common-2.7.1.jar和haoop-nfs-2.7.1.jar;
(2)/usr/local/hadoop/share/hadoop/common/lib”目录下的所有JAR包;
(3)“/usr/local/hadoop/share/hadoop/hdfs”目录下的haoop-hdfs-2.7.1.jar和haoop-hdfs-nfs-2.7.1.jar;
(4)“/usr/local/hadoop/share/hadoop/hdfs/lib”目录下的所有JAR包。

2】编写Java应用程序代码:判断文件是否存在

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
public class HDFSFileIfExist {
    public static void main(String[] args){
        try{
            String fileName = "test";
            Configuration conf = new Configuration();
            URI uri = new URI("hdfs://192.168.80.90:9000");
            FileSystem hdfs = FileSystem.get(uri, conf,"root"); //root有操作权限的用户名
            if(hdfs.exists(new Path(fileName))){
                System.out.println("文件存在");
            }else{
                System.out.println("文件不存在");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这个默认检测的是/user/root/目录下是否存文件。可以更改目录手动确定检测哪个目录,修改filename,修改成某个路径下的文件比如:String fileName = "/user/hadoop/datanode1file.txt"; 这就会检测HDFS上的/user/hadoop/目录下是否存在datanode1file.txt

3】编写Java应用程序代码:写入文件

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
import java.net.URI;
public class WriteFile {
    public static void main(String[] args) {
        try{
            String filename = "test";
            Configuration conf = new Configuration();
            URI uri = new URI("hdfs://192.168.80.90:9000");
            FileSystem hdfs = FileSystem.get(uri, conf,"root"); //root有操作权限的用户名
            byte[] buff = "Hello world".getBytes(); // 要写入的内容
            FSDataOutputStream os = hdfs.create(new Path(filename));
            os.write(buff, 0, buff.length);
            System.out.println("Create:" + filename);
            os.close();
            hdfs.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

注意:因为使用的是root用户,所以会主动在HDFS的/user目录下面创建一个root目录,接着写入test文件。如果想更改目录修改filename的值即可。比如:String filename = "/user/hadoop/test";

运行程序后在虚拟机中输入如下命令,查看是否写入成功:

root@namenode1:~# hdfs dfs -ls /user/hadoop
Found 3 items
-rw-r--r--   2 root supergroup         23 2019-08-03 09:39 /user/hadoop/datanode1file.txt
drwxr-xr-x   - root supergroup          0 2019-08-03 09:44 /user/hadoop/input
-rw-r--r--   3 root supergroup         11 2019-08-03 10:44 /user/hadoop/test

4】读取文件:类似Java的文件读取

package hadoop.hdfs;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.stream.Stream;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataInputStream;

public class ReadFile {
    public static void main(String[] args) {
        try{
            String filename = "/user/hadoop/datanode1file.txt";
            Configuration conf = new Configuration();
            URI uri = new URI("hdfs://192.168.80.90:9000");
            FileSystem hdfs = FileSystem.get(uri, conf,"root"); 
            Path file = new Path(filename);
            FSDataInputStream getIt = hdfs.open(file);
            BufferedReader d = new BufferedReader(new InputStreamReader(getIt));
            int tempbyte;
            while ((tempbyte = d.read()) != -1) {
                System.out.write(tempbyte);
            }
            d.close(); //关闭文件
            hdfs.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

6、YARN概念:

Apache Hadoop YARN 是开源 Hadoop 分布式处理框架中的资源管理和作业调度技术。作为 Apache Hadoop 的核心组件之一,YARN 负责将系统资源分配给在 Hadoop 集群中运行的各种应用程序,并调度要在不同集群节点上执行的任务。

YARN的基本组成结构,YARN 主要由 ResourceManager、NodeManager、ApplicationMaster 和 Container 等几个组件构成。

  • 【1】ResourceManager是Master上一个独立运行的进程,负责集群统一的资源管理、调度、分配等等;
  • 【2】NodeManager是Slave上一个独立运行的进程,负责上报节点的状态;
  • 【3】ApplicationMaster相当于这个Application的监护人和管理者,负责监控、管理这个Application的所有Attempt在cluster中各个节点上的具体运行,同时负责向Yarn ResourceManager申请资源、返还资源等;
  • 【4】Container是yarn中分配资源的一个单位,包涵内存、CPU等等资源,YARN以Container为单位分配资源;



7、MapReduce编程模型


1、WordCount实例分析:

1、Split阶段

2、Map阶段

3、Shuffle阶段

将相同的单词归结到一起,但是不会进行次数的累加,最终结果的统计是reduce阶段要做的,此阶段的输出作为reduce阶段的输入。

4、Reduce阶段

5、总结

2、从分片输入到Map

1、输入文件

2、分片输入-Split

例如:现在输入的文件大小为420M,现在分成的4片,现在又来一个40M的文件,这时候分片就是5片。这时候他们的地址映射都会保存在NameNode中,如果所有的文件加起来大小不变,但是文件的个数变多了,这个时候namenode保存的元数据就会变多,这个时候会对hdfs产生负面的影响。

3、理想的输入文件

4、阶段Map任务的个数

3、Map-Shuffle-Reduce

1、本地优化-Combine

Map输出结果,按照首字母排序,接着合并:

2、从Map-Reduce

3、Reduce任务数量

8、Hadoop的分布式缓存

1、分布式缓存--DistributedCache

1、Hadoop分布式缓存

2、使用DistributedCache

报错

1、没有权限

org.apache.hadoop.security.AccessControlException: Permission denied: user=12783, access=EXECUTE, inode="/user/12783/test":root:supergroup:drwxrwx---

这是因为FileSystem hdfs = FileSystem.get(uri, conf,"root"); 这里没有加有权限的用户名。正确代码如下:

1	import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
public class HDFSFileIfExist {
    public static void main(String[] args){
        try{
            String fileName = "test";
            Configuration conf = new Configuration();
            URI uri = new URI("hdfs://192.168.80.90:9000");
            FileSystem hdfs = FileSystem.get(uri, conf,"root"); //root有操作权限的用户名
            if(hdfs.exists(new Path(fileName))){
                System.out.println("文件存在");
            }else{
                System.out.println("文件不存在");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

或者修改hdfs-site.xml,增加

<property>
      <name>dfs.permissions</name>
      <value>false</value>
</property>

2、Window运行mapreduce程序

Could not locate executable null\bin\winutils.exe in the Hadoop binaries.

Hadoop都是运行在Linux系统下的,在windows下eclipse中运行mapreduce程序,要首先安装Windows下运行的支持插件。文件解压后如下(添加winutils.exe),放到bin目录即可。接着配置环境变量。

在这里插入图片描述

在这里插入图片描述

至此重启电脑后,问题便可以解决了。插件下载地址

https://github.com/sdravida/hadoop2.6_Win_x64/blob/master/bin/winutils.exe

## 3、UnknownHostException
Exception in thread "main" java.lang.IllegalArgumentException: java.net.UnknownHostException: namenode1
	at org.apache.hadoop.security.SecurityUtil.buildTokenService(SecurityUtil.java:374)
	at org.apache.hadoop.hdfs.NameNodeProxies.createNonHAProxy(NameNodeProxies.java:310)
	at org.apache.hadoop.hdfs.NameNodeProxies.createProxy(NameNodeProxies.java:176)
	at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:668)
	at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:604)
	at org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java:148)
	at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2598)
	at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
	at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2632)
	at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2614)
	at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:370)
	at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:169)
	at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:354)

在C:\Windows\System32\drivers\etc 下修改hosts文件,增加一行 : 你的IP namenode1,namenode1是hostname。