[Hadoop]Hdfs-创建文件过程详解

来源:互联网 发布:淘宝如何买到正品耐克 编辑:程序博客网 时间:2024/06/06 04:51

【Hadoop】HDFS - 创建文件流程详解

转载自:foreach_break

本文目录 [+点此展开]

1.本文目的

通过解析客户端创建文件流程,认知hadoop的HDFS系统的一些功能和概念。


2.主要概念

2.1 NameNode(NN)

HDFS系统核心组件,负责分布式文件系统的名字空间管理、INode表的文件映射管理。如果不开启备份/故障恢复/Federation模式,一般的HDFS系统就只有1个NameNode,当然这样是存在单点故障隐患的。

NN管理两个核心的表:文件到块序列的映射、块到机器序列的映射。
第一个表存储在磁盘中,第二表在NN每次启动后重建。

2.2 NameNodeServer(NNS)

负责NN和其它组件的通信接口的开放(IPC、http)等。
NN通过客户端协议(ClientProtocol)和客户端通信,通过数据节点协议(DataNodeProtocol)和DN通信。

2.3 FSNameSystem

管理文件系统相关,承担了NN的主要职责。

2.4 DataNode(DN)

分布式文件系统中存放实际数据的节点,存储了一系列的文件块,一个DFS部署中通常有许多DN。
DN和NN,DN和DN,DN和客户端都通过不同的IPC协议进行交互。
通常,DN接受来自NN的指令,比如拷贝、删除文件块。
客户端在通过NN获取了文件块的位置信息后,就可以和DN直接交互,比如读取块、写入块数据等。

DN节点只管理一个核心表:文件块到字节流的映射。

在DN的生命周期中,不断地和NN通信,报告自己所存储的文件块的状态,NN不直接向DN通信,而是应答DN的请求,比如在DN的心跳请求后,回复一些关于复制、删除、恢复文件块的命令(comands)。
DN和外界通信的接口<host:port>会报告给NN,想和此DN交互的客户端或其它DN可以通过和NN通信来获取这一信息。

2.5 Block

文件块,hadoop文件系统的原语,hadoop分布式文件系统中存储的最小单位。一个hadoop文件就是由一系列分散在不同的DataNode上的block组成。

2.6 BlockLocation

文件块在分布式网络中的位置<host:port>,也包括一些块的元数据,比如块是否损坏、块的大小、块在文件中的偏移等。

2.7 DFSClient

分布式文件系统的客户端,用户可以获取一个客户端实例和NameNode及DataNode交互,DFSClient通过客户端协议和hadoop文件系统交互。

2.8 Lease

租约,当客户端创建或打开一个文件并准备进行写操作,NameNode会维护一个文件租约,以标记谁正在对此文件进行写操作。客户端需要定时更新租约,否则当租约过期,NN会关闭文件或者将文件的租约交给其它客户端。

2.9 LeaseRenewer

续约管控线程,当一个DFSClient调用申请租约后,如果此线程尚未启动,则启动,并定期向NameNode续约。


三.创建一个文件

当hadoop的分布式集群启动之后,可以通过FS或Shell来创建文件,FS创建文件的命令如下:

//cluser是hadoop集群,通过fs和集群文件系统交互final DistributedFileSystem fs = cluster.getFileSystem();// 要创建的文件名final Path tmpFile1 = new Path("/tmpfile1.dat");//创建文件public static void createFile(FileSystem fs, Path fileName, long fileLen,       short replFactor, long seed) throws IOException {    if (!fs.mkdirs(fileName.getParent())) {      throw new IOException("Mkdirs failed to create " +                             fileName.getParent().toString());    }    FSDataOutputStream out = null;    try {      out = fs.create(fileName, replFactor);      byte[] toWrite = new byte[1024];      Random rb = new Random(seed);      long bytesToWrite = fileLen;      while (bytesToWrite>0) {        rb.nextBytes(toWrite);        int bytesToWriteNext = (1024<bytesToWrite)?1024:(int)bytesToWrite;        out.write(toWrite, 0, bytesToWriteNext);        bytesToWrite -= bytesToWriteNext;      }      out.close();      out = null;    } finally {      IOUtils.closeStream(out);    }  }

四、流程分析

创建一个名为tmpfile1.dat的文件,主要流程如下:

这里写图片描述


4.1 发送创建文件的请求(CreateFile)

客户端向NN发起请求,获取文件信息,NN会在缓存中查找是否存在请求创建的文件项(file entry),如果没找到,就在NameSystem中创建一个新的文件项:

块管理器(BlockManager)检查复制因子是否在范围内,如果复制因子过小或过大就会异常。
同时会进行权限验证、加密、安全模式检测(如果在安全模式不能创建文件)等,并记录操作日志和事件日志,然后向客户端返回文件状态。


4.2 申请文件租用权(beginFileLease)

客户端取得文件状态后,对文件申请租用(lease),如果租用过期,客户端将无法再继续对文件进行访问,除非进行续租。


4.3 数据流管控线程启动(DataStreamer & ResponseProcessor)

DataStreamer线程负责数据的实际发送:

当数据队列(Data Queue)为空时,会睡眠,并定期苏醒以检测数据队列是否有新的数据需要发送、Socket套接字是否超时、是否继续睡眠等状态。

ResponseProcessor负责接收和处理pipeline下游传回的数据接收确认信息pipelineACK


4.4 发送添加块申请并初始化数据管道(AddBlock & Setup Pipeline)

当有新的数据需要发送,并且块创建阶段处于PIPELINE_SETUP_CREATE,DataStreamer会和NameNode通信,调用AddBlock方法,通知NN创建、分配新的块及位置,NN返回后,初始化Pipeline和发送流。


4.5 DataNode数据接收服务线程启动(DataXceiverServer & DataXceiver)

当DataNode启动后,其内部的DataXceiverServer组件启动,此线程管理向其所属的DN发送数据的连接建立工作,新连接来时,DataXceiverServer会启动一个DataXceiver线程,此线程负责流向DN的数据接收工作。


4.6 在Pipeline中处理数据的发送和接收

客户端在获取了NameNode分配的文件块的网络位置之后,就可以和存放此块的DataNode交互。
客户端通过SASL加密方式和DN建立连接,并通过pipeline来发送数据。


4.6.1 从pipeline接收数据

pipeline由数据源节点、多个数据目的节点组成,请参考上面的流程图。

位于pipeline中的第一个DataNode会接收到来自客户端的数据流,其内部DataXceiver组件,通过读取操作类型(OP),来区分进行何种操作,如下所示:

  protected final void processOp(Op op) throws IOException {    switch(op) {    case READ_BLOCK:      opReadBlock();      break;    //本例中将会使用WRITE_BLOCK指令    case WRITE_BLOCK:      opWriteBlock(in);      break;        //略...        default:      throw new IOException("Unknown op " + op + " in data stream");    }  }

如果OP是WRITE_BLOCK,调用写数据块的方法,此方法会根据数据源是客户端还是其他DataNode、块创建的阶段等条件进行不同的逻辑。


4.6.2 数据在pipeline中流动

在本例中,第一个收到数据的DN会再启动一个blockReceiver线程,以接收实际的块数据,在本地保存了块数据后,其负责向pipeline中的后续DN继续发送块数据。

每次向下游DN节点发送数据,标志着数据目的节点的targets数组都会排除自身,这样,就控制了pipeline的长度。

下游收到块数据的DN会向上游DN或者客户端报告数据接收状态。

这种链式或者序列化的数据转移方式,就像数据在管道中从上游流向下游,所以这种方式称作pipeline


4.6.3 pipeline的生命周期

这里写图片描述
在本例中:

DataStreamer线程启动后,pipeline进入PIPELINE_SETUP_CREATE阶段;
数据流初始化后,pipeline进入DATA_STREAMING阶段;
数据发送完毕后,pipeline进入PIPELINE_CLOSE阶段。

客户端在DataStreamer线程启动后,同时启动了一个ResponseProcessor线程,此线程用于接收pipeline中来自下游节点的数据接收状态报告pipelineACK,同时此线程和DataStreamer线程协调管理pipeline状态。

当DataStreamer向pipeline发送数据时,会将发送的数据包(packet)从数据队列(Data Queue)中移除,并加入数据确认队列(Ack Queue):

//DataStreamer发送数据后,将dataQueue的第一个元素出队,并加入ackQueueone = dataQueue.getFirst();dataQueue.removeFirst();ackQueue.addLast(one);

而当ResponseProcessor收到下游的pipelineAck后,据此确认信息来判断pipeline状态,是否需要重置和重新调整。如果确认信息是下游节点数据接收成功了,就将确认队列(AckQueue)的第一个数据包删除。

//ResponseProcessor收到成功的Ack,就将ackQueue的第一个包移除lastAckedSeqno = seqno;ackQueue.removeFirst();dataQueue.notifyAll();

通过这样的方式,DataStreamer可以确认数据包是否发送成功,也可以确认全部的数据包是否已经发送完毕。

显然,当AckQueue空了,并且已经发送的数据包是块里的最后一个包,数据就发送完毕了。

发送完毕的判断如下所示:

          if (one.lastPacketInBlock) {            // wait for all data packets have been successfully acked            synchronized (dataQueue) {              while (!streamerClosed && !hasError &&                   ackQueue.size() != 0 && dfsClient.clientRunning) {                try {                  // wait for acks to arrive from datanodes                  dataQueue.wait(1000);                } catch (InterruptedException  e) {                  DFSClient.LOG.warn("Caught exception ", e);                }              }            }            if (streamerClosed || hasError || !dfsClient.clientRunning) {              continue;            }            //在没有错误的情况下,AckQueue为空,并且包one是block的最后一个包,数据就发送完了            stage = BlockConstructionStage.PIPELINE_CLOSE;          }

4.7 发送文件操作完成请求(completeFile)

客户端向NameNode发送completeFile请求:

NN收到请求后,验证块的BlockPoolId是否正确,接着对操作权限、文件写锁(write lock)、安全模式、租约、INode是否存在、INode类型等等进行验证,最后记录操作日志并返回给客户端。


4.8 停止文件租约(endFileLease)

客户端在完成文件写操作后,调用leaseRenewer(LR)实例,从LR管理的续约文件表中删除此文件,表明不再更新租约,一段时间后,租约在NN端自然失效。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃凉东西牙疼怎么办 吃糖导致的牙疼怎么办 微商退货不退钱怎么办 创维电视要收费怎么办 域名已被注册了怎么办 腿上皮肤干燥像鱼鳞怎么办 货拉拉抢不到单怎么办 京东优惠券删了怎么办 吃了发黄的大米怎么办 误吃了霉味大米怎么办 吃了发霉的食物怎么办 面包发霉了吃了怎么办 长期吃了地沟油怎么办 吃了地沟油呕吐怎么办 dnf冲到别人账号怎么办 皮肤买错大区了怎么办 微信实名超过5个怎么办 微信绑定超过5个怎么办 300英雄忘了账号怎么办 163邮箱登陆不上怎么办 手机收不到微信怎么办 苹果微信反应慢怎么办 微信网速特别慢怎么办 微信突然卡住了怎么办 微信一直卡死怎么办 微信打开卡了怎么办 微信卡住不动了怎么办 微信突然卡死了怎么办 手机京东e卡使用怎么办 携程礼品卡欺诈,怎么办 携程礼品卡诈骗怎么办 易事通卡过期了怎么办 设备被淘宝黑了怎么办 饭店排风噪音大怎么办 善融商城不发货怎么办 ps渲染图像很慢怎么办 买房子收据丢了怎么办 买房子发票丢了怎么办 买房的收据丢了怎么办 首付款收据丢了怎么办 预购房收据丢了怎么办