Hadoop之HDFS读写流程

6 篇文章 0 订阅
5 篇文章 0 订阅

HDFS写流程

HDFS写文件流程图

HDFS写流程步骤

创建文件

1、客户端调用DistributedFileSystem.create()方法Rpc方式(ClientProtocol.create())远程调用NameNode(NameNodeRpcServer)的create()方法在HDFS上创建文件。
2、NameNode将该事务操作保持到edits.log文件当中
3、NameNode.create()创建成功,DistrbutedFileSystem.create()返回给客户端DFSOutputStream对象

建立数据流管道

4、客户端调用DFSOutputStream.write()方法写入数据
5、DFSOutputStream会先调用CilentProtocol.addBlock()方法,向NameNode申请空的数据块
6、CilentProtocol.addBlock()返回LocatedBlock对象,内容包含了写入到DataNode的位置信息中

向数据管道pipeline中写入数据

7、客户端向数据管道中写入数据:将数据写入到一个校验块chunk中,一个chunk大小为516byte大小,其中前面512byte为写入的数据,后4byte为校验值(checksum,根据crc32算法进行校验)
8、当一个chunk写入完成,会保持到更大的数据块中packet(64KB)
9、当packet写满之后,会被发到dataqueue队列中
10、packet从队列中取出,通过pipeline写入到datanode中,如图,先到datanode1,然后再有datanode1将输入写入datanode2,datanode3
11、当一个packet在被读取完写入到datanode之后,packet存储到ackqueue校验列表中,等到pipeline返回packet的ack反馈
12、每个包都会有ack反馈,当datanode1,datanode2,datanode3写入完成,会从datanode3->datanode2->datanode1逆反向返回ack校验值
13、如果ackqueue中的ack校验成功,则表示,这个packet写入完成,将该packet从ackqueue中移除,
如果校验失败,则表示ack校验失败,该packet会被ackqueue中取出,重新存储到dataqueue头部,被重新发送
14、当当前block块被写入完成,则会继续调用addBlock,步骤同上
15、当文件中最后一个block数据写入完成,会发送一个空的packet,表示写入结束,关闭pipeline
16、但文件写入完成,则客户端会调用clientProtocol.complete()通知namenode当前文件写入完成
代码演示:

import java.io.*;
import java.net.URI;

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.io.IOUtils;

public class copyLocalToHDFS {
    public static void main(String[] args) {
        //文件读取流
        InputStream in = null;
        try {
            //读取数据到内存中
            in = new BufferedInputStream(new FileInputStream(args[0]));
            //创建配置文件对象
            Configuration conf = new Configuration();
            //创建文件系统
            FileSystem fileSystem = FileSystem.get(URI.create(args[1]),conf);
            //获取输出流,写入到HDFS
            FSDataOutputStream fsDataOutputStream = fileSystem.create(new Path(args[1]));
            //拷贝输入流到输出流,并关闭两个流
            IOUtils.copyBytes(in,fsDataOutputStream,4096,true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

HDFS写入流程容错处理

背景:在文件写入的过程中,有datanode出现网络故障(网络不同)

处理步骤:

1、ackqueue中的缓存数据会被重新载入到dataqueue中
2、输入流会调用ClientProtocol.updateBlockForPipeline(),为block申请一个新的时间戳,namenode会记录新的时间戳
3、当出现故障的datanode恢复,会上报block信息到namenode,如果存在block的时间戳与namenode中记录的不同,则namenode会通过返回心跳协议,让datanode删除本地的block
4、故障的datanode会被从pipeline中删除
5、输出流调用ClientProtocol.getAdditionalDatanode()通知namenode分配新的datanode到pipeline中,并使用新的时间戳建立pipeline
6、输出流调用ClientProtocol.updatePipeline(),更新namenode的元数据
7、HDFS客户端调用DataTransferProtocol通知pipeline中一个datanode,将block数据复制到新的datanode中
8、恢复故障,继续写入数据

HDFS读流程

HDFS读流程图
1、客户端调用DistributedFileSystem.open()方法,远程调用namenode的open方法打开文件,返回FSDataInputStream对象
2、在构造FSDataInputStream对象时,namenode会调用getBlockLocations方法,获得文件的存储block块的datanode列表,(客户端在读取的时候,会根据网络拓扑,来读取文件)
3、客户端在调用FSDataInputStream的read方法,会在在里client最近的datanode,依此读取block块
4、当文件读取完成,则会调用FSDataInputStream的close方法
代码演示

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

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;

public class copyHDFSToLocal {
   public static void main(String[] args) {

       try {
           //配置文件
           Configuration conf = new Configuration();
           FileSystem fileSystem = FileSystem.get(URI.create(args[0]), conf);
           //获取HDFS输入流
           FSDataInputStream open = fileSystem.open(new Path(args[0]));
           //本地输出流
           BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(args[1]));
           IOUtils.copyBytes(open,bufferedOutputStream,4096,true);

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

HDFS读取流程容错处理

情况一:
在读取过程中,client与datanode的通信中断。client与此block的第二个datanode建立连接,读取。在本次读取中,会记录有问题的datanode,并在本次读取时,不会再他上读取数据
情况二:
client读取block数据时,会同时读取block的校验和,如果读取来的数据,计算校验和,如果该block数据的校验和和读取来的校验和不一样,则说明该block数据损坏。client则会再该block的副本上读取数据。同时client会告知namenode这个损坏的block。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值