一.HDFS基本知识

1.让文件平均分块block  每块有多个副本 每块和每个副本存在不同的Datanode上。

一个文件分成多块 默认每块128M  那么一个130M的文件  就会分成一块128M 一块2M

一个文件,除了最后一个block之外,其他block大小都一样

副本因子(replication ):一个文件副本数量,默认三份

二.优缺点

优点

1.使得多个计器之间能够负载均衡

2.有一个服务器挂了也不影响整个文件

3.多个datanode并行处理,提升速度

缺点

1.数据访问有延迟
2.不适合小文件的存储(浪费block)

三.hdfs架构

Master(NameNode)  带N个Slaves(DataNode)
datanode管理数据存储

NameNode:负责客户端请求的响应,负责元数据管理
当一个read读文件请求过来时,他要请求namenode,看目标文件被分成了几分,存到了哪几个节点上

DataNode:负责存储数据块block,定期向Namenode汇报信息,健康状况,与NameNode维持心跳
比如一个DataNode存储空间不够用了,那么再有文件写入时,NameNode作为管理者,就不往这个DataNode上分发了

四.经典部署模式

一个hdfs只部署一个NameNode,每个机器部署一个DataNode 

目前我用三台机器搭建的HADOOP分布式:hadoop102,hadoop103,hadoop104

hadoop102:NameNode,DataNode,NodeManager(NodeManager是yarn的)

hadoop103:DataNode,ResourceManager(yarn),NodeManager

hadoop104:DataNode,NodeManager

部署成功之后可以看到活着的节点有三个

hdfs分片 datax 分片 hdfs怎么分块_hdfs分片 datax 分片

hdfs分片 datax 分片 hdfs怎么分块_Test_02

五.hdfs安装

开始想在windows上搞虚拟机,但是过程比较费劲也比较卡,后来放弃了,直接租的三台阿里云服务器

目前只说大致过程,等我心情好了再写个完整版

我用的是上传压缩包去安装,看网上也有yum安装,yum能在线下载并安装rpm包,能更新系统

1.修改/etc/hosts

三台机器主机名对应ip

2.免密配置

生成的在.ssh目录下生成公钥文件和私钥文件  带.pub的是公钥

你想让谁免密登陆当前机器,就把公钥拷贝给谁  

hdfs分片 datax 分片 hdfs怎么分块_hadoop_03

免密测试

hdfs分片 datax 分片 hdfs怎么分块_hdfs_04

3.配置jdk

4.配置hadoop环境变量

5.修改配置文件

    5.1核心配置文件core-site.xml

    5.2hdfs配置文件hdfs-site.xml

    5.3yarn配置文件yarn-site.xml

    5.4mapreduce配置文件mapred-site.xml

    5.5配置workers(老版本中也叫slaves,听说因为反对奴隶制,改成了workers)

六.安装过程中踩的坑

1.命令不生效

原因:hadoop文件大小为0KB

我也不到我误碰了什么

hdfs分片 datax 分片 hdfs怎么分块_hdfs分片 datax 分片_05

解决办法:

再解压一个,把里边的hadoop文件复制过来

hdfs分片 datax 分片 hdfs怎么分块_hdfs分片 datax 分片_06

2.无法访问yarn控制台

yarn-site.xml配置文件

hdfs分片 datax 分片 hdfs怎么分块_hdfs分片 datax 分片_07

3.格式化报错

格式化这个步骤要放在第一次启动之前

.xml文件的文件头,前边不能留空格,不然hadoop格式化时候会报错

七.hdfs命令

查看根目录文件
hdfs dfs -ls /
将文件上传到根目录
hdfs dfs -put test.txt /
查看文件内容
hdfs dfs -cat /test.txt
创建目录
hdfs dfs -mkdir /testDir
从hdfs上获取文件到本地
hdfs dfs -get /testDir
删除文件
hdfs dfs -rm /test.txt

八.读写文件流程

hdfs写文件流程

1.客户端分块block
2.namenode作为领导,分任务
3.datanode存储数据
4.过程中,datanode和namenode保持心跳,汇报信息

hdfs读文件流程

1.客户端发起读文件操作
2.namenode提供文件的block信息以及存储block的datanode信息
举例 test.txt的block1在datanode1,datanode2
block2在datanode2,datanode3

九.javaApi操作hdfs

主要应用hadoop包下的FileSystem类,有很多操作文件的方法,方法名与hdfs命令类似

1.资源下载路径


2.maven下载仓库配置

<repositories>
        <repository>
            <id>cloudera</id>
            <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
        </repository>
    </repositories>
<!--添加hadoop依赖-->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

3.简单操作hdfs的方法 

(现在一般都用springboot了  下边代码不是springboot,就很入门的测试)

package com.imooc.hadoop.hdfs;

import com.google.code.useragent.UserAgentParser;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;

/**
 * Hadoop HDFS Java API 操作
 */
public class HDFSApp {

    /**
     * 创建文件
     */
    @Test
    public void create() throws Exception {
        FSDataOutputStream output = fileSystem.create(new Path("/hdfsapi/test/a.txt"));
        output.write("hello hadoop".getBytes());
        output.flush();
        output.close();
    }

    /**
     * 查看HDFS文件的内容
     */
    @Test
    public void cat() throws Exception {
        FSDataInputStream in = fileSystem.open(new Path("/hdfsapi/test/a.txt"));
        IOUtils.copyBytes(in, System.out, 1024);
        in.close();
    }


    /**
     * 重命名
     */
    @Test
    public void rename() throws Exception {
        Path oldPath = new Path("/hdfsapi/test/a.txt");
        Path newPath = new Path("/hdfsapi/test/b.txt");
        fileSystem.rename(oldPath, newPath);
    }

    /**
     * 上传文件到HDFS
     *
     * @throws Exception
     */
    @Test
    public void copyFromLocalFile() throws Exception {
        Path localPath = new Path("/Users/rocky/data/hello.txt");
        Path hdfsPath = new Path("/hdfsapi/test");
        fileSystem.copyFromLocalFile(localPath, hdfsPath);
    }

    /**
     * 上传文件到HDFS
     */
    @Test
    public void copyFromLocalFileWithProgress() throws Exception {
        InputStream in = new BufferedInputStream(
                new FileInputStream(
                        new File("/Users/rocky/source/spark-1.6.1/spark-1.6.1-bin-2.6.0-cdh5.5.0.tgz")));

        FSDataOutputStream output = fileSystem.create(new Path("/hdfsapi/test/spark-1.6.1.tgz"),
                new Progressable() {
                    public void progress() {
                        System.out.print(".");  //带进度提醒信息
                    }
                });


        IOUtils.copyBytes(in, output, 4096);
    }


    /**
     * 下载HDFS文件
     */
    @Test
    public void copyToLocalFile() throws Exception {
        Path localPath = new Path("/Users/rocky/tmp/h.txt");
        Path hdfsPath = new Path("/hdfsapi/test/hello.txt");
        fileSystem.copyToLocalFile(hdfsPath, localPath);
    }

    /**
     * 查看某个目录下的所有文件
     */
    @Test
    public void listFiles() throws Exception {
        FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/"));

        for(FileStatus fileStatus : fileStatuses) {
            String isDir = fileStatus.isDirectory() ? "文件夹" : "文件";
            short replication = fileStatus.getReplication();//查看副本数量
            long len = fileStatus.getLen();//文件大小
            String path = fileStatus.getPath().toString();//全路径
            System.out.println(isDir + "\t" + replication + "\t" + len + "\t" + path);
        }

    }

    /**
     * 删除
     */
    @Test
    public void delete() throws Exception{
        fileSystem.delete(new Path("/"), true);
    }
    @After
    public void tearDown() throws Exception {
        configuration = null;
        fileSystem = null;

        System.out.println("HDFSApp.tearDown");
    }


    public static final String HDFS_PATH = "hdfs://127.0.0.1:9820";

    FileSystem fileSystem = null;
    Configuration configuration = null;
    /**
     * 注意这里是@Before
     * @throws Exception
     */
    @Before
    public void setUp() throws Exception {
        System.out.println("HDFSApp.setUp");
        configuration = new Configuration();
        fileSystem = FileSystem.get(new URI(HDFS_PATH), configuration, "hadoop");
    }

    /**
     * 创建HDFS目录
     */
    @Test
    public void mkdir() throws Exception {
        fileSystem.mkdirs(new Path("/hdfsapi/test"));
    }

}