HDFS
HDFS优缺点
* 优点
1)高容错性
数据自动保存多个副本。它通过增加副本的形式,提高容错性。
2)适合处理大数据
数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;
某一个副本丢失以后,它可以自动恢复。
文件规模:能够处理百万规模以上的文件数量,数量相当之大。
3)可构建在廉价机器上,通过多副本机制,提高可靠性。
*缺点
1)不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
2)无法高效的对大量小文件进行存储。
存储大量小文件的话,它会占用NameNode大量的内存来存储文件 目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
3)不支持并发写入、文件随机修改。
一个文件只能有一个写,不允许多个线程同时写;
仅支持数据append(追加),不支持文件的随机修改
HDFS组成架构
* 组成
1)NameNode(nn):就是Master,它 是一个主管、管理者。
(1)管理HDFS的名称空间;
(2)配置副本策略;
(3)管理数据块(Block)映射信息;
(4)处理客户端读写请求。
2)DataNode:就是Slave。NameNode 下达命令,DataNode执行实际的操作。
(1)存储实际的数据块;
(2)执行数据块的读/写操作。
3)Client:就是客户端。
(1)文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
(2)与NameNode交互,获取文件的位置信息;
(3)与DataNode交互,读取或者写入数据;
(4)Client提供一些命令来管理HDFS,比如NameNode格式化;
(5)Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;
4)Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不 能马上替换NameNode并提供服务。
(1)辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode ;
(2)在紧急情况下,可辅助恢复NameNode。
* 文件块
HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数 ( dfs.blocksize)来规定,默认大小在Hadoop2.x版本中是128M,老版本中是64M
寻址时间为传输时间的1% 时,则为最佳状态
思考:为什么块的大小不能设置太小,也不能设置太大?
(1)HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;
(2)如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开 始位置所需的时间。导致程序在处理 这块数据时,会非常慢。
总结:HDFS块的大小设置主要取决于磁盘传输速率。
HDFS 的 Shell 操作
1.基本语法 bin/hadoop fs 具体命令 OR bin/hdfs dfs 具体命令
dfs 和 fs 是执行的同一个类 org.apache.hadoop.fs.FsShell。
2.常用命令实操
(1)-help:输出这个命令参数
(2)-ls: 显示目录信息
(3)-mkdir:在 HDFS 上创建目录
(4)-moveFromLocal:从本地剪切粘贴到 HDFS
(5)-appendToFile:追加一个文件到已经存在的文件末尾
(6)-cat:显示文件内容
(7)-chgrp 、-chmod、-chown:Linux 文件系统中的用法一样,修改文件所属权限
(8)-copyFromLocal:从本地文件系统中拷贝文件到 HDFS 路径去
(9)-copyToLocal:从 HDFS 拷贝到本地
(10)-cp :从 HDFS 的一个路径拷贝到 HDFS 的另一个路径
(11)-mv:在 HDFS 目录中移动文件
(12)-get:等同于 copyToLocal,就是从 HDFS 下载文件到本地
(13)-getmerge:合并下载多个文件,比如 HDFS 的目录 /user/ityouxin/test 下有多个文
件:log.1, log.2,log.3,...
(14)-put:等同于 copyFromLocal
(15)-tail:显示一个文件的末尾
(16)-rm:删除文件或文件夹
(17)-rmdir:删除空目录
(18)-du 统计文件夹的大小信息
(19)-setrep:设置 HDFS 中文件的副本数量
这里设置的副本数只是记录在 NameNode 的元数据中,是否真的会有这么多副本,还得
看 DataNode 的数量。因为目前只有 3 台设备,最多也就 3 个副本,只有节点数的增加到 10
台时,副本数才能达到 10
NN和2NN的工作机制
* 机制
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。
* Fsimage和Edits概念
NameNode被格式化之后,将在/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current目录中产生如下文件
(1)Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目 录和文件inode的序列化信息。
fsimage_0000000000000000000 fsimage_0000000000000000000.md5 seen_txid VERSION
(2)Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先 会被记录到Edits文件中。
(3)seen_txid文件保存的是一个数字,就是最后一个edits_的数字
(4)每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存 中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
* oiv 和oev
1)hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
2)hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
* CheckPoint 时间设置
(1)通常情况下,SecondaryNameNode 每隔一小时执行一次。
(2)一分钟检查一次操作次数,3 当操作次数达到 1 百万时,SecondaryNameNode 执
行一次。
* NameNode 故障处理
方法一:将 SecondaryNameNode 中数据拷贝到 NameNode 存储数据的目录;
1. kill -9 NameNode 进程
2. 删除 NameNode 存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
3. 拷贝 SecondaryNameNode 中数据到原 NameNode 存储数据目录
4. 重新启动 NameNode
方法二:使用-importCheckpoint 选项启动 NameNode 守 护 进 程 , 从 而 将
SecondaryNameNode 中数据拷贝到 NameNode 目录中。
1. 修改 hdfs-site.xml 中的
<property>
<name>dfs.namenode.checkpoint.period</name> <value>120</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value>
</property>
2. kill -9 NameNode 进程
3. 删除NameNode存储的数据(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)
4. 如果 SecondaryNameNode 不和 NameNode 在一个主机节点上,需要将 SecondaryNameNode 存储数据的目录拷贝到 NameNode 存储数据的平级目录,并删 除 in_use.lock 文件
5. 导入检查点数据(等待一会 ctrl+c 结束掉)
6. 启动 NameNode
* 集群安全模式
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)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态)
(2)bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态)
(3)bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态)
(4)bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)
DataNode 工作机制
* 安全模式
1)一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本
身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
2)DataNode 启动后向 NameNode 注册,通过后,周期性(1 小时)的向 NameNode 上
报所有的块信息。
3)心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数
据到另一台机器,或删除某个数据块。如果超过 10 分钟没有收到某个 DataNode 的心跳,则
认为该节点不可用。
4)集群运行中可以安全加入和退出一些机器。
* 数据完整性
DataNode 节点保证数据完整性的方法。
1)当 DataNode 读取 Block 的时候,它会计算 CheckSum。
2)如果计算后的 CheckSum,与 Block 创建时值不一样,说明 Block 已经损坏。
3)Client 读取其他 DataNode 上的 Block。
4)DataNode 在其文件创建后周期验证 CheckSum
* 掉线时限参数设置
1.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>
2.则超时时长的计算公式为:
TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。 默认的dfs.namenode.heartbeat.recheck-interval 大小为5分钟,dfs.heartbeat.interval默认为3秒
* 服役新数据节点
修改好新节点的配置文件,直接启动datanode即可
* 退役旧数据节点
1. 添加白名单
添加到白名单的主机节点,都允许访问 NameNode,不在白名单的主机节点,都会被退出。
(1)在 NameNode 的/opt/module/hadoop-2.7.2/etc/hadoop 目录下创建 dfs.hosts 文件
添加白名单的主机名
(2)在 NameNode 的 hdfs-site.xml 配置文件中增加 dfs.hosts 属性
(3)配置文件分发 xsync
(4)刷新 NameNode
hdfs dfsadmin -refreshNodes
(5)更新 ResourceManager 节点
yarn rmadmin -refreshNodes
如果数据不均衡,可以用命令实现集群的再平衡 ./start-balancer.sh
2. 黑名单退役
在黑名单上面的主机都会被强制退出。
1. 在 NameNode 的 /opt/module/hadoop-2.7.2/etc/hadoop 目录下 创 建 dfs.hosts.exclude 文件
2.在 NameNode 的 hdfs-site.xml 配置文件中增加 dfs.hosts.exclude 属性
3.刷新 NameNode、刷新 ResourceManager
4. 检查 Web 浏览器,退役节点的状态为 decommission in progress(退役中),
5. 等待退役节点状态为 decommissioned(所有块已经复制完成),停止该节点及 节点资源管理器。注意:如果副本数是 3,服役的节点小于等于 3,是不能退役 成功的,需要修改副本数后才能退役
6. 如果数据不均衡,可以用命令实现集群的再平衡 sbin/start-balancer.sh
* Datanode 多目录配置
DataNode 也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本
多目录需要配置hdfs-site.xml
<property>
<name>dfs.datanode.data.dir</name> <value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tm p.dir}/dfs/data2</value> </property>
HDFS 2.X 新特性
1 集群间数据拷贝
1.scp 实现两个远程主机之间的文件复制 scp -r hello.txt
本地主机中转实现两个远程主机的文件复制;如果在两个远程主机之间 ssh 没有配置的情况下可以使用该方式。
2.采用 distcp 命令实现两个 Hadoop 集群之间的递归数据复制 bin/hadoop distcp src dist
2.小文件存档
(1)需要启动 YARN 进程
(2)归档文件 bin/hadoop archive archiveName input.har –p /user/ityouxin/input
(3)查看归档 hadoop fs -lsr /user/ityouxin/output/input.har
(4)解归档文件 hadoop fs -cp har:/// user/ityouxin/output/input.har/* /user/ityouxin
HDFS HA 高可用
* 配置zookerper集群
1. 集群规划 在 hadoop102、hadoop103 和 hadoop104 三个节点上部署 Zookeeper。
2. 解压安装zookeeper的安装包,并在该目录下创建zkData目录
3.重命名conf的zoo_sample.cfg 为 zoo.cfg 并添加配置
dataDir=/opt/module/zookeeper-3.4.10/zkData
#######################cluster########################## server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
配置参数解读
Server.A=B:C:D。
A 是一个数字,表示这个是第几号服务器; 来源于zkData中的myid里的值
B 是这个服务器的 IP 地址;
C 是这个服务器与集群中的 Leader 服务器交换信息的端口;
D 是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的
Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
4./zkData 目录下创建一个 myid 的文件 ,并添加server对应的编号
5.拷贝配置好的 zookeeper 到其他机器上 并分别修改 myid 文件中内容为 3、4
6.分别启动 zookeeper bin/zkServer.sh start
7.查看状态 bin/zkServer.sh status
* 配置 HDFS-HA 集群
1. 配置 hadoop-env.sh
2. 配置 core-site.xml
<configuration>
<!-- 把两个 NameNode 的地址组装成一个集群 mycluster -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- 指定 hadoop 运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/ha/hadoop-2.7.2/data/tmp</value>
</property>
</configuration>
3.配置 hdfs-site.xml
<configuration>
<!-- 完全分布式集群名称 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- 集群中 NameNode 节点都有哪些 -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!-- nn1 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hadoop102:9000</value>
</property>
<!-- nn2 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hadoop103:9000</value>
</property>
<!-- nn1 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hadoop102:50070</value>
</property>
<!-- nn2 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hadoop103:50070</value>
</property>
<!-- 指定 NameNode 元数据在 JournalNode 上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</value>
</property>
<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<!-- 使用隔离机制时需要 ssh 无秘钥登录-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/ityouxin/.ssh/id_rsa</value>
</property>
<!-- 声明 journalnode 服务器存储目录-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/ha/hadoop-2.7.2/data/jn</value>
</property>
<!-- 关闭权限检查-->
<property>
<name>dfs.permissions.enable</name>
<value>false</value>
</property>
<!-- 访问代理类:client,mycluster,active 配置失败自动切换实现方 式-->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
</configuration>
* 启动 HDFS-HA 集群
1. 在各个 JournalNode 节点上,输入以下命令启动 journalnode 服务 sbin/hadoop-daemon.sh start journalnode
2. 在[nn1]上,对其进行格式化,并启动 bin/hdfs namenode -format
sbin/hadoop-daemon.sh start namenode
3. 在[nn2]上,同步 nn1 的元数据信息 bin/hdfs namenode -bootstrapStandby
4. 启动[nn2] sbin/hadoop-daemon.sh start namenode
5.在[nn1]上,启动所有 datanode sbin/hadoop-daemons.sh start datanode
6.将[nn1]切换为 Active bin/hdfs haadmin -transitionToActive nn1
7.查看是否 Active bin/hdfs haadmin -getServiceState nn1
8.手动切换[nn2] 为 Active bin/hdfs haadmin -failover --forcefence --forceactive nn1 nn2
* 配置 HDFS-HA 自动故障转移
1.配置
1)在 hdfs-site.xml 中增加
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
2)在 core-site.xml 文件中增加
<property>
<name>ha.zookeeper.quorum</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
2.启动
(1)关闭所有 HDFS 服务:sbin/stop-dfs.sh
(2)启动 Zookeeper 集群: bin/zkServer.sh start
(3)初始化 HA 在 Zookeeper 中状态: bin/hdfs zkfc -formatZK
(4)启动 HDFS 服务: sbin/start-dfs.sh
YARN-HA 配置
* HA配置
1.配置
(1)yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--启用 resourcemanager ha-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!--声明两台 resourcemanager 的地址-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>cluster-yarn1</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop102</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop103</value>
</property>
<!--指定 zookeeper 集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
<!--启用自动恢复-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--指定 resourcemanager 的状态信息存储在 zookeeper 集群-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
</configuration>
2.启动 YARN
(1)在 hadoop102 中执行: sbin/start-yarn.sh
(2)在 hadoop103 中执行: sbin/yarn-daemon.sh start resourcemanager
(3)查看服务状态, bin/yarn rmadmin -getServiceState rm1
* HDFS Federation 架构设计
NameNode 架构的局限性
1.局限性
(1)Namespace(命名空间)的限制
由于 NameNode 在内存中存储所有的元数据(metadata),因此单个 NameNode 所能存
储的对象(文件+块)数目受到 NameNode 所在 JVM 的 heap size 的限制。50G 的 heap 能够
存储 20 亿(200million)个对象,这 20 亿个对象支持 4000 个 DataNode,12PB 的存储(假
设文件平均大小为 40MB)。随着数据的飞速增长,存储的需求也随之增长。单个 DataNode
从 4T 增长到 36T,集群的尺寸增长到 8000 个 DataNode。存储的需求从 12PB 增长到大于100PB。
(2)隔离问题
由于 HDFS 仅有一个 NameNode,无法隔离各个程序,因此 HDFS 上的一个实验程序就
很有可能影响整个 HDFS 上运行的程序。
(3)性能的瓶颈
2.HDFS Federation 应用思考 不同应用可以使用不同 NameNode 进行数据管理
Hadoop 生态系统中,不同的框架使用不同的 NameNode 进行管理 NameSpace。 (隔离性)