Hadoop初级之HDFS系统
一 HDFS概述
1.1 HDFS产生背景
随着数据量越来越大,在一个操作系统管辖的范围内存不下了,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种。
1.2 HDFS概念
HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
HDFS的设计适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。
1.3 HDFS优缺点
1.3.1 优点
理解性的记忆
1)高容错性
(1)数据自动保存多个副本。它通过增加副本的形式,提高容错性。
(2)某一个副本丢失以后,它可以自动恢复。
2)适合大数据处理
(1)数据规模:能够处理数据规模达到 GB、TB、甚至PB级别的数据。
(2)文件规模:能够处理百万规模以上的文件数量,数量相当之大。
3)流式数据访问
(1)一次写入,多次读取,不能修改,只能追加。
(2)它能保证数据的一致性。
4)可构建在廉价机器上,通过多副本机制,提高可靠性。
1.3.2 缺点
1)不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
2)无法高效的对大量小文件进行存储
(1)存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是有限的。
(2)小文件存储的寻道时间会超过读取时间,它违反了HDFS的设计目标。
3)并发写入、文件随机修改
(1)一个文件只能有一个写,不允许多个线程同时写。
(2)仅支持数据 append(追加),不支持文件的随机修改。
1.4 HDFS架构
1)Client:就是客户端。
(1)文件切分。文件上传 HDFS 的时候,Client 将文件切分成一个一个的Block,然后进行存储。
(2)与NameNode交互,获取文件的位置信息。
(3)与DataNode交互,读取或者写入数据。
(4)Client提供一些命令来管理HDFS,比如启动或者关闭HDFS。
(5)Client可以通过一些命令来访问HDFS。
2)NameNode:就是master,它是一个主管、管理者。
(1)管理HDFS的名称空间。
(2)管理数据块(Block)映射信息
(3)配置副本策略
(4)处理客户端读写请求。
3) DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作。
(1)存储实际的数据块。
(2)执行数据块的读/写操作。
4) Secondary NameNode:并非NameNode的热备。冷备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
(1)辅助NameNode,分担其工作量。
(2)定期合并Fsimage和Edits,并推送给NameNode。
(3)在紧急情况下,可辅助恢复NameNode。
1.5 HDFS 文件块大小
HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M。
HDFS的块比磁盘的块大,其目的是为了最小化寻址开销。如果块设置得足够大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。因而,传输一个由多个块组成的文件的时间取决于磁盘传输速率。
如果寻址时间约为10ms,而传输速率为100MB/s,为了使寻址时间仅占传输时间的1%,我们要将块大小设置约为100MB。默认的块大小128MB。
块的大小:10ms*100*100M/s = 100M
二 HFDS命令行操作
1.1. 1)基本语法
hadoop fs 具体命令
1.2. 2)参数大全
[root@jh hadoop-2.7.2]$ bin/hadoop fs
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]查看
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] <path> ...]
[-cp [-f] [-p] <src> ... <dst>]复制
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]查看文件大小
[-expunge]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]帮助文档
[-ls [-d] [-h] [-R] [<path> ...]]查看某个路径下的所有信息
[-mkdir [-p] <path> ...]创建文件将爱
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]移动
[-put [-f] [-p] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]删除
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]删除空目录
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]查看文件后几行或者 动态查看
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]创建文件
[-usage [cmd ...]]
1.3. 3)常用命令实操
(0)启动Hadoop集群(方便后续的测试)
[root@jh hadoop-2.7.2]$ sbin/start-dfs.sh
[root@jh02 hadoop-2.7.2]$ sbin/start-yarn.sh
(1)-help:输出这个命令参数
[root@jh hadoop-2.7.2]$ hadoop fs -help rm
(2)-ls: 显示目录信息
[root@jh hadoop-2.7.2]$ hadoop fs -ls /
(3)-mkdir:在hdfs上创建目录
[root@jh hadoop-2.7.2]$ hadoop fs -mkdir -p /user/root/test
(4)-moveFromLocal从本地剪切粘贴到hdfs
[root@jh hadoop-2.7.2]$ touch test01.txt
[root@jh hadoop-2.7.2]$ hadoop fs -moveFromLocal ./test01.txt /user/root/test
(5)-appendToFile :追加一个文件到已经存在的文件末尾
[root@jh hadoop-2.7.2]$ touch ximen.txt
[root@jh hadoop-2.7.2]$ vi ximen.txt
输入
wo ai test01
[root@jh hadoop-2.7.2]$ hadoop fs -appendToFile ximen.txt本地文本 /user/root/test/test01.txt
(6)-cat :显示文件内容
(7)-tail:显示一个文件的末尾
[root@jh hadoop-2.7.2]$ hadoop fs -tail /user/root/test/test01.txt
(8)-chgrp 、-chmod、-chown:linux文件系统中的用法一样,修改文件所属权限
[root@jh hadoop-2.7.2]$ hadoop fs -chmod 666 /user/root/test/test01.txt
[root@jh hadoop-2.7.2]$ hadoop fs -chown root:root /user/root/test/test01.txt
(9)-copyFromLocal:从本地文件系统中拷贝文件到hdfs路径去
[root@jh hadoop-2.7.2]$ hadoop fs -copyFromLocal README.txt /user/root/test
(10)-copyToLocal:从hdfs拷贝到本地
[root@jh hadoop-2.7.2]$ hadoop fs -copyToLocal /user/root/test/test01.txt ./test01.txt
(11)-cp :从hdfs的一个路径拷贝到hdfs的另一个路径
[root@jh hadoop-2.7.2]$ hadoop fs -cp /user/root/test/test01.txt /test012.txt
(12)-mv:在hdfs目录中移动文件
[root@jh hadoop-2.7.2]$ hadoop fs -mv /test012.txt /user/root/test/
(13)-get:等同于copyToLocal,就是从hdfs下载文件到本地
[root@jh hadoop-2.7.2]$ hadoop fs -get /user/root/test/test012.txt ./
(14)-getmerge :合并下载多个文件,比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,...
[root@jh hadoop-2.7.2]$ hadoop fs -getmerge /user/root/test/* ./zaiyiqi.txt
(15)-put:等同于copyFromLocal
[root@jh hadoop-2.7.2]$ hadoop fs -put ./zaiyiqi.txt /user/root/test/
(16)-rm:删除文件或文件夹
[root@jh hadoop-2.7.2]$ hadoop fs -rm /user/root/test/test012.txt
(17)-rmdir:删除空目录
[root@jh hadoop-2.7.2]$ hadoop fs -mkdir /test
[root@jh hadoop-2.7.2]$ hadoop fs -rmdir /test
(18)-df :统计文件系统的可用空间信息
[root@jh hadoop-2.7.2]$ hadoop fs -df -h /
(19)-du统计文件夹的大小信息
[root@jh hadoop-2.7.2]$ hadoop fs -du -s -h /user/root/test
2.7 K /user/root/test
[root@jh hadoop-2.7.2]$ hadoop fs -du -h /user/root/test
1.3 K /user/root/test/README.txt
15 /user/root/test/test01.txt
1.4 K /user/root/test/zaiyiqi.txt
(20)-setrep:设置hdfs中文件的副本数量 3
[root@jh hadoop-2.7.2]$ hadoop fs -setrep 2 /user/root/test/test01.txt
这里设置的副本数只是记录在namenode的元数据中,是否真的会有这么多副本,还得看datanode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到10台时,副本数才能达到10。
三 HDFS客户端操作
3.1 HDFS客户端环境准备
1.3.1. HDFS客户端环境准备.doc
3.2 通过API操作HDFS
3.2.1 HDFS获取文件系统
1 创建配置信息对象
2 获取文件系统
3 打印文件系统
3.2.2 HDFS文件上传(测试参数优先级)
1 获取文件系统
2 上传文件
3 关闭资源
3.2.3 HDFS文件下载
1 获取文件系统
2 下载文件
3 关闭资源
3.2.4 HDFS目录创建
1 获取文件系统
2 创建目录
3 关闭资源
3.2.5 HDFS文件夹删除
1 获取文件系统
2 删除文件夹
3 关闭资源
3.2.6 HDFS文件名更改
1 获取文件系统
2 重命名文件或文件夹
3 关闭资源
3.2.7 HDFS文件详情查看
查看文件名称、权限、长度、块信息
3.2.8 HDFS文件和文件夹判断
1 获取文件系统
2 判断是文件还是文件夹
3 关闭资源
3.3 通过IO流操作HDFS
3.3.1 HDFS文件上传
1 获取文件系统
2 创建输入流
3 获取输出流
4 流对拷
5 关闭资源
3.3.2 HDFS文件下载
1)需求:从HDFS上下载文件到本地控制台上。
2)实操:
1 获取文件系统
2 获取输入流
3 获取输出流
4 流对拷
5 关闭资源
3.3.3 定位文件读取
1)下载第一块
1 获取文件系统
2 获取输入流
3 创建输出流
4 流的对拷
5 关闭资源
2)下载第二块
1 获取文件系统
2 打开输入流
3 定位输入数据位置
4 创建输出流
5 流的对拷
6 关闭资源
3)合并文件
在window命令窗口中执行
type hadoop-2.7.2.tar.gz.part2 >> hadoop-2.7.2.tar.gz.part1
四 HDFS的数据流
4.1 HDFS写数据流程
4.1.1 剖析文件写入
1)客户端通过Distributed FileSystem模块向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在。
2)namenode返回是否可以上传。
3)客户端请求第一个 block上传到哪几个datanode服务器上。
4)namenode返回3个datanode节点,分别为dn1、dn2、dn3。
5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
6)dn1、dn2、dn3逐级应答客户端。
7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
8)当一个block传输完成之后,客户端再次请求namenode上传第二个block的服务器。(重复执行3-7步)。
4.1.2 网络拓扑概念
在本地网络中,两个节点被称为“彼此近邻”是什么意思?在海量数据处理中,其主要限制因素是节点之间数据的传输速率——带宽很稀缺。这里的想法是将两个节点间的带宽作为距离的衡量标准。
节点距离:两个节点到达最近的共同祖先的距离总和。
算一算每两个节点之间的距离。
4.1.3 机架感知(副本节点选择)
1)官方ip地址:
http://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-common/RackAwareness.html
2)Hadoop2.7.2副本节点选择
第一个副本在client所处的节点上。如果客户端在集群外,随机选一个。
第二个副本和第一个副本位于相同机架,随机节点。
第三个副本位于不同机架,随机节点。(原因:避免机架宕机)
3)HDFS如何控制客户端读取哪个副本节点数据
HDFS满足客户端访问副本数据的最近原则。即客户端距离哪个副本数据最近,HDFS就让哪个节点把数据给客户端。
4.2 HDFS读数据流程
1)客户端通过Distributed FileSystem向namenode请求下载文件,namenode通过查询元数据,找到文件块所在的datanode地址。
2)挑选一台datanode(就近原则,然后随机)服务器,请求读取数据。
3)datanode开始传输数据给客户端(从磁盘里面读取数据输入流,以packet为单位来做校验)。
4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件。
4.3 一致性模型
1.3.2. 1)debug调试如下代码
// 向HDFS上写数据
@Test
public void writeFile() throws IOException, InterruptedException, URISyntaxException{
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://jh:9000"), configuration, "root");
// 2 获取输出流
FSDataOutputStream fos = fs.create(new Path("/hello.txt"));
// 3 写数据
fos.write("hello".getBytes());
// 4 一致性刷新
fos.hflush();
// 5 关闭资源
fos.close();
fs.close();
}
2)总结
写入数据时,如果希望数据被其他client立即可见,调用如下方法
FsDataOutputStream.hflush(); //清理客户端缓冲区数据,被其他client立即可见
五 NameNode工作机制
5.1 NameNode&Secondary NameNode工作机制
冷备:定时定点备份。
热备:就是一有改动,就备份。
1)第一阶段:namenode启动
1)第一次启动namenode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
2)客户端对元数据进行增删改的请求
3)namenode记录操作日志,更新滚动日志。
4)namenode在内存中对数据进行增删改
2)第二阶段:Secondary NameNode工作
1)Secondary NameNode询问namenode是否需要checkpoint。直接带回namenode是否检查结果。
2)Secondary NameNode请求执行checkpoint。
3)namenode滚动正在写的edits日志
4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode
5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
6)生成新的镜像文件fsimage.chkpoint
7)拷贝fsimage.chkpoint到namenode
8)namenode将fsimage.chkpoint重新命名成fsimage
5.2 镜像文件和编辑日志文件
1)概念
namenode被格式化之后,将在/opt/hadoop-2.7.2/hadoopdata/dfs/name/current目录中产生如下文件
fsimage_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSION
(1)Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件idnode的序列化信息。
(2)Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中。
(3)seen_txid文件保存的是一个数字,就是最后一个edits_的数字
(4)每次Namenode启动的时候都会将fsimage文件读入内存,并从00001开始到seen_txid中记录的数字依次执行每个edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成Namenode启动的时候就将fsimage和edits文件进行了合并。
2)oiv查看fsimage文件
(1)查看oiv和oev命令
[root@jh current]$ hdfs
oiv apply the offline fsimage viewer to an fsimage
oev apply the offline edits viewer to an edits file
(2)基本语法
hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
(3)案例实操
[root@jh current]$ pwd
/opt/hadoop-2.7.2/hadoopdata/dfs/name/current
[root@jh current]$ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/hadoop-2.7.2/fsimage.xml
[root@jh current]$ cat /opt/hadoop-2.7.2/fsimage.xml
将显示的xml文件内容拷贝到idea中创建的xml文件中,并格式化。
部分显示结果如下:
<inode>
<id>16386</id>
<type>DIRECTORY</type>
<name>user</name>
<mtime>1512722284477</mtime>
<permission>root:supergroup:rwxr-xr-x</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16387</id>
<type>DIRECTORY</type>
<name>root</name>
<mtime>1512790549080</mtime>
<permission>root:supergroup:rwxr-xr-x</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16389</id>
<type>FILE</type>
<name>wc.input</name>
<replication>3</replication>
<mtime>1512722322219</mtime>
<atime>1512722321610</atime>
<perferredBlockSize>134217728</perferredBlockSize>
<permission>root:supergroup:rw-r--r--</permission>
<blocks>
<block>
<id>1073741825</id>
<genstamp>1001</genstamp>
<numBytes>59</numBytes>
</block>
</blocks>
</inode>
3)oev查看edits文件
(1)基本语法
hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
(2)案例实操
[root@jh current]$ hdfs oev -p XML -i
edits_0000000000000000012-0000000000000000013 -o /opt/hadoop-2.7.2/edits.xml
[root@jh current]$ cat /opt/hadoop-2.7.2/edits.xml
将显示的xml文件内容拷贝到idea中创建的xml文件中,并格式化。
显示结果如下:
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
<EDITS_VERSION>-63</EDITS_VERSION>
<RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>129</TXID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_ADD</OPCODE>添加操作
<DATA>
<TXID>130</TXID>
<LENGTH>0</LENGTH>
<INODEID>16407</INODEID>
<PATH>/hello7.txt</PATH>
<REPLICATION>2</REPLICATION>
<MTIME>1512943607866</MTIME>
<ATIME>1512943607866</ATIME>
<BLOCKSIZE>134217728</BLOCKSIZE>
<CLIENT_NAME>DFSClient_NONMAPREDUCE_-1544295051_1</CLIENT_NAME>
<CLIENT_MACHINE>192.168.1.5</CLIENT_MACHINE>
<OVERWRITE>true</OVERWRITE>
<PERMISSION_STATUS>
<USERNAME>root</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>420</MODE>
</PERMISSION_STATUS>
<RPC_CLIENTID>908eafd4-9aec-4288-96f1-e8011d181561</RPC_CLIENTID>
<RPC_CALLID>0</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE>
<DATA>
<TXID>131</TXID>
<BLOCK_ID>1073741839</BLOCK_ID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_GENSTAMP_V2</OPCODE>
<DATA>
<TXID>132</TXID>
<GENSTAMPV2>1016</GENSTAMPV2>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_ADD_BLOCK</OPCODE>
<DATA>
<TXID>133</TXID>
<PATH>/hello7.txt</PATH>
<BLOCK>
<BLOCK_ID>1073741839</BLOCK_ID>
<NUM_BYTES>0</NUM_BYTES>
<GENSTAMP>1016</GENSTAMP>
</BLOCK>
<RPC_CLIENTID></RPC_CLIENTID>
<RPC_CALLID>-2</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_CLOSE</OPCODE>
<DATA>
<TXID>134</TXID>
<LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/hello7.txt</PATH>
<REPLICATION>2</REPLICATION>
<MTIME>1512943608761</MTIME>
<ATIME>1512943607866</ATIME>
<BLOCKSIZE>134217728</BLOCKSIZE>
<CLIENT_NAME></CLIENT_NAME>
<CLIENT_MACHINE></CLIENT_MACHINE>
<OVERWRITE>false</OVERWRITE>
<BLOCK>
<BLOCK_ID>1073741839</BLOCK_ID>
<NUM_BYTES>25</NUM_BYTES>
<GENSTAMP>1016</GENSTAMP>
</BLOCK>
<PERMISSION_STATUS>
<USERNAME>root</USERNAME>
<GROUPNAME>supergroup</GROUPNAME>
<MODE>420</MODE>
</PERMISSION_STATUS>
</DATA>
</RECORD>
</EDITS>
5.3 滚动编辑日志
正常情况HDFS文件系统有更新操作时,就会滚动编辑日志。也可以用命令强制滚动编辑日志。
1)滚动编辑日志(前提必须启动集群)
[root@jh current]$ hdfs dfsadmin -rollEdits
2)镜像文件什么时候产生
Namenode启动时加载镜像文件和编辑日志
5.4 Namenode版本号
1)查看namenode版本号
在/opt/hadoop-2.7.2/hadoopdata/dfs/name/current这个目录下查看VERSION
namespaceID=1933630176
clusterID=CID-1f2bf8d1-5ad2-4202-af1c-6713ab381175
cTime=0
storageType=NAME_NODE
blockpoolID=BP-97847618-192.168.10.102-1493726072779
layoutVersion=-63
在/opt/hadoop-2.7.2/hadoopdata/dfs/name/current这个目录下查看VERSION
2)namenode版本号具体解释
(1)namespaceID在HDFS上,会有多个Namenode,所以不同Namenode的namespaceID是不同的,分别管理一组blockpoolID。
(2)clusterID集群id,全局唯一
(3)cTime属性标记了namenode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。
(4)storageType属性说明该存储目录包含的是namenode的数据结构。
(5)blockpoolID:一个block pool id标识一个block pool,并且是跨集群的全局唯一。当一个新的Namespace被创建的时候(format过程的一部分)会创建并持久化一个唯一ID。在创建过程构建全局唯一的BlockPoolID比人为的配置更可靠一些。NN将BlockPoolID持久化到磁盘中,在后续的启动过程中,会再次load并使用。
(6)layoutVersion是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。
5.5 web端访问SecondaryNameNode
(1)启动集群
(2)浏览器中输入:http://jh:50090/status.html
5.6 chkpoint检查时间参数设置
(1)通常情况下,SecondaryNameNode每隔一小时执行一次。
[hdfs-site.xml]
3600 就是一个小时
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
(2)一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作动作次数</description>
</property>
<property>
<name>fs.checkpoint.dir</name>
<value>file:///root/hdpdata/namesecondary</value>
</property>
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description> 1分钟检查一次操作次数</description>
</property>
(1)通常情况下,SecondaryNameNode每隔一小时执行一次。
(2)一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。
5.7 SecondaryNameNode目录结构
Secondary NameNode用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。
在/opt/hadoop-2.7.2/hadoopdata/dfs/namesecondary/current这个目录中查看SecondaryNameNode目录结构。
edits_0000000000000000001-0000000000000000002
fsimage_0000000000000000002
fsimage_0000000000000000002.md5
VERSION
SecondaryNameNode的namesecondary/current目录和主namenode的current目录的布局相同。
好处:在主namenode发生故障时(假设没有及时备份数据),可以从SecondaryNameNode恢复数据。
5.8 Namenode故障处理方法
Namenode故障处理方法
Namenode故障后,可以采用如下两种方法恢复数据。
方法一:将SecondaryNameNode中数据拷贝到namenode存储数据的目录;
方法二:使用-importCheckpoint选项启动namenode守护进程,从而将SecondaryNameNode中数据拷贝到namenode目录中。
1 手动拷贝SecondaryNameNode数据:
模拟namenode故障,并采用方法一,恢复namenode数据
1)kill -9 namenode进程
2)删除namenode存储的数据(/opt/hadoop-2.7.2/hadoopdata/dfs/name)
[root@jh hadoop-2.7.2]$ rm -rf /opt/hadoop-2.7.2/hadoopdata/dfs/name/*
3)拷贝SecondaryNameNode中数据到原namenode存储数据目录
[root@jh dfs]$ scp -r root@jh02:/opt/hadoop-2.7.2/hadoopdata/dfs/namesecondary/* ./name/
4)重新启动namenode
[root@jh hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
2 采用importCheckpoint命令拷贝SecondaryNameNode数据
模拟namenode故障,并采用方法二,恢复namenode数据
0)修改hdfs-site.xml中的
<property> <name>dfs.namenode.checkpoint.period</name> <value>60</value> </property>
<property> <name>dfs.namenode.name.dir</name> <value>/opt/hadoop-2.7.2/hadoopdata/dfs/name</value> </property> |
1)kill -9 namenode进程
2)删除namenode存储的数据(/opt/hadoop-2.7.2/hadoopdata/dfs/name)
[root@jh hadoop-2.7.2]$ rm -rf /opt/hadoop-2.7.2/hadoopdata/dfs/name/*
3)如果SecondaryNameNode不和Namenode在一个主机节点上,需要将SecondaryNameNode存储数据的目录拷贝到Namenode存储数据的平级目录,并删除in_use.lock文件。
[root@jh dfs]$ scp -r root@jh02:/opt/hadoop-2.7.2/hadoopdata/dfs/namesecondary ./
[root@jh namesecondary]$ rm -rf in_use.lock
[root@jh dfs]$ pwd /opt/hadoop-2.7.2/hadoopdata/dfs
[root@jh dfs]$ ls data name namesecondary |
4)导入检查点数据(等待一会ctrl+c结束掉)
[root@jh hadoop-2.7.2]$ bin/hdfs namenode -importCheckpoint
5)启动namenode
[root@jh hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
5.9 集群安全模式操作
1)概述
Namenode启动时,首先将映像文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作。一旦在内存中成功建立文件系统元数据的映像,则创建一个新的fsimage文件和一个空的编辑日志。此时,namenode开始监听datanode请求。但是此刻,namenode运行在安全模式,即namenode的文件系统对于客户端来说是只读的。
系统中的数据块的位置并不是由namenode维护的,而是以块列表的形式存储在datanode中。在系统的正常操作期间,namenode会在内存中保留所有块位置的映射信息。在安全模式下,各个datanode会向namenode发送最新的块列表信息,namenode了解到足够多的块位置信息之后,即可高效运行文件系统。
如果满足“最小副本条件”,namenode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1)。在启动一个刚刚格式化的HDFS集群时,因为系统中还没有任何块,所以namenode不会进入安全模式。
2)基本语法
集群处于安全模式,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。
(1)hdfs dfsadmin -safemode get (功能描述:查看安全模式状态)
(2)hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态)
(3)hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态)
(4)hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)
3)案例
模拟等待安全模式
1)先进入安全模式
[root@jh hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode enter
2)执行下面的脚本
#!/bin/bash
bin/hdfs dfsadmin -safemode wait
bin/hdfs dfs -put ~/hello.txt /root/hello.txt
3)再打开一个窗口,执行
[root@jh hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode leave
5.10 Namenode多目录配置
1)namenode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。
2)具体配置如下:
(1)在hdfs-site.xml文件中增加如下内容
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</value>
</property>
(2)停止集群,删除data和logs中所有数据。
[root@jh hadoop-2.7.2]$ rm -rf /root/hdpdata/data/ /root/apps/hadoop-2.8.1/logs/
[root@jh02 hadoop-2.7.2]$ rm -rf data/ logs/
[root@hadoop104 hadoop-2.7.2]$ rm -rf data/ logs/
(3)格式化集群并启动。
[root@jh hadoop-2.7.2]$ bin/hdfs namenode -format
[root@jh hadoop-2.7.2]$ sbin/start-dfs.sh
(4)查看结果
[root@jh dfs]$ ll
总用量 12
drwx------. 3 root root 4096 12月 11 08:03 data
drwxrwxr-x. 3 root root 4096 12月 11 08:03 name1
drwxrwxr-x. 3 root root 4096 12月 11 08:03 name2
六 DataNode工作机制
6.1 DataNode工作机制
1)一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
2)DataNode启动后向namenode注册,通过后,周期性(1小时)的向namenode上报所有的块信息。
3)心跳是每3秒一次,心跳返回结果带有namenode给该datanode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用。
4)集群运行中可以安全加入和退出一些机器
6.2 数据完整性
1)当DataNode读取block的时候,它会计算checksum。
2)如果计算后的checksum,与block创建时值不一样,说明block已经损坏。
3)client读取其他DataNode上的block。
4)datanode在其文件创建后周期验证checksum。
6.3 掉线时限参数设置
datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为:
timeout = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。
而默认的dfs.namenode.heartbeat.recheck-interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。
<property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value> </property> <property> <name> dfs.heartbeat.interval </name> <value>3</value> </property> |
6.4 DataNode的目录结构
和namenode不同的是,datanode的存储目录是初始阶段自动创建的,不需要额外格式化。
1)在/opt/hadoop-2.7.2/hadoopdata/dfs/data/current这个目录下查看版本号
[root@jh02 current]$ cat VERSION
storageID=DS-1b998a1d-71a3-43d5-82dc-c0ff3294921b
clusterID=CID-1f2bf8d1-5ad2-4202-af1c-6713ab381175
cTime=0
datanodeUuid=970b2daf-63b8-4e17-a514-d81741392165
storageType=DATA_NODE
layoutVersion=-56
2)具体解释
(1)storageID:存储id号
(2)clusterID集群id,全局唯一
(3)cTime属性标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。
(4)datanodeUuid:datanode的唯一识别码
(5)storageType:存储类型
(6)layoutVersion是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。
3)在/opt/hadoop-2.7.2/hadoopdata/dfs/data/current/BP-97847618-192.168.10.102-1493726072779/current这个目录下查看该数据块的版本号
[root@jh02 current]$ cat VERSION
#Mon May 08 16:30:19 CST 2017
namespaceID=1933630176
cTime=0
blockpoolID=BP-97847618-192.168.10.102-1493726072779
layoutVersion=-56
4)具体解释
(1)namespaceID:是datanode首次访问namenode的时候从namenode处获取的storageID对每个datanode来说是唯一的(但对于单个datanode中所有存储目录来说则是相同的),namenode可用这个属性来区分不同datanode。
(2)cTime属性标记了datanode存储系统的创建时间,对于刚刚格式化的存储系统,这个属性为0;但是在文件系统升级之后,该值会更新到新的时间戳。
(3)blockpoolID:一个block pool id标识一个block pool,并且是跨集群的全局唯一。当一个新的Namespace被创建的时候(format过程的一部分)会创建并持久化一个唯一ID。在创建过程构建全局唯一的BlockPoolID比人为的配置更可靠一些。NN将BlockPoolID持久化到磁盘中,在后续的启动过程中,会再次load并使用。
(4)layoutVersion是一个负整数。通常只有HDFS增加新特性时才会更新这个版本号。
6.5 服役新数据节点
0)需求:
随着公司业务的增长,数据量越来越大,原有的数据节点的容量已经不能满足存储数据的需求,需要在原有集群基础上动态添加新的数据节点。
1)环境准备
(1)克隆一台虚拟机
(2)修改ip地址 和主机名称
(3)增加新增节点的同步ssh 免密登录
(4)删除原来HDFS文件系统留存的文件
/opt/hadoop-2.7.2/data
2)服役新节点具体步骤
(1)在namenode的/opt/hadoop-2.7.2/etc/hadoop目录下创建dfs.hosts文件
[root@jh03 hadoop]$ pwd
/opt/hadoop-2.7.2/etc/hadoop
[root@jh03 hadoop]$ touch dfs.hosts
[root@jh03 hadoop]$ vi dfs.hosts
添加如下主机名称(包含新服役的节点)
jh01
jh02
jh04
jh03
(2)在namenode的hdfs-site.xml配置文件中增加dfs.hosts属性
<property>
<name>dfs.hosts</name>
<value>/opt/hadoop-2.7.2/etc/hadoop/dfs.hosts</value>
</property>
(3)刷新namenode
[root@jh hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful
(4)更新resourcemanager节点
[root@jh hadoop-2.7.2]$ yarn rmadmin -refreshNodes
17/06/24 14:17:11 INFO client.RMProxy: Connecting to ResourceManager at jh02/192.168.8.115:8033
(5)在namenode的slaves文件中增加新主机名称
(6)单独命令启动新的数据节点和节点管理器
[root@jh03 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start datanode
starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-jh03.out
[root@jh03 hadoop-2.7.2]$ sbin/yarn-daemon.sh start nodemanager
starting nodemanager, logging to /opt/hadoop-2.7.2/logs/yarn-root-nodemanager-jh03.out
(7)在web浏览器上检查是否ok
1.3.3. 3)如果数据不均衡,可以用命令实现集群的再平衡
[root@jh sbin]$ ./start-balancer.sh
starting balancer, logging to /opt/hadoop-2.7.2/logs/hadoop-root-balancer-jh.out
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
6.6 退役旧数据节点
1)在namenode的/opt/hadoop-2.7.2/etc/hadoop目录下创建dfs.hosts.exclude文件
[root@jh hadoop]$ pwd
/opt/hadoop-2.7.2/etc/hadoop
[root@jh hadoop]$ touch dfs.hosts.exclude
[root@jh hadoop]$ vi dfs.hosts.exclude
添加如下主机名称(要退役的节点)
jh03
2)在namenode的hdfs-site.xml配置文件中增加dfs.hosts.exclude属性
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/hadoop-2.7.2/etc/hadoop/dfs.hosts.exclude</value>
</property>
3)刷新namenode、刷新resourcemanager
[root@jh hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@jh hadoop-2.7.2]$ yarn rmadmin -refreshNodes
17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at jh02/192.168.1.103:8033
4)检查web浏览器,退役节点的状态为decommission in progress(退役中),说明数据节点正在复制块到其他节点。
5)等待退役节点状态为decommissioned(所有块已经复制完成),停止该节点及节点资源管理器。注意:如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役。
[root@jh03 hadoop-2.7.2]$ hadoop-daemon.sh stop datanode
stopping datanode
[root@jh03 hadoop-2.7.2]$ yarn-daemon.sh stop nodemanager
stopping nodemanager
6)从include文件中删除退役节点,再运行刷新节点的命令
(1)从namenode的dfs.hosts文件中删除退役节点jh03
jh
jh02
jh04
(2)刷新namenode,刷新resourcemanager
[root@jh hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@jh hadoop-2.7.2]$ yarn rmadmin -refreshNodes
17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at jh02/192.168.1.103:8033
7)从namenode的slave文件中删除退役节点jh03
jh
jh02
jh04
8)如果数据不均衡,可以用命令实现集群的再平衡
[root@jh hadoop-2.7.2]$ sbin/start-balancer.sh
starting balancer, logging to /opt/hadoop-2.7.2/logs/hadoop-root-balancer-jh.out
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
6.7 Datanode多目录配置
1)datanode也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本。
2)具体配置如下:
hdfs-site.xml
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
</property>
七 HDFS其他功能
7.1 集群间数据拷贝
1)scp实现两个远程主机之间的文件复制
scp –r hello.txt root@jh02:/user/root/hello.txt // 推 push
scp –r root@jh02:/user/root/hello.txt hello.txt // 拉 pull
scp –r root@jh02:/user/root/hello.txt root@hadoop104:/user/root //是通过本地主机中转实现两个远程主机的文件复制;如果在两个远程主机之间ssh没有配置的情况下可以使用该方式。
1.3.4. 2)采用discp命令实现两个hadoop集群之间的递归数据复制
[root@jh hadoop-2.7.2]$ bin/hadoop distcp hdfs://haoop102:9000/user/root/hello.txt hdfs://jh02:9000/user/root/hello.txt
7.2 Hadoop存档
1)理论概述
每个文件均按块存储,每个块的元数据存储在namenode的内存中,因此hadoop存储小文件会非常低效。因为大量的小文件会耗尽namenode中的大部分内存。但注意,存储小文件所需要的磁盘容量和存储这些文件原始内容所需要的磁盘空间相比也不会增多。例如,一个1MB的文件以大小为128MB的块存储,使用的是1MB的磁盘空间,而不是128MB。
Hadoop存档文件或HAR文件,是一个更高效的文件存档工具,它将文件存入HDFS块,在减少namenode内存使用的同时,允许对文件进行透明的访问。具体说来,Hadoop存档文件可以用作MapReduce的输入。
2)案例实操
(1)需要启动yarn进程
[root@jh hadoop-2.7.2]$ start-yarn.sh
(2)归档文件
归档成一个叫做xxx.har的文件夹,该文件夹下有相应的数据文件。Xx.har目录是一个整体,该目录看成是一个归档文件即可。
[root@jh hadoop-2.7.2]$ bin/hadoop archive -archiveName myhar.har -p /user/root /user/my
(3)查看归档
[root@jh hadoop-2.7.2]$ hadoop fs -lsr /user/my/myhar.har
[root@jh hadoop-2.7.2]$ hadoop fs -lsr har:///myhar.har
(4)解归档
[root@jh hadoop-2.7.2]$ hadoop fs -cp har:/// user/my/myhar.har /* /user/root
7.3 快照管理
快照相当于对目录做一个备份。并不会立即复制所有文件,而是指向同一个文件。当写入发生时,才会产生新文件。
1)基本语法
(1)hdfs dfsadmin -allowSnapshot 路径 (功能描述:开启指定目录的快照功能)
(2)hdfs dfsadmin -disallowSnapshot 路径 (功能描述:禁用指定目录的快照功能,默认是禁用)
(3)hdfs dfs -createSnapshot 路径 (功能描述:对目录创建快照)
(4)hdfs dfs -createSnapshot 路径 名称 (功能描述:指定名称创建快照)
(5)hdfs dfs -renameSnapshot 路径 旧名称 新名称 (功能描述:重命名快照)
(6)hdfs lsSnapshottableDir (功能描述:列出当前用户所有可快照目录)
(7)hdfs snapshotDiff 路径1 路径2 (功能描述:比较两个快照目录的不同之处)
(8)hdfs dfs -deleteSnapshot <path> <snapshotName> (功能描述:删除快照)
2)案例实操
(1)开启/禁用指定目录的快照功能
[root@jh hadoop-2.7.2]$ hdfs dfsadmin -allowSnapshot /user/root/data
[root@jh hadoop-2.7.2]$ hdfs dfsadmin -disallowSnapshot /user/root/data
(2)对目录创建快照
[root@jh hadoop-2.7.2]$ hdfs dfs -createSnapshot /user/root/data
通过web访问hdfs://jh:9000/user/root/data/.snapshot/s…..// 快照和源文件使用相同数据块
[root@jh hadoop-2.7.2]$ hdfs dfs -lsr /user/root/data/.snapshot/
(3)指定名称创建快照
[root@jh hadoop-2.7.2]$ hdfs dfs -createSnapshot /user/root/data miao170508
(4)重命名快照
[root@jh hadoop-2.7.2]$ hdfs dfs -renameSnapshot /user/root/data/ miao170508 root170508
(5)列出当前用户所有可快照目录
[root@jh hadoop-2.7.2]$ hdfs lsSnapshottableDir
(6)比较两个快照目录的不同之处
[root@jh hadoop-2.7.2]$ hdfs snapshotDiff /user/root/data/ . .snapshot/root170508
(7)恢复快照
[root@jh hadoop-2.7.2]$ hdfs dfs -cp /user/root/input/.snapshot/s20170708-134303.027 /user
7.4 回收站
1)默认回收站
默认值fs.trash.interval=0,0表示禁用回收站,可以设置删除文件的存活时间。
默认值fs.trash.checkpoint.interval=0,检查回收站的间隔时间。
要求fs.trash.checkpoint.interval<=fs.trash.interval。
2)启用回收站
修改core-site.xml,配置垃圾回收时间为1分钟。
<property> <name>fs.trash.interval</name> <value>1</value> </property> |
3)查看回收站
回收站在集群中的;路径:/user/root/.Trash/….
4)修改访问垃圾回收站用户名称
进入垃圾回收站用户名称,默认是dr.who,修改为root用户
[core-site.xml]
<property> <name>hadoop.http.staticuser.user</name> <value>root</value> </property> |
5)通过程序删除的文件不会经过回收站,需要调用moveToTrash()才进入回收站
Trash trash = New Trash(conf);
trash.moveToTrash(path);
6)恢复回收站数据
[root@jh02 hadoop-2.7.2]$ hadoop fs -mv /user/root/.Trash/Current/user/root/input /user/root/input
7)清空回收站
[root@jh02 hadoop-2.7.2]$ hdfs dfs -expunge