Hadoop--HDFS

Hadoop--HDFS

Edits和Fsimage机制详解

概述

fsimage镜像文件包含了整个HDFS文件系统的全部目录和文件的indoe(节点)信息,好比:/node01/node,会记录每一个节点nodeid,以及节点之间父子路径。html

以及文件名,文件大小,文件被切成几块,每一个数据块描述信息、修改时间、访问时间等;此外还有对目录的修改时间、访问权限控制信息(目录所属用户,所在组等)等。java

另外,edits文件主要是在NameNode已经启动状况下对HDFS进行的各类更新操做进行记录,好比 :hadoop fs -mkdir hadoop fs -delete hadoop fs -put等。node

对于每次事务操做,都会用一个TXID来标识,OP_MKDIR OP_DELETE等。git

Edits文件存储的操做,而fsimage文件存储的是执行操做后,变化的状态。(元数据)github

HDFS客户端执行全部的写操做都会被记录到edits文件中。web

关键点

1.当执行格式化指令时候,会在指定元数据目录生成 dfs/name/current/shell

最开始只有fsimage,没有edits文件(由于没有启动HDFS)apache

2.当初次启动HFDS,会生成edits_inprogress_0000000000000000001,此文件用于记录事务(写操做)windows

3.HDFS对于每次写操做,都会用一个事务ID(TXID)来记录,TXID是递增的。服务器

4.edits_0000000000000000003-0000000000000000007,数字表示的合并后起始的事务id和终止事务id

5.seen_txid 存储的当前的事务id,和edits_inprogress最后的数字一致

6.datanode存储块的目录路径:/tmp/dfs/data/current/BP-859711469-192.168.150.137-1535216211704/current/finalized/subdir0/subdir0

7.finalized此目录存储的已经存储完毕的数据块,rbw目录存的是正在写但还未写完的数据块

查看Edits文件和Fsimage文件

hdfs oev -i edits_0000000000000000001-0000000000000000003 -o edits.xml

hdfs oiv -i fsimage_0000000000000000012 -o fsimage.xml -p XML

HDFS API操做

1.建立java工程

2.导入hadoop依赖jar包

链接namenode以及读取hdfs中指定文件
 
 
 
x
 
 
 
 
@Test
public void testConnectNamenode() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.211:9000"), conf);
InputStream in=fs.open(new Path("/park/1.txt"));
OutputStream out=new FileOutputStream("1.txt");
IOUtils.copyBytes(in, out, conf);
}
 
上传文件到hdfs上
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testPut() throws Exception{
Configuration conf=new Configuration();
conf.set("dfs.replication","1");
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.21:9000"),conf,"root");
ByteArrayInputStream in=new ByteArrayInputStream("hello hdfs".getBytes());
OutputStream out=fs.create(new Path("/park/2.txt"));
IOUtils.copyBytes(in, out, conf);
}
 
从hdfs上删除文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testDelete()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.21:9000"),conf,"root");
//true表示不管目录是否为空,都删除掉。能够删除指定的文件
fs.delete(new Path("/park01"),true);
//false表示只能删除不为空的目录。
fs.delete(new Path("/park01"),false);
fs.close();
}
 
在hdfs上建立文件夹
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testMkdir()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.211:9000"),conf,"root");
fs.mkdirs(new Path("/park02"));
}
 
查询hdfs指定目录下的文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testLs()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.214:9000"),conf,"root");
RemoteIterator<LocatedFileStatus> rt=fs.listFiles(new Path("/"), true);
while(rt.hasNext()){
System.out.println(rt.next());
}
}
 
递归查看指定目录下的文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testLs()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.214:9000"),conf,"root");
RemoteIterator<LocatedFileStatus> rt=fs.listFiles(new Path("/"), true);
while(rt.hasNext()){
System.out.println(rt.next());
}
}
 

 

重命名
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testCreateNewFile() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.176:9000"),conf,"root");
fs.rename(new Path("/park"), new Path("/park01"));
 
        
}
 

 

获取文件的块信息
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testCopyFromLoaclFileSystem() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.176:9000"),conf,"root");
BlockLocation[] data=fs.getFileBlockLocations(new Path("/park01/1.txt"),0,Integer.MaxValue);
for(BlockLocation bl:data){
System.out.println(bl);
}
}
 

从HDFS下载文件过程

1.Client向namenode发起 Open file 请求。目的是获取指定文件的输入流。

namenode收到请求以后,会检查路径的合法性,此外,仍是检查客户端的操做权限。若是检测未经过,则直接报错返回。后续过程不会发生。

2.Client也会向namenode发起:Getblockloaction请求,获取指定文件的元数据信息。若是第一步的检测经过,namenode会将元数据信息封装到输入流里,返回给客户端。

3.4 客户端根据元数据信息,直接去对应的datanode读取文件块,而后下载到本地(建立本地的输出流,而后作流的对接)

5.读完后,关流。

上传文件到HDFS

1.Client向namenode发现 Create file请求,目的是获取HDFS文件的输出流。namenode收到请求后,会检测路径的合法性和权限。若是检测未经过,直接报错返回。

若是经过检测,namenode会将文件的切块信息(好比文件被切成几块,每一个文件块的副本存在哪台datanode上),而后把这些信息封装到输出流里,返回给客户端。

因此注意:文件块的输出(上传)是客户端直接和对应DN交互的,namenode的做用是告诉Client文件块要发送给哪一个datanode上。

 

2.Client经过输出流,发送文件块(底层会将一个文件块打散成一个一个的packet,每一个packet的大小=64kb)。这个过程的机制,叫Pipeline(数据流管道机制)

这种机制的目的:

为了提升网络效率,咱们采起了把数据流和控制流分开的措施。在控制流从客户机到主Chunk、而后冉 到全部二级副本的同时,数据以管道的方式,顺序的沿着一个精心选择的Chunk服务器链推送。咱们的目标 是充分利用每台机器的带宽,避免网络瓶颈和高延时的链接,最小化推送全部数据的延时。 为了充分利用每台机器的带宽,数据沿着一个Chunk服务器链顺序的推送,而不是以其它拓扑形式分散 推送(例如,树型拓扑结构)。线性推送模式下,每台机器全部的出凵带宽都用于以最快的速度传输数据,而 不是在多个接受者之间分配带宽。

3.4.5 。经过数据流管道机制,实现数据的发送和副本的复制。每台datanode服务器收到数据以后,会向上游反馈ack确认机制。直到第五步的ack发送给Client以后,再发送下一个packet。依次循环,直到全部的数据都复制完毕。此外,在底层传输的过程当中,会用到全双工通讯。

补充:建议看《Google File System》的3.2节

6.数据上传完以后,关流。

从HDFS删除文件的流程

一、客户端向namenode发现 删除文件指令,好比:

 
 
 
xxxxxxxxxx
 
 
 
 
hadoop fs  -rm /park01/1.txt
 

二、namenode收到请求后,会检查路径的合法性以及权限

三、若是检测经过,会将对应的文件从元数据中删除。(注意,此时这个文件并无真正从集群上被删除)

四、每台datanode会按期向namenode发送心跳,会领取删除的指令,找到对应的文件块,进行文件块的删除。

HDFS的租约机制

HDFS的有个内部机制:不容许客户端的并行写。指的是同一时刻内,不容许多个客户端向一个HDFS上写数据。

因此要实现以上的机制,实现思路就是用互斥锁,可是若是底层要是用简单的互斥锁,可能有与网络问题,形成客户端不释放锁,而形成死锁。因此Hadoop为了不这种状况产生,引入租约机制。

租约锁本质上就是一个带有租期的互斥锁。

Hadoop的思想来自于Google的论文,3.1

Hadoop 租约锁对应的类:org.apache.hadoop.hdfs.server.namenode.LeaseManager.Lease

还有一个租约锁管理者:

org.apache.hadoop.hdfs.server.namenode.LeaseManager

HDFS特色

一、分布式存储架构,支持海量数据存储。(GB、TB、PB级别数据)

二、高容错性,数据块拥有多个副本(副本冗余机制)。副本丢失后,自动恢复。

三、低成本部署,Hadoop可构建在廉价的服务器上。

四、可以检测和快速应对硬件故障,经过RPC心跳机制来实现。

五、简化的一致性模型,这里指的是用户在使用HDFS时,全部关于文件相关的操做,好比文件切块、块的复制、块的存储等细节并不须要去关注,全部的工做都已被框架封装完毕。用户所须要的作的仅仅是将数据上传到HDFS。这大大简化了分布式文件存储操做的难度和管理的复杂度。

六、HDFS不能作到低延迟的数据访问(毫秒级内给出响应)。可是Hadoop的优点在于它的高吞吐率(吞吐率指的是:单位时间内产生的数据流)。能够说HDFS的设计是牺牲了低延迟的数据访问,而获取的是数据的高吞吐率。若是要想获取低延迟的数据访问,能够经过Hbase框架来实现。

七、HDFS不准修改数据,因此适用场景是:一次写入,屡次读取(once-write-many-read)。注意:HDFS容许追加数据,但不容许修改数据。追加和修改的意义是不一样的。

八、HDFS不支持并发写入,一个文件同一个时间只能有一个写入者。

九、HDFS不适合存储海量小文件,由于会浪费namenode服务节点的内存空间

相关文章
相关标签/搜索