HDFS副本放置策略
客户端:执行put命令所在的机器称为客户端
- 第一副本
假如上传节点为dn节点,优先放置在本节点;否则会随机找一个磁盘不太慢、CPU不太繁忙的节点 - 第二副本
放置于第一副本不同的机架上 - 第三副本
放置于第二副本的相同机架的不同节点上
CDH机架有一个默认的机架,虚拟的概念,CDH一般不调整这种默认机架
HDFS的读写流程
写流程
- 1、client调用FileSystem.create(filePath)方法
client调用FileSystem.create(filePath)方法跟NN进行rpc通信,nn会检查文件是否存在以及是否有权限进行创建,如果检查失败,返回错误信息,如果检查通过,就创建一个新文件,不会关联任何block块,然后返回一个FSDataOutputStream对象 - 2、client端调用FSDataOutputStream对象的write()方法
将第一块的第一个副本写到第一个DN;第一个写完,
就传输第二个副本到第二个DN上;第二个写完,
就传输第三个副本到DN上;第三个副本写完,
就返回一个ack packet确认包给第二个DN;
第二个DN接收到第三个的ack packet加上自身的ok后,就返回一个ack packet确认包给第一个DN,
第一个DN接收到第二个DN的ack packet 并加上自身的ok,就返回ack paket确认包给FSDataOutputStream对象,
标志着第一块 3副本已经写入完毕,然后余下的block依次这样写 - 3、当向文件写入完数据后
client调用FSDataOutputStream对象的close()方法,关闭输出流 - 4、最后调用FileSystem.complete()方法告诉NN数据写入成功
读流程
- 1、client调用FileSystem.open(filePath)方法,
与NN进行rpc通信,返回该文件的部分或者全部block列表,也就是FSDataInputStream对象 - 2、client调用FSDataInputStream.open()方法,
与第一块最近的DN进行read,读取完成后,会check,假如ok,就关闭与DN的通信;假如失败,会记录失败块+DN信息,下次将不会访问该block块,然后会去该块的第二个DN地址进行读取,check完成后,关闭通信;
假如block块列表读取完成后,文件还未结束,就再次调用FileSystem从NN获取该文件的下一批次的block块列表,然后继续跟NN进行read - 3、client调用FSDataInputStream的close()方法,关闭输入流
配置pid文件的生成路径
启动hdfs或yarn,如果不在配置文件配置的话,生成的pid文件会在/tmp目录下,如果linux一个月自动清理pid文件,pid文件会造成集群的启动和停止(jps文件不会影响集群),所以我们需要在hdfs和yarn的配置文件中配置让,pid文件不要生成在/tmp目录下
hdfs的配置
配置hadoop-env.sh
export HADOOP_PID_DIR=/home/hadoop/tmp
yarn配置
配置yarn-env.sh
export YARN_PID_DIR=/home/hadoop/tmp
重新启动,查看pid文件路径
[hadoop@JD tmp]$ pwd
/home/hadoop/tmp
生成在配置的路径下
[hadoop@JD tmp]$ ll
total 20
-rw-rw-r-- 1 hadoop hadoop 5 Dec 1 18:28 hadoop-hadoop-datanode.pid
-rw-rw-r-- 1 hadoop hadoop 5 Dec 1 18:28 hadoop-hadoop-namenode.pid
-rw-rw-r-- 1 hadoop hadoop 5 Dec 1 18:29 hadoop-hadoop-secondarynamenode.pid
-rw-rw-r-- 1 hadoop hadoop 5 Dec 1 18:29 yarn-hadoop-nodemanager.pid
-rw-rw-r-- 1 hadoop hadoop 5 Dec 1 18:29 yarn-hadoop-resourcemanager.pid
HDFS DFS常用命令
hadoop fs 跟 hdfs dfs命令的区别
在linux输入hdfs dfs命令还是会调用hadoop fs命令
[hadoop@JD ~]$ hdfs dfs
Usage: hadoop fs [generic options]
[-cat [-ignoreCrc] <src> ...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [<path> ...]]
[-put [-f] [-p] [-l] <localsrc> ... <dst>]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
hdfs的回收站
切记检查生产上是否开启了回收站,CDH默认是开启的,哪怕开了回收站后,删除文件的时候也要慎用-skipTrash(直接删除)命令
- 配置开启回收站(10080代表保留7天),在core-site.xml进行配置
key | value |
---|---|
fs.trash.interval | 10080 |
配置开启回收站后,删除文件,会将文件删除到回收站中,七天过后会自动删除;但是如果使用hdfs dfs -put -skipTrash /xxx命令,哪怕配置了回收站,也会直接把文件删除
查看hdfs上的数据健康情况
[hadoop@JD ~]$ hdfs fsck /
19/12/05 20:40:09 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Connecting to namenode via http://JD:50070/fsck?ugi=hadoop&path=%2F
FSCK started by hadoop (auth:SIMPLE) from /192.168.0.3 for path / at Thu Dec 05 20:40:10 CST 2019
........Status: HEALTHY
Total size: 174944 B
Total dirs: 13
Total files: 8
Total symlinks: 0
Total blocks (validated): 7 (avg. block size 24992 B)
Minimally replicated blocks: 7 (100.0 %)
Over-replicated blocks: 0 (0.0 %)
Under-replicated blocks: 0 (0.0 %)
Mis-replicated blocks: 0 (0.0 %)
Default replication factor: 1
Average block replication: 1.0
这两个指标最重要,正常情况下这俩都是0
Corrupt blocks: 0 #损坏的块
Missing replicas: 0 (0.0 %)#丢失的副本
Number of data-nodes: 1
Number of racks: 1
FSCK ended at Thu Dec 05 20:40:10 CST 2019 in 7 milliseconds
The filesystem under path '/' is HEALTHY
HDFS的多节点(nn),单节点的磁盘均衡
各DN节点的数据均衡
为了防止各个节点的磁盘使用率差距过大,我们可以执行start-balancer.sh脚本设置阈值,参数为threshold = xxx,生产上一般设置阈值为10即可。
-
设置阈值的目的是
90+60+80=230/3=76%
所有节点的磁盘used与集群的平均used之差要小于这个阈值 -
同时也要设置执行平衡脚本时得带宽,生产上设置30m即可,不能让带宽占得太大,影响正常的写入流程,在hdfs-site.xml设置
key | value |
---|---|
dfs.datanode.balance.bandwidthPerSec | 30m |
-
执行
[hadoop@JD sbin]$ pwd /home/hadoop/app/hadoop/sbin [hadoop@JD sbin]$ ./start-balancer.sh 设置阈值执行 [hadoop@JD sbin]$ ./start-balancer.sh -threshold 5
其实可以自己写一个定时脚本,例如crontab,在每天晚上零点20的时候执行,从而达到每天调度,数据平衡,毛刺修正
一个DN节点的多个磁盘的数据均衡
操作使用文档:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSDiskbalancer.html
-
为什么要放置多个物理的磁盘目录
/data01 disk1 /data02 disk2 /data03 disk3 为了高效率写 高效率读 提前规划好2-3年存储量 ,避免后期加磁盘维护的工作量
-
查看磁盘所占空间大小
[hadoop@JD sbin]$ df -h /data01 90% /data02 60% /data03 80% /data04 0%
-
在hdfs-site.xml中开启磁盘数据平衡(注意apache的某些低版本的hdfs没有该配置项,cdh的版本都有)
key | value |
---|---|
dfs.disk.balancer.enabled | true |
-
在JD这台机器上生成执行计划,会生成JD.plan.json
hdfs diskbalancer -plan JD -
根据执行计划去执行
hdfs diskbalancer -execute JD.plan.json -
查看状态
hdfs diskbalancer -query JD -
什么时候手动或调度执行?
a.新盘加入 b.监控服务器的磁盘剩余空间 小于阈值 10%,发邮件预警 手动执行
怎么在DataNode中挂载磁盘?
由hdfs-site.xml文件的dfs.datanode.data.dir属性控制
key | value |
---|---|
dfs.datanode.data.dir | file://${hadoop.tmp.dir}/dfs/data |
假如我们现在有/data01,/data02,/data03,/data04四个目录需要挂载在该DataNode节点中,修改hdfs-site.xml文件添加属性
<property>
<name>dfs.datanode.data.dir</name>
<value>/data01,/data02,/data03,/data04</value>
</property>
HDFS的安全模式
进入安全模式
[hadoop@JD ~]$ hdfs dfsadmin -safemode enter
离开安全模式
[hadoop@JD ~]$ hdfs dfsadmin -safemode leave
安全模式影响
安全模式会影响写数据,对读数据没有影响;如果NN的log显示进入safe mode时,正常手动让其离开安全模式
如果hdfs突然进入安全模式,从flume或者kafka读数据到hdfs会抛大量的错,这时候我们最好可以在数据上游设置一个开关,不让数据到下游来