HDFS入门
1.分布式文件系统HDFS
当单台服务器的存储容量和计算性能已经无法处理超大文时,分布式文件系统应运而生。为了存储超大文件,可以将文件切分成很多小“块”,将这些块均匀的存储在多台服务器上,然后,通过一套系统来维护这些文件数据块。当用户需要访问这些超大文件时,该系统将后台多台服务器上存储的“块”进行临时拼装,并返回给统一的客户端,用户就像操作一台计算机一样,自然地访问该超大文件。这套系统就是“分布式文件系统”。
HDFS是基于流式访问模式,为处理超大文件的需求而设计的。HDSF中存放的数据一定是流式数据,是可序列化和反序列化的数据,HDFS不支持存储和访问非序列化的数据。当HDFS设计为流式数据访问模式时,就可以将超大文件序列化为字节的序列或者字节数组来存储,这样不会破坏文件的结构和内容。
- 处理超大文件;
- 流式数据访问模式(一次写入,多次读取);
- 处理非结构化数据;
- 运行于廉价的商用机器集群;
- 发生故障时能继续运行且不被用户察觉。
- 不适合处理低延迟数据访问;
- 无法高效存储大量小型文件;
- 不支持用户写入及任意修改同一文件。
- HDFS中,同一个文件只对应一个写入者,并且只能执行追加操作,不支持多个用户对同一文件的写操作,以及在文件的任意位置上进行修改。
- 可扩展性及可配置性;
- 跨平台性;
- Shell命令行接口;
- Web界面。
2.HDFS核心设计
数据块(block)是HDFS上存储的基本单位。任何一个文件系统都有数据块的概念,只要是文件系统,都涉及文件数据的存储问题,需要相应的数据结构,那么数据块可以说是文件系统上存储数据的基本单位。
Hadoop2.0中,HDFS的数据块大小升级到了128MB,当小于一个数据块大小的文件存储进来时不会占据整个数据块的空间,假如一个文件的大小是10MB,那么剩余的118MB的空间将会被其他文件使用。
为了提升HDFS的可靠性,可以创建多份数据块的副本,并将他们放置在服务器集群的DataNode节点,以便MapReduce分布式计算框架可以在数据所在节点上处理这些数据。
数据块的分布式存储和数据块副本的存放策略。不但可以保证数据的可靠性,还能提供更好的性能。当一个数据有多个副本时,若其中一个副本突然损坏,还可以继续使用剩下的副本。HDFS正是通过数据块冗余的方式来保证数据的可靠性。那么,当一份数据有多个副本时,到底选择哪一个副本呢?这涉及数据块副本的存放策略,若存放恰当便能体现出高性能。
在分布式集群中,通常包含非常多的服务器,由于受到机架槽位和交换机网口的限制,通常大型的分布式集群都是由多个机架组织而成。机架内服务器之间的网络速度通常都会高于跨机架机器之间的网络速度,并且机架之间服务器的网络通信受到上层交换机间网络带宽的限制。
由于Hadoop的HDFS对数据文件的分布式存放是以数据块为单位的,每个数据块会有多个副本(默认为3),并且为了数据的安全和高效,Hadoop中3个副本的存放策略如下:
- 第一个副本放置在客户端所在的DataNode节点中(如果客户端不在集群范围内,则第一个DataNode随机选取,当然原则还是选取距离客户端近的DataNode)
- 第二个副本放置在与第一个节点不同机架中的DataNode中(随机选取)
- 第三个副本放置在与第一个副本所在节点同一机架的另一个节点上。
- 如果还有更多的副本,就随机放在集群的DataNode节点中。
数据块的备份数默认为3,对其配置可以分为以下两种方式:
- 通过配置文件hdfs-sits.cml来设置
<property>
<name>dfs.replication</name>
<value>3</value> <!--设置副本数为3-->
</property>
- 通过命令行方式动态地修改数据块的备份数
hadoop fs -setrep -R 3
第二种方式不需要重启HDFS系统,而第一种只要重启HDFS才能生效。
安全模式是Hadoop集群的一种保护模式,NameNode在启动时会自动进入安全模式,也可手动进入安全模式。与Windows安全模式一样,Hadoop也有自己的安全模式,在安全模式下,用户可以安全的修复系统的某些错误。安全模式是指在不加载第三方设备驱动程序的情况下启动计算机,使计算机运行在系统最简模式,这样用户就可以方便的检测与修复计算机系统的错误。
当Hadoop集群处于安全模式时,HDFS会自动检查数据块的完整性,此时不提供写操作。HDFS是通过数据块副本冗余的方式来保证数据可靠性的,那么对于同一份数据的多个副本来说,其中某个副本可能会经常损坏,损坏了的数据块副本不能正常为客户端提供访问服务。基于这样的原因,HDFS会周期性地检查各个数据块的完整性,如果发现已损坏的数据块,就会及时地向NameNode汇报并做好标记,随后由NameNode负责将修复数据块的任务分配给某个具体的DataNode节点。当然,Hadoop集群进入安全模式之后,只负责数据块的完整性校验工作。
hadoop dfsadmin -safemode leave #强制NameNode退出安全模式
hadoop dfsadmin -safemode enter #进入安全模式
hadoop dfsadmin -safemode get #查看安全模式状态
hadoop dfsadmin -safemode wait #等待,一直到安全模式结束
在Hadoop的HDFS网络集群中,由于集群规模庞大,非常容易出现服务器与服务器之间磁盘利用率不均衡的情况。当数据不均衡时,映射任务可能会分配给没有存储数据的机器,这将导致网络带宽的消耗,也无法很好的进行本地计算。
当HDFS负载不均衡的时候,需要对HDFS进行数据的负载均衡做调整,即对各节点机器上数据的存储分布进行调整,从而让数据均匀地分布在各个DataNode节点上,均衡I/O性能,防止热点的发生。然而进行负载均衡,必须满足以下原则:
- 数据均衡不能导致数据块减少或数据备份丢失
- 管理员可以终止数据均衡进程
- 每次移动的数据量以及占用的网络资源必须是可控的
- 数据均衡过程,不能影响NameNode的正常工作
- Hadoop负载均衡的原理
- DataNode分组
- Over
- Above
- Below
- Under
三条分界线从上到下依次为上阈值、集群的均值和下阈值。
对于Over组中的的DataNode节点均满足数据迁移的条件
DataNode_usedspace_percent > Cluster_usedspace_percent + up_threshold
其余的几组类似。
- HDFS数据负载均衡脚本使用方法
Hadoop中包含一个start-threshold.sh脚本,通过运行它,可以启动HDFS数据均衡服务。该工作可以做到热插拔。即无需重新动计算机很Hadoop服务。
影响balancer的参数如下:
- -threshold
默认设置为10,参数取值范围为0-100 - dfs.balance.bandwidthPerSec
默认设置为1048576(1MB/s) - 在hdfs-site.xml中可以设置负载均衡占用的网络带宽
<property>
<name>dfs.balance.bandwidthPerSec</name>
<value>1057576</value>
</property>
心跳机制
在计算机集群远程长连接应用场景中,有可能很长一段时间,节点与节点之间都没有呢数据往来,但应该是一直保持连接,不过中间节点出现故障时难以得知的,某些节点(如防火墙)甚至会自动把一定时间内没有数据交互的连接中断。这个时候就需要心跳数据包来维持连接,保持节点与节点之间的通信。
从节点通过心跳给主节点汇报自己的信息,主节点通过心跳来给从节点下达命令。NameNode通过心跳得知DataNode的状态信息,ResourceManager通过心跳得知NodeManager的状态。,如果主节点长时间没有收到从节点的心跳信息,主节点就认为从节点已失效,这就是HDFS心跳机制。
3.HDFS体系结构
主从架构
一个HDFS集群由多个NameNode节点和多个DataNode节点组成。
NameNode节点作为主控服务器节点,负责管理HDFS的命名空间,记录文件数据块在每个DataNode节点上的位置和副本信息,协调客户端对文件的访问操作,以及记录命名空间内的改动命令或命名空间本身属性的改动等信息。
DataNode是数据存储节点,负责自身所在物理节点上的存储管理。客户端访问操作数据,是通过向NameNode发起请求并获取文件数据所在DataNode节点的地址信息的。对数据流的读写操作在DataNode节点完成,NameNode节点不会参与文件数据流的读写,而是由DataNode节点负责完成。
核心组件功能
HDFS核心组件包括NameNode、DataNode和SecondaryNameNode。
- NameNode负责维护文件系统树,他不存储与真实数据,而是存储元数据,NameNode保存在内存中。
- DataNode在磁盘上保存数据的基本单位是数据块,默认大小是128MB。DataNode负责处理文件系统客端的读写请求,在NameNode的统一调度下进行数据块的创建、删除和复制。NameNode是所有HDFS元数据的仲裁者和管理者,这样,用户数据永远不会流经NameNode,对于文件操作,NameNode只负责处理文件元数据的操作,DataNode负责处理文件内容的读写请求,数据流不经过NameNode,客户端只会询问NameNode将要访问的文件数据跟哪个DataNode有联系。文件副本存放在哪些DataNode上由NameNode来控制。
- NameNode负责管理数据块的副本,他按照一定的周期,接收来自每个DataNode的心跳信号和状态报告。通过心跳信号判断DataNode节点工作是否正常,而块状态报告包含了某DataNode节点上存储的所有数据块的列表信息.
[master@master var]$ tree
.
└── hadoop
├── dfs
│ ├── data
│ └── name
│ ├── current
│ │ ├── edits_0000000000000000001-0000000000000000002
│ │ ├── edits_0000000000000000003-0000000000000000154
│ │ ├── edits_0000000000000000155-0000000000000000156
│ │ ├── edits_0000000000000000157-0000000000000000158
│ │ ├── edits_0000000000000000159-0000000000000000160
│ │ ├── edits_0000000000000000161-0000000000000000162
│ │ ├── edits_0000000000000000163-0000000000000000163
│ │ ├── edits_0000000000000000164-0000000000000000165
│ │ ├── edits_0000000000000000166-0000000000000000167
│ │ ├── edits_inprogress_0000000000000000168
│ │ ├── fsimage_0000000000000000165
│ │ ├── fsimage_0000000000000000165.md5
│ │ ├── fsimage_0000000000000000167
│ │ ├── fsimage_0000000000000000167.md5
│ │ ├── seen_txid
│ │ └── VERSION
│ └── in_use.lock
├── tmp
│ └── dfs
│ └── namesecondary
│ ├── current
│ │ ├── edits_0000000000000000001-0000000000000000002
│ │ ├── edits_0000000000000000003-0000000000000000154
│ │ ├── edits_0000000000000000155-0000000000000000156
│ │ ├── edits_0000000000000000157-0000000000000000158
│ │ ├── edits_0000000000000000159-0000000000000000160
│ │ ├── edits_0000000000000000161-0000000000000000162
│ │ ├── edits_0000000000000000164-0000000000000000165
│ │ ├── edits_0000000000000000166-0000000000000000167
│ │ ├── fsimage_0000000000000000165
│ │ ├── fsimage_0000000000000000165.md5
│ │ ├── fsimage_0000000000000000167
│ │ ├── fsimage_0000000000000000167.md5
│ │ └── VERSION
│ └── in_use.lock
└── var
- fsimage对元数据定期进行镜像操作,形成镜像文件。
- edits文件存放一定时间内用户对HDFS进行的操作
- checkpoint是检查点,随着对HDFS的不断操作,edits文件会越来越多,当达到某一阈值时(一般该阈值默认是64MB或者3600s)就会触发检查点,此时SecondaryNameNode就要开始工作了。namesecondary目录下的edits和fsimage文件就是检查点被触发之后检查任务产生的结果。
- 以下为SecondaryNameNode同步元数据的过程图:
数据块损坏处理
HDFS生成数据块副本都会生成一个校验码,用来检测或校验数据传输或者保存时候所产生的错误。校验码会以文件的形式存储,并且与数据块存放在一起。当客户端从DataNode上读取数据的时候,会再次计算校验和,如果计算之后的校验和与该数据块在创建时候的校验和不一样,则说明该数据块已经损坏。此时,客户端就不会继续读取数据块了,而是向NameNode申请读取该数据块的其他副本。同时客户端会把已经损坏的数据块的信息汇报给NameNode,NameNode会立即标记该数据块的状态为已损坏。然后NameNode从该数据块的正常副本中再复制一份副本,NameNode将复制出来的数据块副本分配到合适的DataNode节点上,从而保证集群中文件数据的各个数据块副本时始终是3个。
另外。DataNode还有一个自检过程,就是在数据块创建三周之后,自动触发校验和运算,以保证集群中数据块的安全。