Hadoop02---HDFS基础(HDFS原理 java客户端).md

HDFS基础

一 启动HDFS

一键开启:

start-dfs.sh

一键停止:

stop-dfs.sh>

二 HDFS基本原理

1.HDFS上传文件流程

  1. 客户端向NameNode进行请求
  2. NameNode校验存储空间,空间充足,向客户端返回ok
  3. 客户端将文件进行切块处理,将切块数量等信息传递给namenode
  4. NameNode确认所有数据块的存储位置,并将位置信息返回给客户端
  5. 客户端依据获得的存储位置信息,在文件系统中建立连接,将客户端与目标DataNode相连
  6. 连接成功向客服端返回ok,不成功则由客户端向NameNode反馈,重新获取存储位置
  7. 建立连接后,开始进行上传,将文件块进一步拆分成便于传输的文件包进行传输
  8. 每个块的传输顺序为:客户端—>第一个DataNode—>第二个DataNode—>第三个DataNode(默认3个)
  9. 传输完毕后,若出现某个数据块全部存储失败则重新上传;在每个块都有至少一个存储成功的情况下,则向客户端反馈上传成功。

2.连接校验

  • NameNode的族群ID和数据块池ID
  • DataNode的族群ID和datanodeuuID
  • DataNode的数据块池ID
  • HDFS通过族群ID和数据块池ID确定身份
  • 通过datanodeUuid区分不同的DataNode

3.下载文件流程

  1. 客户端发起下载请求;
  2. NN将元数据 信息发送至客户端;
  3. 客户端在每个块的备份中选择一个网络通信良好的DN进行下载;
  4. 各数据块依次传输并完成拼接。

4.数据存储位置特征

  1. 一个数据块默认大小是128M;
  2. 每个数据块会默认至少备份3份在DN中;
  3. 每个数据块的存储位置会记录在DD的元数据中;
  4. HDFS中应避免存储大量小文件,因为元数据存储在内存中,大小受到限制,每存储一个文件,元数据都要至少使用150K数据来记录文件信息,小文件过多会降低HDFS的使用效率;
  5. HDFS中的数据可以多次读取,但是不支持随机修改;
  6. HDFS读取文件要分别各DN和NN进行多次通信,因此效率不高。

5.NameNode和DataNode的通信机制

  1. 心跳反馈机制:DN每3秒钟向NN发送一次心跳
  2. DN会向NN汇报存储状况、数据块状态等信息,若NN发现备份数量缺少,会向DN发送复制任务,保证备份数量
  3. 若NN和DN的网络通信出现错误,或DN的宕机,NN连续30s没有收到DN的心跳,五分钟后NN会向DN发送通信请求(Ping),若不同,则再过五分钟重新发送,若第二次仍无法通信成功,判定该DN死亡;
  4. NN将无效的DN剔除时间:(5+5+0.5=10.5m)

6.NameNode职责

  1. 接收客户端的上传、下载请求,返回元数据给客户端
  2. 生成集群ID、块池ID,接收DN的注册请求,生成DNUuID
  3. 存储、维护元数据
  4. 接收DN的心跳,保证其正常工作
  5. 统计分析数据块数量,不足时向DN发送复制任务
  6. 管理DN的存储空间、存储内容

7.DataNode职责

  1. 接收NN的任务,进行复制等操作
  2. 存储数据块
  3. 接收并处理客户端的读写任务
  4. 向NN注册,发送心跳,汇报存储空间的等信息

8.元数据工作机制

  1. NN中的原数据实际上是NN内存中的一个Java对象:FsImage
  2. 用户的每个操作 都会记录到工作日志中,并存储到NN中
  3. FsImage的数据结构是树形结构
8.1 chockpoint机制
  1. NN会初始序列化一个FsImage文件
  2. 引入secondrayName,一个非NN的其他设备
  3. secondrayName会下载NN序列化的FsImage文件和日志文件
  4. 将FsImage反序列化为FsImage对象到内存中,结合日志文件,复制用户近一小时的操作
  5. 得到一个新的FsImage对象,将其序列化为新的FsImage文件,并将其传输给NN
  6. NN中最多保留两个FsImage文件,如果有新的传进来,会自动删除最旧的FsImage文件
  7. 以上操作每一小时自动执行一遍(日志文件每小时生成一个)
8.2 备用Namenode
  1. secondrayName只执行备份,不会执行NN的其他操作
  2. 为防止NN宕机,引入备用NameNode
  3. 备用NameNode尽量与NN同步(通过NN传递过来的日志文件进行同步)
  4. 引入zookeeper系统,监测NN是否正常工作
  5. 若检测到主NN故障,立刻切换到从NN进行工作

三 在java端操作HDFS

1.常用方法

  • 通过java获取HDFS客户端对象

**以下是常用的方法 : **

public class HdfsClient {
    public static void main(String[] args) throws Exception {

        FileSystem fs = GetHDML.getFS();

        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : fileStatuses) {
            Path path = fileStatus.getPath();
            String name = path.getName();
            System.out.println(path+"---"+name);
        }


        fs.close();

    }

    private static void listFiles(FileSystem fs) throws IOException {
        //        fs.listFiles()
        RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path("/"), false);
        while (files.hasNext()){
            LocatedFileStatus status = files.next();
            //获取文件大小
            long len = status.getLen();
            //获取切块大小
            long blockSize = status.getBlockSize();
            //字符串
            String s = status.toString();
            //获取切块
            BlockLocation[] blockLocations = status.getBlockLocations();

            for (BlockLocation blockLocation : blockLocations) {
                //
                long length = blockLocation.getLength();

                String[] hosts = blockLocation.getHosts();
                for (String host : hosts) {
                    System.out.println(len+"---"+blockSize+"---"+s+"---"+length+"---"+host);
                }
            }

        }
    }

    private static void vi(FileSystem fs) throws IOException {
        //写入数据
        //覆盖写入
        Scanner sc = new Scanner(System.in);
        System.out.println("输入要写入的位置:");
        String s = sc.nextLine();
        Path path = new Path(s);
        FSDataOutputStream out = fs.create(path);
        System.out.println("输入内容:");
        s = sc.nextLine();
        out.write(s.getBytes());
    }

    private static void open(FileSystem fs) throws IOException {
        //读取文件
        Scanner sc = new Scanner(System.in);
        System.out.println("输入要读取的目录:");
        String s = sc.nextLine();
        Path path1 = new Path(s);
        FSDataInputStream open = fs.open(path1);
        //转换流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(open));
        while ((s=bufferedReader.readLine())!=null)
        {
            System.out.println(s);
        }
    }

    private static void mkdir(FileSystem fs) throws IOException {
        //新建文件夹
        Scanner sc = new Scanner(System.in);
        System.out.println("输入要创建的目录:");
        String s = sc.nextLine();
        Path path1 = new Path(s);
        boolean b = fs.mkdirs(path1);
    }

    private static void remove(FileSystem fs) throws IOException {
        //删除文件
        Scanner sc = new Scanner(System.in);
        System.out.println("输入要删除的目录:");
        String s = sc.nextLine();
        Path path1 = new Path(s);
        fs.delete(path1,true);
    }

    /**
     * 移动和重命名
     * @param fs
     * @throws IOException
     */
    private static void move(FileSystem fs) throws IOException {
        //移动和重命名
        Scanner sc = new Scanner(System.in);
        System.out.println("输入源目录、目标目录:");
        String s = sc.nextLine();
        String[] split = s.split("\\s+");
        Path path1 = new Path(split[0]);
        Path path2 = new Path(split[1]);
        fs.rename(path1,path2);
    }

    /**
     * 下载文件
     * @param fs
     * @throws IOException
     */
    private static void get(FileSystem fs) throws IOException {
        Scanner sc = new Scanner(System.in);
        System.out.println("输入源路径、目标路径(及是否删除源文件):");
        String s = sc.nextLine();
        String[] split = s.split("\\s+");
        Path path1 = new Path(split[0]);
        Path path2 = new Path(split[1]);
        boolean b = false;
        if (split.length==3)
        {
            b=Boolean.parseBoolean(split[2]);
        }
        //下载文件
        fs.copyToLocalFile(b,path1,path2);
    }


    /**
     * 上传文件
     * @param fs
     * @throws IOException
     */
    public static void put(FileSystem fs) throws IOException {

        Scanner sc = new Scanner(System.in);
        System.out.println("输入源路径、目标路径(及是否删除源文件、是否覆盖已有文件):");

        String s = sc.nextLine();
        String[] split = s.split("\\s+");
        Path path1 = new Path(split[0]);
        Path path2 = new Path(split[1]);
        //是否删除源文件
        boolean b1=false;
        //是否覆盖已有文件
        boolean b2=true;
        if (split.length>2)
        {
            b1=Boolean.parseBoolean(split[2]);
            if (split.length>3)
            {
                b2=Boolean.parseBoolean(split[3]);
            }
        }
        fs.copyFromLocalFile(b1,b2,path1,path2);
    }
}

2.修改配置属性

  • 方法一:

    • 通过配置对象进行设置
    public class ConfDEeail {
        public static void main(String[] args) {
            //创建配置对象
            Configuration conf = new Configuration();
            //设置副本数量
            conf.set("dfs.replication","4");
            //设置数据包大小
            conf.set("dfs.blocksize","64M");
    //        FileSystem.newInstance(new URI("hdfs://linux01:8020"),conf,"root");
        }
    }
    
  • 方法二:

    • /etc/hadoop 目录下的hdfs-site.xml 文件复制到maven项目的resources 目录下
    • 更改configuration 标签中的内容删除
    • 通过自行添加property标签,进行设置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值