HDFS杂记

学习摘要:

学习阶段,有不对的地方请指出,不胜感激。

/**
HDFS:分布式文件系统,主要是用来解决海量数据的存储问题;
思想:分而治之。
应用:为其他分布式计算框架提供数据存储服务;
重点概念:数据块/副本、负载均衡、心跳机制、副本存放策略、元数据/元数据管理、安全模式、机架感知等等。

HDFS的设计思路:
1、大文件被切割成小文件,使用分而治之的思想让很多服务器对同一个文件进行联合管理。
2、每个小文件做冗余备份,并且分散存储到不同的服务器,做到高可靠不丢失。

HDFS的架构:
主节点NameNode:是集群的管理者,掌管文件系统目录树,处理客户端读写请求。
SecondaryNameNode:定期合并NameNode中fsimage和edits文件形成新的fsiamge文件跟新NameNode中的fsimage文件
从节点DataNode:存储整个集群所有的数据块,处理真正数据读写。

文件系统存储文件通过统一的命名空间--目录树来定位文件。
1、HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数(dfs.blocksize)来设置,默认的2.x版本中是128M;
2、HDFS文件系统会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件
	eg:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
3、目录结构及文件分块位置信息(元数据)的管理由NameNode节点承担
	namenode是HDFS集群主节点,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息
4、文件的各个block的存储管理有datanode节点来承担;
5、HDFS是设计适应一次写入,多次读取的场景,不支持文件的修改,但是允许文件内容的追加;
	适合用来做数据分析,并不适合用来做网盘应用,因为:不便修改,延迟大,网络开销大,成本高;
	
HDFS优点:
1、可构建在廉价的机器上,创建多个副本提高可靠性,提供容错和回复机制;
2、高容错性,数据自动保存多个副本,副本丢失后,自动恢复;
3、适合做批处理,移动计算而非移动数据,数据位置暴露给计算框架
4、适合大数据处理,百万规模以上的文件数量,10K+节点规模;
5、流式文件访问,一次性写入,多次读取,保证数据一致性。

HDFS缺点:
1、不适合低延迟数据访问,比如毫秒级。
2、不适合小文件存取,一个小文件占用一个block块,不同文件的block块没有关联,这样就会产生大量的block块,
	每个block块的信息都要存储在NameNode的内存中,这样会占用很多的内存,
	小文件过多,也会浪费大量的寻址时间;
3、不适合并发写入,文件随机修改,一个文件只能有一个写者,仅仅支持append操作;

HDFS不适合存储小文件的原因:
元数据信息存储在NameNode内存中,一个节点的内存是有限的;
存取大量小文件消耗大量的寻道时间

hdfs常用的命令:
hadoop fs -ls /
hadoop fs -put /dd /aa
hadoop fs -get /aa /bb
hadoop fs -mkdir -p /ddd/eee
hadoop fs -rm -r /ddd/eee
hadoop fs -getmerge /aaa/log.* ./log.sum
hadoop fs cp /aaa /bbb
hadoop fs mv /aaa /bbb
hadoop fs -rmdir /aaa/bbb
hadoop fs -appendToFile  /hello.txt  /helloWorld.txt
hadoop fs cat /hello.txt
hadoop fs tail /hello.txt
hadoop fs -text /hello.txt  以字符形式
hadoop fs -chgrp
hadoop fs -chmod 666 /hello.txt
hadoop fs -chown someUser:someGroup /hello.txt
hadoop fs -df -h /
hadoop fs -du -s -h /aaa/*
hadoop fs -count /aaa/  统计一个指定目录下的文件节点数量
hadoop fs -setrep 3 /aaa/hello.txt 设置某个文件的副本数量
hdfs dfsadmin -report 查看dfs集群工作状态的命令。


JAVA API操作:
创建文件,导入包:common hdfs
关键步骤:
创建文件系统对象:FileSystem fs = FileSystem.get(conf)
根据上面命令需求创建:Configuration conf = new Configuration();
如果我们在集群上跑:conf.set("fs.defaultFS","hdfs://hadoop01:9000");
设置文件系统搭建使用的用户:Sytem.setProperty("HADOOP_USER_NAME","hadoop");
参数优先级: 1、客户端代码中设置的值 2、classpath下的用户自定义配置文件 3、然后是服务器的默认配置
conf.set("dfs.replication", "2");
conf.set("dfs.block.size", "128m");

构造一个配置参数对象,设置一个参数:我们要访问的hdfs的URI
从而FileSystem.get()方法就知道应该是去构造一个访问hdfs文件系统的客户端,以及hdfs的访问地址 new
Configuration();的时候,它就会去加载jar包中的hdfs-default.xml
然后再加载classpath下的hdfs-site.xml
conf.addResource("config/core-site.xml");
conf.addResource("config/hdfs-site.xml");
conf.addResource("config/mapred-site.xml");
conf.addResource("config/yarn-site.xml");

常用的操作:
1、创建文件夹:fs.mkdirs(new Path("")) 这里可以直接创建多级目录;
2、上传文件:fs.copyFromLocalFile("源文件地址","目标地址")
3、下载文件:fs.copyToLocalFile(new Path("/wordcount/input/helloWorld.txt"), new Path("c:/"));
4、重命名一个文件:fs.rename(new Path("/hadoop-eclipse-plugin-2.6.4.jar"), new Path("/eclipsePlugin.jar"));
5、判断路径是否存在:fs.exists(new Path(""));
6、迭代删除文件:fs.delete(new Path(""),true);
7、获取一个路径下的所有的文件和文件夹列表,不包括子文件下的内容!!!
   FileStatus[] listStatus = fs.listStatus(new Path("/wordcount"));
   判断一个资源是文件还是文件夹:[文件夹]fileStatus.isDirectory() [文件]fileStatus.isFile()
8、获取一个指定路径下的所有的文件
	RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/wordcount"), true);
	获取文件的block块的信息:
	BlockLocation[] blockLocations = fileStatus.getBlockLocations();
	

下载HDFS文件:
首先open一个针对HDFS上的输入流:open一个针对HDFS上文件的输入流:
FSDataInputStream in = fs.open(new Path("/jdk-7u65-linux-i586.tar.gz"));
再构造一个文件的输出流----针对本地的
FileOutputStream out = new FileOutputStream(new File("下载到哪里"));
IOUtils.copyBytes(in,out,4096);

上传一个文件到HDFS上:
首先创建一个输入流----针对本地要上传的文件
FileInputStream in = new FileInputStream("本地要上传的文件的路径");
再创建一个输出流----针对本地的文件;
FSDataOutputStream out = fs.create(new Path("文件要存储到hdfs的路径"));
IOUtils.copyBytes(in,out,4096);

随机读取:FSDataInputStream in = fs.open(new Path("/someThing.txt"));
		  in.seek(10);
		  FileOutputSteam out = new FilePOutputStream(new File("dddddd"));
		  IOUtils.copyBytes(in,out,19L,true);  19L就是指的读取的长度。

HDFS的核心设计:
一、hadoop的心跳机制:
1、hadoop是Master/Slave结构,Master中有Namenode和ResourceManager, Slave中有DataNode和NodeManager;
2、Mater启动的时候会启动一个IPC(进程间通信)server服务,等待slave下达命令;
3、Slave启动时,会主动链接master的ipc server服务,并且每隔3秒钟会链接一次master,这个时间间隔是可以调整的
   通过参数:dfs.heartbeat.interval来进行调整,这个每隔一段时间去连接一次的机制,我们形象的称为心跳。
   Slave通过心跳汇报自己的信息给master,master也通过心跳给slave下达命令。
4、NameNode通过心跳得知DataNode的状态;ResourceManager 通过心跳得知 NodeManager 的状态。
5、如果master长时间都没有收到slave的心跳,就认为该slave挂掉了!!!!!

NameNode感知到DataNode掉线死亡的时长计算:
HDFS默认的超时时间为10分钟+30秒
timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval
heartbeat.recheck.interval单位为毫秒30000 默认5分钟;
dfs.heartbeat.interval单位是秒3 默认的是3秒

<property>
	<name>heartbeat.recheck.interval</name>
	<value>5000</value>
</property>
<property>
	<name>dfs.heartbeat.interval</name>
	<value>3</value>
</property>

二、HDFS安全模式
safemode是namenode的一种状态;
NameNode进入安全模式的原理:
a、namenode发现集群中的block丢失率达到一定比例时(0.1%),namenode就会进入安全模式,
   在安全模式下,客户端不能对任何数据进行操作,只能查看元数据信息(比如:ls/mkdir)
   这个丢失率是可以手动配置的,默认是:dfs.safemode.threshold.pct=0.999f
   
b、如何退出安全模式:
   1、找到问题所在,进行修复(比如修复宕机的datanode)
   2、或者可以进行手动的强行退出安全模式(但是这样并没有真正的解决问题)
      hdfs dfsadmin -safemode leave 手动离开安全模式
	  hdfs dfsadmin -safemode get 查看安全模式的状态

在hdfs集群正常的冷启动的时候,NameNode也会在safemode状态下维持相当长的一段时间,此时你不需要去理会,会自动退出;

正常启动进入安全模式的原理:
namenode的内存元数据中,包含文件路径、副本数、blockId,以及每一block所在datanode的信息,而fsimage中,不包含block所在的
datanode信息----->就会导致namenode认为所有的block都已经丢失----->进入安全模式----->datanode启动之后,会定期向namenode汇报
自身所持有的blockId信息-----随着datanode陆续启动,从而陆续汇报block信息,namenode就会将内存元数据中的bolck所在的datanode
信息补全更新----->找到了所有block的位置,从而会自动的退出安全模式。

三、副本存放策略
1、作用:
	数据分块存储和副本的存放,是保证可靠性和高性能的关键;
	
2、方法:
	将每个文件的数据进行分块存储,每一个数据块又保存有多个副本,这些数据块副本分布在不同的机器节点上。
	
3、存放说明:
	在多数情况下,HDFS默认的副本系数是3
	第一个副本:存放在和client所在的节点里(如果client不在集群范围中,则第一个node随机选取的,
	系统会尝试不选择哪些不满或者太忙的node);
	第二个副本:放置在与第一个节点不同的机架中的节点中;
	第三个副本:和第二个在同一机架,随机放在不同的节点中。
	
4、修改副本数:
	修改hdfs-site.xml文件:
	<property>
		<name>dfs.replication</name>
		<value>2</value>
	</property>
	
	命令设置:hadoop fs -setrep -R 2 /
	
四、负载均衡
机器和机器之间的磁盘利用率不平衡是HDFS集群中一个非常容易出现的一个情况;
尤其在datanode节点出现故障或者在现有的集群上增添新的datanode的时候,
分析数据块分布和重新均衡datanode上的数据分布的方法:
start-balancer.sh
start-balancer.sh -threshold 5
自动进行均衡非常慢,一天能移动的数据量在10G-10T的级别,很难满足超大集群的需求
原因:HDFS集群默认不允许balance操作,占用很大的网络带宽,这个带宽是可以调整的
	hdfs dfsadmin -setBalanacerBandwidth 10485760
	该数值的单位是字节,上面的配置是10M/s  默认的是1M/s
	另外可以在hdfs-site.xml配置文件中配置修改:
	<property>
		<name>dfs.balance.bandwidthPerSec</name>
		<value>10485760</value>
	</property>
	
	start-balancer.sh -t 10%
	机器容量最高的那个值  和  最低的那个值之间的差距  不能超过10%

五大常用的命令:
	tar -zxvf hadoop.tart.gz -C apps/
	rm -rf /  这个命令谨慎使用
	tail -f
	netstat -nltp  查看进程号和端口号的对应关系
	ps -ef /  ps -aux  查看进程详情
	rpm -ivh / yum install -y   安装一个软件  只适用于centos
两大常见的异常:
	command not found   要么命令写错  要么path变量中根本就没有这个命令
	no such file or direcotory


	
元数据:
	1、抽象目录树结构
	2、系统中的每一个文件和它的切块之间的映射关系
	3、每一个切块都有多个副本,这些副本的存放地


那么集群在经过一段时间的使用之后,就有可能给客户端提供错误的数据 为什么?
		因为HDFS集群中的任何一个datanode都是不可靠的。也就意味着datanode会宕机
		如果有一个datnaode宕机
		那么该datnaode上的所有数据块副本都会被HDFS的自我恢复机制在其他的datanode中复制出来


		以前的一个数据块的三个副本存放地 就会有一个 host 发生变化
		2 3 4    ---->  4 宕机 ----> 自我恢复 -- 2 3 5


	
	那就要求datanode每隔一段固定的时间,都需要向namenode进行汇报


	按照规定,每个datanode都是需要向namenode进行汇报。
	那么如果从某个时刻开始,某个datanode再也不向namenode进行汇报了。  有可能宕机了。


	因为只要通过网络传输数据,就一定存在一种可能:  丢失  或者  延迟


	HDFS的标准: 如果连续10次没有收到datnaode的汇报。 那么namenode就会认为该datanode存在宕机的可能


决定HDFS集群的启动时长会有两个因素:
	1、磁盘元数据的大小
	2、datanode的节点个数
	当元数据很大,或者 节点个数很多的时候,那么HDFS的启动,需要一段很长的时间
	
在安全模式下:
	如果一个操作涉及到元数据的修改的话。都不能
	如果一个操作仅仅只是查询。那是被允许的。
	所谓的安全模式,仅仅只是保护namenode  不是保护datanode
	
负载均衡:
	1、节点均衡
	2、机架均衡
	3、磁盘均衡
	




HDFS工作原理:
HDFS写数据流程:
客户端要向HDFS写数据,首先要跟namenode通信,以确认可以写文件并获得接收文件block的datanode负责向其他datanode复制block的副本。
1、client发出写数据请求;
2、namenode响应请求,然后去metadata中查询文件目录树等一系列校验,如果能上传该数据,则返回该文件的所有切块应该被存放在哪些
   datanode上的datanodes列表:
   blk-001:hadoop02 hadoop03
   blk-002:hadoop03 hadoop04
3、client拿到datanode列表之后,开始传输数据
4、首先是第一个块blk-001,datanode列表就是hadoop02 hadoop03;client就把blk-001传到hadoop02和hadoop03上;
5、用传第一个块的方式传其他的数据块;
6、当所有的数据块都传完之后,client会给namenode返回一个状态信息,表示数据以全部写入成功,或者是失败的信息;
7、namenode接收到client返回的状态信息来判断单词写入数据的请求是否成功,如果成功,就需要更新元数据信息。


详细的步骤说明:
1、使用HDFS提供的客户端client,向远程的namenode发起RPC请求;
2、namenode响应请求,然后去metadata中查询文件目录树等一系列校验,判断文件是否已经存在,创建者是否有权限进行操作,
   成功则会为文件创建一个记录,否则会让客户端抛出异常;
3、当客户端开始写入文件的时候,客户端会将文件切分成多个packets,并在内部以数据队列"data queue"的形式管理这些packets,
   并向namenode申请blocks,获取用来存储replicas的合适的datanode列表;列表的大小根据namenode中replication的设定而定;
4、开始以pipeline的形式将packet写入所有的replicas中。客户端把packet以流的方式写入第一个datanode,
   该datanode把该packet存储之后,再将其传递给在此pipeline中的下一个datanode,直到最后一个datanode,这种写数据的方式
   呈流水线的形式;
5、最后一个datanode才成功存储之后,会返回一个ack packet(确认队列),在pipeline里传递至客户端,在客户端的开发库内维护着
   ack queue,成功收到datanode返回的ack packet后,会从data queue移除响应的packet。
6、如果传输过程中,有某个datanode出现了故障,那么当前的pipeline会被关闭,出现故障的datanode会从当前的pipeline中移除,
   剩余的block会继续向剩下的datanode中以pipeline的形式传输,同时namenode会分配一个新的datanode,保持replicas设定的数量;
7、客户端完成数据写入之后,会对数据流调用close()方法,关闭数据流;
8、只要写入了dfs.replication.min的副本数,写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标副本数,
   因为namenode已知道文件有哪些块组成,所以它在返回成功前只需要等待数据块进行最小量的复制;
   


HDFS读数据流程:
客户端将要读取的文件路径发送给namenode,namenode获取文件的元信息(主要的存放位置信息)返回给客户端,
客户端根据返回的信息找到相应的datanode逐个获取文件的block并在客户端本地进行数据追加合并从而获取整个文件。


详细的操作步骤:
1、使用HDFS提供的客户端client,向远程的namenode发起RPC请求;
2、namenode会视情况返回文件的全部block列表,对于每个block,namenode都会返回有该block拷贝的datanode地址;
3、客户端client会选取离客户端最近的datanode来读取block;如果客户端本身就是datanode,那么将从本地直接获取数据;
4、读取完当前block的数据后,关闭当前的datanode链接,并为读取下一个block寻找最佳的datanode;
5、当读完列表block后,且文件读取还没有结束,客户端会继续向namenode获取下一批的block列表;
6、读取完一个block都会进行checksum验证,如果读取datanode是出现错误,客户端会通知namenode,然后再从下一个拥有
   该block拷贝的datanode继续读;
   


NameNode的工作机制:
职责:
1、负责客户端请求的响应;
2、维护目录树结构(元数据);
3、配置和应用副本存放策略;
4、管理集群数据块负载均衡问题;




NameNode元数据管理


WAL:预写日志系统;


NameNode对数据的管理采用了两种存储形式:内存和磁盘
首先是内存中存储了一份完整的元数据,包括目录树结构,以及文件和数据块和副本存储的映射关系;


1、内存元数据metadata(全部存在内存中)
其次是在磁盘中也存储了一个份完成的元数据。有三种格式;


2、磁盘元数据镜像文件fsimage_0000000000000000555


3、数据历史操作日志文件edits: edits_0000000000000000001-0000000000000000018
   (可以通过日志运算出元数据,全部存在磁盘中)
   
4、数据预写操作日志文件 edits_inprogress_0000000000000000556
   (存储在磁盘中)
   
metadata = 最新的 fsimage_0000000000000000555 + edits_inprogress_0000000000000000556
metadata = 所有的edits之和(edits_001_002 + …… + edits_444_555 + edits_inprogress_556)


VERSION文件解析:(存放hdfs集群的版本信息)
		#Sun Jan 06 20:12:30 CST 2017 ## 集群启动时间
		namespaceID=844434736 ## 文件系统唯一标识符
		clusterID=CID-5b7b7321-e43f-456e-bf41-18e77c5e5a40 ## 集群唯一标识符
		cTime=0 ## fsimage 创建的时间,初始为 0,随 layoutVersion 更新
		storageType=NAME_NODE ##节点类型
		blockpoolID=BP-265332847-192.168.123.202-1483581570658 ## 数据块池 ID,可以有多个
		layoutVersion=-60 ## hdfs 持久化数据结构的版本号
查看 edits 文件信息:
hdfs oev -i edits_0000000000000000482-0000000000000000483 -o edits.xml
cat edits.xml




查看 fsimage 镜像文件信息:
hdfs oiv -i fsimage_0000000000000000348 -p XML -o fsimage.xml
cat fsimage.xml




NameNode元数据存储机制:
A、内存中有一份完整的元数据(内存 metadata)
B、磁盘有一个准完整的元数据(fsiamge)文件(在namenode的工作目录中)
C、用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志(edits文件)
   PS:当客户端对HDFS中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,
       当客户端操作成功之后,相应的元数据会更新到内存metadata中




元数据的CheckPoint:	   
每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,
并加载到内存进行merge(这个过程称为checkpoint)


1、namenode把操作方在内存中处理速度更快,但是进程一旦杀掉内存中的数据会被清空,所以同时要把元数据信息
   序列化到磁盘中。
2、但是如果操作时不断的进行序列化,会严重影响性能,所以采用只在开始时序列化一次的机制,之后的操作只存入日志。
3、之后只能把原镜像和日志文件合并即可,这部分操作由secondarynamenode完成,再把合并后的镜像返回给namenode即可;
   所以namenode内有两个镜像和一堆日志文件;


过程:
1、secondarynamenode发起checkpoint请求;
2、namenode进行日志的处理,产生一个新的edits文件,checkpoint完成之前操作写入新的edits_improgress文件
3、将原来序列化镜像和eidts文件拷贝到secondarynamenode中,然后将两者合并出新的metadate;
4、将metadata序列化成新的fsimage文件;
5、将secondarynamenode中新产生的fsimage文件拷贝到namenode中。




重要配置参数:
dfs.namenode.checkpoint.check.period=60  ##检查触发条件是否满足的频率  60秒
dfs.namenode.checkpoint.period=3600  ##两次checkpoint之间的时间间隔3600秒
dfs.namenode.checkpoint.txns=1000000  ##两次checkpoint之间最大的操作记录


CheckPoint附带的作用:
NameNode和SecondaryNamenode的工作目录存储结构完全相同,所以当Namenode故障退出需要重新恢复时,
可以从SecondaryNamenode的工作目录中将fsimage拷贝到NameNode的工作目录,以恢复namenode的元数据。




DataNode工作机制:
1、工作职责:
存储管理用户的文件块数据
定期向namenode汇报自身所持有的block信息(通过心跳信息上报)
<property>
	<!—HDFS 集群数据冗余块的自动删除时长,单位 ms,默认一个小时 -->
	<name>dfs.blockreport.intervalMsec</name>
	<value>3600000</value>
	<description>Determines block reporting interval in milliseconds.</description>
</property>




2、DataNode掉线判断时限参数:就是心跳判断 默认 2 * 5min + 10 * 3s


block块信息地址:
/home/hadoop/hadoopdata/data/current/BP-771296455-192.168.123.106-1504830258603/curr
ent/finalized/subdir0/subdir0




**/	
	

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值