为什么要用HDFS
- 一台服务器存不下数据,需要多台服务器。多台服务器上的数据需要一个系统来组织和管理。
tip:HDFS、NTFS是不同的文件管理系统
HDFS的定义
- HDFS是一个分布式的文件系统,通过目录树来定位文件
HDS的使用场景
- 一次写入,多次读出,不支持文件的修改,并且数据读取慢
- 适合做数据分析的存储
优点
-
高容错
自动保存多个副本,当节点数足够的时候,会自动保持副本份数。如10个节点,3个副本,一台挂掉,那么这台节点上的数据会被转存到其他节点,保证副本份数。
-
适合做大数据,大文件规模,GB,TB,PB
缺点
- 不适合低延时的数据访问,毫秒级的响应不适合
- 无法高效的对大量小文件存储
- 每一个小文件,在NameNode中会消耗150字节的内存,小文件多,会占用大量NameNode 的内存存储
- 小文件的存储寻址的时间超过了读取时间,违背设计原则
- 不支持并发写入数据,即两个客户端无法同时写入相同的文件,不同文件可以并发写入
- 不支持随机写操作,即无法修改文件
组成架构
NameNode
- 管理HDFS名称空间
- 管理数据块的映射信息
- 处理客户端的读写请求
DataNode
- 存储实际的数据块
- 执行数据块的读写请求
客户端
- 文件切块:上传文件的时候,客户端将文件切分成Block,然后上传
- 与NameNode交互,获取文件位置信息
- 与DataNode交互,读取或写入数据
- 提供命令管理、访问HDFS
2ndNameNode
- 辅助NameNode工作,合并fsimage和edits
- 紧急情况下,可辅助恢复NameNode
块大小设置
设置方法
- 默认大小Hadoop 2.x是128MB(),1.x是64MB。
- hdfs-site中,dfs.blocksize设置(字节)
设置原则
- 块的寻址约10ms,1%,1s,磁盘速率100MB/s,所以一个块大约128MB,
- 当磁盘速率较高的时候,可以设置为256MB。
- HDFS块大小取决于磁盘传输速率。
为什么块的大小不能太大或太小?
- 太小:块数太多,增加块的寻址时间同时增加内存消耗
- 太大:并行度减小
HDFS的shell操作
hadoop fs和hdfs dfs的关系,后者是前者的实现类。
# 查看HDFS节点状态
hdfs dfsadmin -report
# 帮助命令
hadoop fs -help rm
# 地柜查看目录
hadoop fs -ls -R /
# 创建多及目录
hadoop fs -mkdir -p /sanguo/shuguo
# 剪切本地文件到HDFS,本地文件会消失
hadoop fs -moveFromLocal 本地文件 目标地址
# 复制本地文件到HDFS
hadoop fs -copyFromLocal 本地文件 目标地址
# 复制HDFS文件到本地
hadoop fs -copyToLocal 目标文件 本地地址
# 追加
hadoop fs -appendToFile 源文件 目标文件
# 合并一个目录下的多个文件,下载到本地,如一个目录下的多个log文件合并,
hadoop fs -getmerge /user/*.log ./my_log.txt
# 查看文件尾部,查看日志尾部,一般最新的日志都在最后面
hadoop fs -tail /user/2019.log
# 统计目录大小
hadoop fs -du -h -s 目标目录
# 设置文件的副本数量。副本数量>节点数,依然备份节点数个副本
hadoop fs -setrep 2 目标文件
HDFS的客户端操作
客户端配置
-
windows下,解压Hadoop压缩包,配置环境变量(这一步非必须)
-
Java工程中添加maven依赖
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.7</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.7.7</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.7</version> </dependency>
-
配置日志,log4j.properties
客户端操作的问题
问题1:为什么需要解压Hadoop压缩包
不一定需要,只要在Java工程配置好apache.hadoop相关依赖即可
问题2:提示用户名没有权限
-
出现问题:Permission denied: user=tensory, access=READ_EXECUTE
-
解决方法
-
方法一:run的时候,run configurations,设置用户名为集群的用户名
Run–Edit Configure—在VM options中配置:-DHADOOP_USER_NAME=hadoop
-
方法二:创建FileSystem对象的时候,传入HDFS的用户名
-
客户端读取配置的优先级
客户端代码中conf.set > resources/hdfs-site.xml > 集群上的hdfs-site.xml > 默认配置
测试一下上传文件的时候的副本份数
# 三个 优先级逐渐降低
conf.set("dfs.replication", "1")
resources/hdfs-site.xml设置副本份数
集群的hdfs-site.xml中的副本份数
客户端操作
文件下载
设置为false,即不使用本地的文件系统,则存在crc校验,会生成 .zhangsan.txt.crc文件
问题记录
-
出现问题
java.io.IOException: (null) entry in command string: null chmod 0644 E:\IdeaProjects\Hadoop-demo\src\main\resources\zhangsan-1.txt中
-
解决办法:下载对应版本的hadoop.dll放在windows\system32下面
HDFS的IO流操作
不使用API进行文件的读写,如果要修改Hadoop源码,在定制化严重的公司,需要自定义、封装一些框架,就需要IO流读写。
文件定位读取——如何读取指定block
文件分块,如何获取某一块,例如只需要读日志文件的最后一块?
- 获取输入流
- 设置指定读取的起点,根据块的大小,确定定位点
- 获取输出流
- 流的对拷(从定位点读到结尾)
- 关闭相关资源
HDFS的数据流操作
HDFS写数据流程
-
step1. 客户端向NameNode申请写数据/user/hadoop/ss.avi
-
step2. NameNode判断路径、文件是否存在。相应可以写数据
-
step3. 客户端向NameNode申请上传第一个Block(128MB),请返回DataNode
-
step4. NameNode根据节点距离、负载返回3个DataNode,dn1, dn2, dn3
-
step5. 创建FSDataOutputStream对象,请求数据通道,dn1–dn2–dn3–dn2–dn1
-
step6. 以packet为单位以数据流的方式,传输数据到dn1的内存队列中,dn1的内存数据序列化到磁盘,并传给dn2,dn2将数据存在内存队列,并传给dn3,dn2的内存数据序列化到本地。dn3的内存数据本地化,清空内存,告诉dn2,dn2清空内存告诉dn1,dn1清空内存
如何计算节点的距离
两个节点的最短路径为,两个节点到达最近公共祖先的距离之和。
不同的集群共有一个父节点,一个集群下的不同机架共有一个父节点。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2OP84mD-1595422402732)(C:\Users\tensory\AppData\Roaming\Typora\typora-user-images\image-20200517173249877.png)]
机架感知
默认3个副本,存在哪里呢?
-
第一个:客户端在集群外,随机选一个机架,随机选一个。在集群内,则本地节点。
-
第二个:和第一个副本相同机架的不同节点。
-
第三个:其他机架的随机节点。
读数据流程
- step1. 向NameNode请求读数据/user/hadoop/ss.avi
- step2. 返回目标数据的元数据信息
- step3. 向DataNode请求读数据,数据存在哪个节点?
- step4. 根据距离最近,以block为单位读数据。
- step5. 等所有的block读取完毕,进行拼接。
NameNode和SecondaryNameNode
NN和2NN工作机制
-
NameNode的元数据存在哪里?
元数据在内存中,但元数据在磁盘有备份,即fsimage。
-
磁盘的数据何时更新?
当内存数据更新或添加元数据,将修改日志追加到edits中,只进行追加操作效率高。fsimage+edit = 内存中的元数据。
-
长时间向Edits添加日志,越来越大,而且集群重启需要从fsimage+edit恢复文件系统太慢,怎么办?
2NN将fsimage与edits合并。
NameNode和2ndNameNode的协同工作
- NameNode启动,加载fsimage和edits存到内存中,每个block的元数据占150Byte。
- 客户端请求对文件系统进行增删改等更新操作
- NameNode将操作记录到edits中,再更新内存数据。(为什么?)
- 2nnNameNode向NameNode请求是否需要checkpoint,checkpoint有两个条件
- 定时时间到了(1h)
- edits满了(1million条数据)
- 请求执行checkpoint
- 滚动正在写的edits_inprogress为edtis_001,
- 创建新的edits_inprogress_002,后续写入这个文件
- 将NameNode的fsimage和edits_001,加载到内存中合并,生成新的fsimage.checkpoint,传输给NameNode
- NameNode将fsimage.checkpoint更名为fsimage,此时fsimage和edits_inprogress_002共同构成内存最新的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPJTxZNb-1595422402735)(C:\Users\tensory\AppData\Roaming\Typora\typora-user-images\image-20200517180150665.png)]
fsimage和edits
各自存在哪里?
hdfs oiv / oev 可以查看fsimage和edits序列化文件
# 离线的fsimage文件转化为可读模式
hdfs oiv -p XML -i src -o dst
# 离线的fsimage文件转化为可读模式
hdfs oev -p XML -i src -o dst
NameNode
如何确定下次启动合并哪些edits文件?
seen_txtid
CheckPoint
2ndNameNode何时合并edits和fsimage
hdfs-site.xml配置
checkpoint.period,默认1h,
checkpoint.txns,100万条日志
check_period,1分钟检查一次日志的条数
NameNode的故障处理
NameNode挂了,数据如何恢复:
方法一:
- 将2ndNameNode的namesecondary目录下的所有数据拷贝到NameNode中dfs中,恢复部分数据,差了edit_inprogress这个部分、
- 启动NameNode
方式二:使用 -importCheckpoint启动NameNode,等待
-
配置hdfs-site.xml中的检查点,时间由3600s设置为短一点的时间,如120s
-
需要将2ndNameNode的namesecondary目录下的数据拷贝到NameNode目录的同级目录,并删除in_use.lock文件
-
导入检查点,NameNode启动
hdfs namenode -importCheckpoint
-
等待120s,NameNode挂掉
-
启动NameNode
方法二更规范,检查的数据更多,但没有大的区别
集群的安全模式
NameNode启动
启动,将fsimage加载内存,执行edit中的操作,更新内存,建立fs的元数据镜像,创新的fsimage和一个空的edit。NameNode监听DataNode的请求,等待想他传递块的信息。这个过程,NameNode运行在安全模式,即NameNode的文件系统对客户端只读。
DataNode启动
启动,数据块以块列表的形式存储在DN中,安全模式下,各个DN向NN发送最新的块信息,NN了解足够多的块信息的时候,即可高效运行。
刚上电,DN要讲块信息山川给NN,这个过程处于安全模式。
安全模式退出判断
最小副本条件:NN会在30秒之后,推出安全模式。集群的99.9%的块满足至少1个副本,dfs.replication.min=1,则推出安全模式。
启动一个刚格式化的NN,由于系统没有块,所以不存在安全模式。
安全模式操作
# 查看安全模式状态,也可以在WebUI的Overview也可以看到
hdfs dfsadmin -safemod get
# 启动安全模式,HDFS只读
hdfs dfsadmin -safemod enter
# 离开安全模式
hdfs dfsadmin -safemod leave
# 等待安全模式离开
hdfs dfsadmin -safemod wait
案例
# 一个终端
# step1
hdfs dfsadmin -safemod enter
# step3
hdfs dfsadmin -safemod leave
# 另一个终端
# step2
#!/bin/bash
hdfs dfsadmin -safemod wait
hdfs dfs -put ./my.txt /
NameNode添加多个目录
多个目录,存储的是完全相同的内容,但仍然是一个进程,只是一个数据的多副本数据可靠性。
DataNode
工作机制
- DN启动,向NN注册,发送块列表。数据:数据、长度、校验和、时间戳
- NN将信息写入内存,返回注册成功
- 以后DataNode每小时,上报所有块信息
- DataNode向NameNode发送心跳,心跳每3秒一次,NameNode返回的心跳带有给DataNode的命令
- 超过10分钟,没有收到DN的心跳,则NN认为该DN节点不可用,以后不会在该节点存储。
数据完整性
什么是奇偶校验?
奇偶校验只能校验单点故障,多点故障无法解决。
CRC
16、32、64、128位的CRC
对原始数据尽心CRC计算,与校验位尽心对比。
掉线时限设置
在hdfs-site.xml
心跳超过10分钟+30秒断了,NN认为DN不可用
有一个公式:2*5 分钟 + 30s
服役新数据节点
slaves文件只是为了群起集群,如果是单个节点启动,无需配置slaves。
所以新节点,不需要配置slaves,但是为了今后群起,可以配置。如果只是临时增加节点,后面要删除,不用加入slaves。只要在core-site.xml中配置了namenode,就能识别这个节点为集群的一部分。
添加白名单
服役新节点,没有任何限制,只需要知道NameNode的主机IP,如何解决这个问题?——添加白名单。
只有在白名单的节点,才可以访问NN。
-
在etc/hadoop/下创建dfs.hosts文件(随意命名),写入白名单节点
-
在hdfs-site.xml中引入这个文件,即dfs.hosts这个条目
-
分发配置文件
-
刷新NameNode,重新读取配置文件
hdfs dfsadmin -refreshNodes
yarn rmadmin -freshNodes
一般在刚搭建集群的时候,配置。如果想踢掉某个节点,采用白名单,数据依然标记在踢掉的节点。即Avalability依然标记被剔除的节点。
数据均衡
退役一个节点之后,负载可能不均衡
start-balancer.sh
黑名单
在黑名单的主机,被强制退出。
白名单和黑名单不能有交集。
-
创建dfs.hosts.exclude文件中添加想退役的节点。
-
在hdfs-site.xml中配置dfs.hosts.exclude
-
刷新hdfs和yarn。等待数据迁移完成。
-
在退役节点,关闭DN和NM进程。
这种方式,退役,保证退役节点的数据拷贝到其他节点,保证数据副本数。
重新启动集群的时候,WebUI上对应的几点会消失。
DataNode多目录的配置
DN的多目录的数据不是副本
应该在集群初始时刻配置
- 如果不是初始时刻,还原集群到初始时刻
- 在hdfs-site.xml配置多个目录
- 格式化NN
- 群起集群
HDFS 2.x新特性
集群间的数据拷贝
scp拷贝数据的三种方法,推、拉、第三方服务器方式
场景:测试集群的数据拷贝到生产集群。
hadoop distcp hdfs://源集群的数据 hdfs://目的集群路径
小文件存档
HDFS存储小文件的弊端
NN的内存空间中,任何一个块,无论块的大小,都会占用150 Bytes。
办法之一
HDFS存档文件或HAR文件,是更高效的的存档工具,HDFS存档文件对内还是一个一个独立的文件,对NN来说是一个大文件。即多个小文件,对NN来说是一个文件,*.HAR文件。客户端访问的时候,依然是一个一个小文件。
操作
-
确保dfs和yarn
-
归档为.har文件(这是一个MR任务)
hadoop archive -archiveName 归档后的文件名.har -p 源数据 目的路径
-
查看原文件,如果不带har://,则查看归档后的文件
hadoop fs -ls -R har:///user/hadoop/归档后的文件名.rar
用户访问的时候,使用 har:///…这种路径使用,依然是一个个单独的文件,而对于HDFS是一个har文件。
回收站案例
默认关闭,因为很少删除数据,HDFS的最大特点是可以存储海量的数据,很少存储数据。
core-site.xml
fs.transh.interval=0,设置文件存货时间,分钟。
fs.trash.checkpoint.interval,设置检查回收站的数据是否到存活时间,为0表示与存活时间相等
权限问题,权限用户默认为dr.who,在core-site.xml中配置用户,http.staticuser.user
查看
/user/hadoop/.Trash
恢复回收站数据,使用hadoop fs -mv 命令,去回收站直接移动数据
清空
其实不是清空,而是重新命名了一下
快照管理
Linux的快照?
什么是SequenceFile?
SequenceFile是一种通过二进制序列化之后的key/value的字节流组成的文本存储文件。
key为文件位置和文件名,value为文件内容
map输出的临时文件就是以SequenceFile文件存储。
HDFS HA高可用
HA是提高NamNode的可靠性,依赖ZK