注意机器启动过之后,同步的时候不要同步data文件夹
一次写入,多次读出,不支持文件修改。适合数据分析,不适合网盘应用
分布式存储,文件系统。
优点:
高容错性。多复制,丢失自动恢复
适合大数据,数据以及文件规模
可以在廉价机器上,多副本来实现高可靠
缺点:
不适合低延时数据访问
无法对小文件高效存储
不支持并发多线程同时写入、文件随机修改,只支持append
组成 nn:master,
管理HDFS命名空间;
配置副本策略(放在那个nn节点);
管理数据块Block (DN里面存放的是一个个数据块,不是简单的文件)的映射信息;
处理客户端读写请求
dn:slave,nn下达指令,DN执行操作。
存储实际的数据块,数据块的形式存在
执行读写操作。
client:
文件切块,block大小由此处决定,平衡数据存储
与NN交互,获取文件位置信息
DN交互,获取文件信息
访问和管理HDFS
2NN:
HDFS文件块:
物理上是分块存储的,大小可以通过配置参数来决定,默认是128M
web页面无法新建文件夹权限问题 http://hadoop101:9870/explorer.html#/
在浏览器创建目录和删除目录及文件,是dr.who用户,dr.who其实是hadoop中http访问的静态用户名,并没有啥特殊含义,可以通过修改core-site.xml,配置为当前用户
< property >
< name > hadoop.http.staticuser.user</ name >
< value >deltaqin </ value >
</ property >
另外,通过查看hdfs的默认配置hdfs-default.xml发现hdfs默认是开启权限检查的。
dfs.permissions .enabled= true #是否在HDFS中开启权限检查,默认为true
解决 第一种方案
直接修改/user目录的权限设置,操作如下:
hdfs dfs -chmod -R 755 /user
第二种方案
在Hadoop的配置文件core-site.xml中增加如下配置:
< property >
< name > hadoop.http.staticuser.user</ name >
< value > deltaqin </ value >
</ property >
< property >
< name > dfs.permissions.enabled</ name >
< value > false</ value >
</ property >
命令行操作 1 2 3 4 5 bin/hadoop fs bin/hdfs dfs hadoop fs hdfs dfs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 sbin/start-dfs.sh sbin/start-yarn.sh hadoop fs -help rm touch kongming.txthadoop fs -moveFromLocal ./kongming.txt /sanguo/shuguo hadoop fs -copyFromLocal README.txt / touch liubei.txtvi liubei.txt san gu mao lu hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt hadoop fs -put ./zaiyiqi.txt /user/atguigu/test/ hadoop fs -copyToLocal /sanguo/shuguo/kongming.txt ./ hadoop fs -get /sanguo/shuguo/kongming.txt ./ hadoop fs -getmerge /user/atguigu/test/* ./zaiyiqi.txt hadoop fs -ls / hadoop fs -mkdir -p /sanguo/shuguo hadoop fs -cat /sanguo/shuguo/kongming.txt hadoop fs -chmod 666 /sanguo/shuguo/kongming.txt hadoop fs -chown deltaqin:deltaqin /sanguo/shuguo/kongming.txt hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt hadoop fs -mv /zhuge.txt /sanguo/shuguo/ hadoop fs -tail /sanguo/shuguo/kongming.txt hadoop fs -rm /user/atguigu/test/jinlian2.txt hadoop fs -mkdir /test hadoop fs -rmdir /test hadoop fs -du -s -h /user/atguigu/test 2.7 K /user/atguigu/test hadoop fs -du -h /user/atguigu/test 1.3 K /user/atguigu/test/README.txt 15 /user/atguigu/test/jinlian.txt 1.4 K /user/atguigu/test/zaiyiqi.txt hadoop fs -setrep 10 /sanguo/shuguo/kongming.txt
客户端操作 连接和关闭 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Before public void before () throws IOException, InterruptedException { fileSystem = FileSystem.get(URI.create("hdfs://hadoop101:8020" ), new Configuration (), "deltaqin" ); } @After public void after () throws IOException { fileSystem.close(); }
基本操作API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 @Test public void put () throws IOException, InterruptedException { fileSystem.copyFromLocalFile( new Path ("/Users/qinzetao/Pictures/QQ20200621-0.jpg" ), new Path ("/1.jpg" )); } @Test public void get () throws IOException { fileSystem.copyToLocalFile( new Path ("/1.jpg" ), new Path ("/Users/qinzetao/Documents/大数据/1_hadoop/代码/Hadoop/hdfs200105" ) ); } @Test public void ls () throws IOException { FileStatus[] fileStatuses = fileSystem.listStatus(new Path ("/" )); for (FileStatus fileStatus : fileStatuses) { System.out.println(fileStatus.getPath()); System.out.println(fileStatus.getOwner()); System.out.println("=================" ); } } @Test public void lf () throws IOException { RemoteIterator<LocatedFileStatus> statusRemoteIterator = fileSystem.listFiles(new Path ("/" ), true ); while (statusRemoteIterator.hasNext()) { LocatedFileStatus fileStatus = statusRemoteIterator.next(); System.out.println(fileStatus.getPath()); BlockLocation[] blockLocations = fileStatus.getBlockLocations(); for (int i = 0 ; i < blockLocations.length; i++) { System.out.println("第" + i + "块" ); String[] hosts = blockLocations[i].getHosts(); for (String host : hosts) { System.out.print(host + " " ); } System.out.println(); } System.out.println("===================================" ); } } @Test public void append () throws IOException { FSDataOutputStream append = fileSystem.append( new Path ("/README.txt" ) ); append.write("TestAPI" .getBytes()); IOUtils.closeStream(append); } @Test public void mv () throws IOException { fileSystem.rename(new Path ("/1.jpg" ), new Path ("/logs/2.jpg" )); }
数据流 写数据 完整流程
注意每一块选择存放在哪些节点是完全独立的过程。
节点选择 NameNode 会 选择 距离待上传数据最近 距离 的DataNode接收数据
节点距离(网络拓扑距离):两个节点到达最近的共同祖先的距离总和。
rack:机架,看做路由器,下面有很多DN
机架**感知 (副本存储节点**选择) 副本放置策略:For the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on the local machine if the writer is on a datanode, otherwise on a random datanode, another replica on a node in a different (remote) rack, and the last on a different node in the same remote rack .
第一个副本在Client所处的节点上。如果客户端在集群外,随机选一个。
第二个副本和第一个副本位于相同机架,随机节点 。
第三个副本位于不同机架,随机节点。
读数据
NameNode和SecondaryNameNode 元数据要求读写快,放在内存里面
涉及到持久化问题,如何提高效率?
利用多级缓存的思想!!!
FSImage文件是HDFS中名字节点NameNode上文件/目录元数据在特定某一时刻的持久化存储文件。(相当于是内存的镜像)
edits.log记录的是该干什么,不是元数据,元数据是读取这个记录之后读取对应的元数据放到内存里面得到的。
日志和image都在磁盘上,一个是日志,一个是数据
NN NN只持久化操作日志,
edits.log:记录操作,编辑日志
fsimage:edits持久化,镜像文件
NameNode被格式化之后,将在 $HADOOP_HOME/data/tmp/dfs/name/current 目录中产生如下文件:
Fsimage文件:(记录某一时刻内存状态)HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
Edits文件:(记录过程,没有元数据)存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
seen_txid文件保存的是一个数字,就是最后一个edits_的数字
每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作 ,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
启动流程
重启结束之后会触发一次合并,保存为checkpoint
2NN
Fsimage和Edits 格式化会生成一个空的fsimage,就可以启动了。
oiv查看Fsimage文件 oev apply the offline edits viewer to an edits file
oiv apply the offline fsimage viewer to an fsimage
1 2 3 4 5 6 hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径 pwd /opt/module/hadoop-3.1.3/data/tmp/dfs/name/current hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml cat /opt/module/hadoop-3.1.3/fsimage.xml
记录块信息,几块,多大
F simage中只记录由哪些块组成,没有记录块所对应 D ata N ode ,为什么?
在集群刚刚启动后,加载fsimage之后,要求DataNode上报数据块信息,并间隔一段时间后再次上报。(在安全模式里面,由DN主动向NN汇报,不让NN维护可以避免自己拿到的是陈旧的位置,)
oev查看Edits文件 1 2 3 4 hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径 hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop-3.1.3/edits.xml cat /opt/module/hadoop-3.1.3/edits.xml
内部是一个个的record,记录的是一个个操作
NameNode如何确定下次开机启动的时候合并哪些Edits?
Check Point时间设置 通常情况下,SecondaryNameNode 每隔**一小时执行一次 。下图所示:**
hdfs-default.xml:
1 2 3 4 <property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
*一分钟 *检查一次操作次数,当操作次数达到 1百万 * 时,SecondaryNameNode 执行 一次。 *
1 2 3 4 5 6 7 8 9 10 11 <property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操作动作次数</description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description> 1分钟检查一次操作次数</description> </property >
**(现在都用HA,不用这个)N ameNode故障 处理** NameNode故障后,可以采用如下两种方法恢复数据。
将SecondaryNameNode中数据拷贝到NameNode存储数据的目录 2NN的数据其实只是NN的部分数据,所以这个一般不再使用
1 2 3 4 5 6 7 kill -9 NameNode进程rm -rf /opt/module/hadoop-3.1.3/data/tmp/dfs/name/*scp -r atguigu@hadoop104:/opt/module/hadoop-3.1.3/data/tmp/dfs/namesecondary/* ./name/ hdfs --daemon start namenode
使用-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode 中数据拷贝到NameNode目录中。 修改hdfs-site.xml中的
1 2 3 4 5 6 7 8 9 <property> <name>dfs.namenode.checkpoint.period</name> <value>120</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/opt/module/hadoop-3.1.3/data/tmp/dfs/name</value> </property>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 kill -9 NameNode进程rm -rf /opt/module/hadoop-3.1.3/data/tmp/dfs/name/*scp -r atguigu@hadoop104:/opt/module/hadoop-3.1.3/data/tmp/dfs/namesecondary ./ rm -rf in_use.lock pwd /opt/module/hadoop-3.1.3/data/tmp/dfs ls data name namesecondary bin/hdfs namenode -importCheckpoint hdfs --daemon start namenode
集群安全模式 集群状态不正确的时候,就加入,启动的时候也会进入。
NameNode启动时,首先将镜像文件(Fsimage)载入内存,并执行编辑日志(Edits)中的各项操作。一旦在内存中成功建立文件系统元数据的映像,则创建一个新的Fsimage文件和一个空的编辑日志。此时,NameNode开始监听DataNode请求。这个过程期间,NameNode一直运行在安全模式,即NameNode的文件系统对于客户端来说是只读的。
系统中的数据块的位置并不是由NameNode维护的,而是以块列表的形式存储在DataNode中。在系统的正常操作期间,NameNode会在内存中保留所有块位置的映射信息。在安全模式下,各个DataNode会向NameNode发送最新的块列表信息 ,NameNode了解到足够多的块位置信息之后,即可高效运行文件系统。
如果满足“最小副本条件”,NameNode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1,一块只要有一个副本就可以)。在启动一个刚刚格式化的HDFS集群时,因为系统中还没有任何块,所以NameNode不会进入安全模式。
集群处于安全模式,不能执行重要操作(写操作)。集群启动完成后,自动退出安全模式。
(1)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态)
(2)bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态)
(3)bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态)
(4)bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式状态)
1 2 3 4 5 6 7 8 9 hdfs dfsadmin -safemode get Safe mode is OFF hdfs dfsadmin -safemode enter touch safemode.shvim safemode.sh
1 2 3 #!/bin/bash hdfs dfsadmin -safemode wait hdfs dfs -put /opt/module/hadoop-3.1.3/README.txt /
1 2 3 4 5 6 7 8 9 10 11 12 chmod 777 safemode.sh ./safemode.sh hdfs dfsadmin -safemode leave Safe mode is OFF
DataNode
原理:把文件数据整整齐齐切开之后按照block存放,想要直接自己恢复的话,可以复制出来,使用cat将文件追加,拼接起来之后直接解压就可以获取原始数据
块也有自己的元数据
保证数据完整性的方法 (1)当DataNode读取Block的时候,它会计算CheckSum。
(2)如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
(3)Client读取其他DataNode上的Block。
(4)DataNode在其文件创建后周期验证CheckSum。
掉线处理(时限设置)
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒 ,dfs.heartbeat.interval的单位为秒 。
1 2 3 4 5 6 7 8 <property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value> </property> <property> <name>dfs.heartbeat.interval</name> <value>3</value> </property>
添加新数据****节点 在原有集群基础上动态添加新的数据节点。
再克隆一台hadoop104主机,修改IP地址和主机名称,
-a 包含所有属性以及角色权限复制
1 2 sudo rsync -av /opt/module hadoop104:/optsudo rsync -av /etc/profile.d hadoop104:/etc
删除原来HDFS文件系统留存的文件(/opt/module/hadoop-3.1.3/data和log),source一下配置文件 source /etc/profile
注意这里使用的不是群起,所以不需要配置workers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 hdfs --daemon stop datanode hdfs --daemon start datanode sbin/yarn-daemon.sh start nodemanager hadoop fs -put /opt/module/hadoop-3.1.3/LICENSE.txt / ./start-balancer.sh starting balancer, logging to /opt/module/hadoop-3.1.3/logs/hadoop-atguigu-balancer-hadoop102.out Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
退役旧数据****节点 添加白****名单 添加到白名单的主机节点,都允许访问NameNode,不在白名单的主机节点,都会被退出。
1 2 3 4 5 6 7 8 9 10 pwd /opt/module/hadoop-3.1.3/etc/hadoop touch dfs.hostsvi dfs.hosts hadoop102 hadoop103 hadoop104
1 2 3 4 5 <property> <name>dfs.hosts</name> <value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts</value> </property>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 xsync hdfs-site.xml hdfs dfsadmin -refreshNodes Refresh nodes successful yarn rmadmin -refreshNodes 17/06/24 14:17:11 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.1.103:8033 ./start-balancer.sh starting balancer, logging to /opt/module/hadoop-3.1.3/logs/hadoop-atguigu-balancer-hadoop102.out Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
黑名单****退役 在黑名单上面的主机都会被强制退出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 pwd /opt/module/hadoop-3.1.3/etc/hadoop touch dfs.hosts.excludevi dfs.hosts.exclude hadoop105 <property> <name>dfs.hosts.exclude</name> <value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts.exclude</value> </property> hdfs dfsadmin -refreshNodes Refresh nodes successful yarn rmadmin -refreshNodes 17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.1.103:8033 hdfs --daemon stop datanode stopping datanode sbin/yarn-daemon.sh stop nodemanager stopping nodemanager sbin/start-balancer.sh starting balancer, logging to /opt/module/hadoop-3.1.3/logs/hadoop-atguigu-balancer-hadoop102.out Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
Datanode多****目录配置 *DataNode也可以配置成多个目录,每个 目录存储的数据不一样。即 :数据不是副本 *
配置namenode所在的机器的hdfs-site.xml,数据就会均匀的放在data/data和data/data2
1 2 3 4 <property > <name > dfs.datanode.data.dir</name > <value > file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value > </property >
Hadoop3新特性
最低java版本由7升级为8
引入纠删码,默认3副本,开销较大,只是为了提高容错能力。纠删码在不到百分之50的数据冗余的情况下提供和3副本相同的容错机制,所以使用纠删码作为副本机制的改进
重写shell脚本。