HDFS-API 操作

>hdfs 动态扩容:

HDFS 中存储的文本副本大小:默认是128M

参数:dfs.blocksize 默认128M 每一个副本大小,这是客户端的行为,传一个副本或者获取一个副本,值获取配置大小的副本,也就是存储的大小都是由客户端决定的。

def.replication 默认副本数量3个,也是由客户端决定,

元数据存储目录:

dfs.namenode.name.dirfile://${hadoop.tmp.dir}/dfs/name

 默认的存储方式是,在配置的hadoop.tmp.dir配置目录下面的name,

正确的做法是,配置多个目录

<name>dfs.namenode.name.dir</name>

<value>/mnt/disk1, /mnt/disk2,nfs://xxx/xxxx</value>

dataNode的文件块目录也应该是配置到专门存储数据的磁盘

dfs.datanode.data.dir 默认的也是在 file://${hadoop.tmp.dir}/dfs/data 目录中

<name>dfs.datanode.dir</name>

<value>/mnt/disk1, /mnt/disk2,nfs://xxx/xxxx</value>

这里的写法核上面的写法是不一样的,上面的namenode 的写法是没一个数据在每一个目录都写一遍,而datanode 的写法是,讲所有的挂载目录都当成是一个,这次给这个目录写,下一次给下一个目录写。

第一个api操作程序:

// 1 获取入口FileSystem

Configuration conf = new Configuration();
// set 客户端使用的参数
conf.set("dfs.replication","2");

FileSystem dfsClient = FileSystem.get(new URI("hdfs://172.16.214.128:9000"), conf,"root");

// 上传一个文件
Path fromLocalPath = new Path("/Users/xuxliu/Downloads/hadoopConfigcopy.docx");
Path targetHdfsPath = new Path("/test/test.doc");
dfsClient.copyFromLocalFile(fromLocalPath, targetHdfsPath);
dfsClient.close();

遇到问题:Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Permission denied: user=xuxliu, access=WRITE, inode="/":root:supergroup:drwxr-xr-x

权限问题,默认是需要开启权限的,而我们在命令行里面没有遇到这个问题是因为命令行里是root执行的,解决方法,关闭权限

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

需要重启

API 测试代码

private FileSystem dfsClient;

    @Before
    public void init() throws Exception {
        Configuration conf = new Configuration();
        conf.set("dfs.replication","2");
        dfsClient = FileSystem.get(new URI("hdfs://172.16.214.128:9000"), conf,"root");
    }

    /**
     *  测试hdfs 上取文件到本地
     */
    @Test
    public void testGetFile() throws IOException {
        Path targetLocalPath = new Path("/Users/xuxliu/Downloads/");
        Path sorHdfsPath = new Path("/test/test.doc");
        dfsClient.copyToLocalFile(sorHdfsPath, targetLocalPath);

        dfsClient.close();
    }

    @Test
    public void testMkdir() throws IOException {
        boolean mkdirs = dfsClient.mkdirs(new Path("/xxx/yyyy"));
        dfsClient.close();
    }

    @Test
    public void testDelete() throws IOException {
//        delete(Path f, boolean recursive)
        boolean delete = dfsClient.delete(new Path("/xxx"), true);
        dfsClient.close();
    }

    @Test
    public void testRenameDir() throws IOException {
        dfsClient.rename(new Path("/xxx"), new Path("/xxxuuu"));
        dfsClient.close();
    }

    @Test
    public void testlistDir() throws IOException {
//        final Path f, final boolean recursive)  递归显示全部
        RemoteIterator<LocatedFileStatus> iterator = dfsClient.listFiles(new Path("/"), true);
        while (iterator.hasNext()){
            LocatedFileStatus next = iterator.next();
            System.out.println(next.getBlockLocations());
            System.out.println(next.getBlockSize());
            System.out.println(next.getOwner());
        }

        dfsClient.close();
    }

    @Test
    public void testDirInfo() throws IOException {
//        List the statuses of the files/directories in the given path if the path is
//          * a directory.  不会递归
        FileStatus[] fileStatuses = dfsClient.listStatus(new Path("/"));
        for (FileStatus fs: fileStatuses
             ) {
            System.out.println(fs);
//            FileStatus{path=hdfs://172.16.214.128:9000/a.txt; isDirectory=false;
//            length=15; replication=2; blocksize=134217728; modification_time=1550903769312;
//            access_time=1550903768982; owner=root; group=supergroup; permission=rw-r--r--;
//            isSymlink=false}
        }

        dfsClient.close();
    }

    @Test
    public void testGetPartOfFile() throws IOException {
        FSDataInputStream inputStream = dfsClient.open(new Path("/qingshu.txt"));
        FileOutputStream outputStream = new FileOutputStream("/Users/xuxliu/Downloads/qingshu.txt");

        // offset from start index 指定读取的起始位置
        inputStream.seek(20);

        byte[] bytes = new byte[10];
        int len = 0;
        long count = 0;
        while (inputStream.read(bytes)!=-1){// 不等于-1 就是读取了一个缓存
            outputStream.write(bytes);
            count += 1;

            if (count == 20){
                break;
            }
        }

        inputStream.close();
        outputStream.close();
        dfsClient.close();
    }

    @Test
    // 输出流的方式网 hdfs 写数据
    public void testWriteDataToHdfs() throws IOException {
        // 打开 hdfs 文件
        FSDataOutputStream hdfsOut = dfsClient.create(new Path("/qingshu2.txt"));
        hdfsOut.write("77777777777777777".getBytes());
        hdfsOut.write("88888888888888888".getBytes());

        hdfsOut.flush();
        hdfsOut.close();
        dfsClient.close();
    }

HDFS 读写机制:

写:

  1. 客户端请求写数据(带着路径)nameNode,namenode会返回这个路径是否能写
  2. 客户端继续请求namenode,写入一个block,
  3. namenode 会返回来可用的datanode blockId 可用的datanode等
  4. 客户端和datanode握手,请求传输文件块,只会传递给一个datanode,这个datanode会和其他的datanode发请求,谁准备接受数据。返回接听的端口,告诉客户端准备好了
  5. 客户端本地读书局,然后网络流给第一台机器收数据,这台机器的这些数据,还会给其他datanode传输数据
  6. 接着客户端传递这个文件的第二块,重复上面的步骤

下载数据:

  1. 客户端读取数据请求。
  2. namenode 会根据请求参数,查看这些数据是否存在,如果存在则返回请求文件的元数据
  3. 客户端拿着这些元数据取datanode 取数据

NameNode 如何管理元数据的:

元数据是什么:HDFS 中的文件的描述信息,路径/BLK信息/位置/长度/副本数量,这些数据是放在内存中的

所以宕机那么就会很危险了。

元数据的的任何东西都是因为客户端的操作而引起的。nameNode 的信息会根据客户端的操作而跟新,也会将这些操作写到磁盘里面去,防止宕机,隔一段时间就会将操作的东西写到磁盘(fsimage), 而这个存放是有secondaryNamenode做的,到达一个触发点就会将这段时间的操作,写到 fsimage,然后nameNode重新记录新的操作,万一宕机,那么可以根据执行这些记录而重新操作一遍讲数据恢复。

secondaryNamenode 执行checkpoint操作

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值