随着数据量越来越大,在一个本地文件系统里边已经存不下所有的数据,需要将数据分配到更多的操作系统和文件管理系统,但是不方便管理和维护,所以需要一个系统来统一管理这些存储了所有数据的机器,这个系统也就是分布式文件管理系统,HDFS只是分布式文件管理系统的一种。
![image.png](https://img-blog.csdnimg.cn/img_convert/827e11ae5dd6d2766a97e82ee42ca02d.png#clientId=u0d082548-c00e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=419&id=ue4f4e063&margin=[object Object]&name=image.png&originHeight=419&originWidth=811&originalType=binary&ratio=1&rotation=0&showTitle=false&size=144103&status=done&style=none&taskId=ub50a345e-8d91-4e6a-8b81-293605bbf7a&title=&width=811)
HDFS(全称:Hadoop Distribute File System,Hadoop 分布式文件系统),用于文件存储和管理,通过目录树来定位文件,是分布式的。可以与Linux文件系统做类比,只不过是封装了很多机器的文件管理功能。
HDFS 通过统一的命名空间目录树来定位文件; 另外,它是分布式的,由很多服务器联合起来实现
其功能,集群中的服务器有各自的角色(分布式本质是拆分,各司其职);
HDFS 的架构是典型的 Master/Slave 结构。
HDFS集群往往是一个NameNode(HA架构会有两个NameNode,联邦机制)+多个DataNode组成;
NameNode是集群的主节点,DataNode是集群的从节点。
HDFS 中的文件在物理上是分块存储(block)的,块的大小可以通过配置参数来规定;Hadoop2.x版本中默认的block大小是128M;
HDFS 支持传统的层次型文件组织结构。用户或者应用程序可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。
Namenode 负责维护文件系统的名字空间,任何对文件系统名字空间或属性的修改都将被Namenode 记录下来。
HDFS提供给客户单一个抽象目录树,访问形式:hdfs://namenode的hostname:port/test/input
hdfs://linux121:9000/test/input
我们把目录结构及文件分块位置信息叫做元数据。
NameNode的元数据记录每一个文件所对应的block信息(block的id,以及所在的DataNode节点的信息)
文件的各个 block 的具体存储管理由 DataNode 节点承担。一个block会有多个DataNode来存储,DataNode会定时向NameNode来汇报自己持有的block信息。
为了容错,文件的所有 block 都会有副本。每个文件的 block 大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。副本数量默认是3个。
HDFS 是设计成适应一次写入,多次读出的场景,且不支持文件的随机修改。 (支持追加写入,不只支持随机更新),正因为如此,HDFS 适合用来做大数据分析的底层存储服务,并不适合用来做网盘等应用(修改不
方便,延迟大,网络开销大,成本太高)
![image.png](https://img-blog.csdnimg.cn/img_convert/e5b77ec5f87021834170e4152b90fb08.png#clientId=ucea71b1f-bafa-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=634&id=uae0769bd&margin=[object Object]&name=image.png&originHeight=634&originWidth=1223&originalType=binary&ratio=1&rotation=0&showTitle=false&size=122384&status=done&style=none&taskId=ue849ac13-3abe-42fd-9c36-b5bdc4b8147&title=&width=1223)
如果没有配置 hadoop 的环境变量,则在 hadoop 的安装目录下的bin目录中执行以下命令,如已配置 hadoop 环境变量,则可在任意目录下执行,命令与linux命令大同小异,可以对比记忆
bin/hadoop fs 具体命令 或者 bin/hdfs dfs 具体命令
[root@node101 ~]# hdfs dfs
Usage: hadoop fs [generic options]
[-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] [-l] [-d] <localsrc> ... <dst>]
[-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] <path> ...]
[-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] [-x] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
[-help [cmd ...]]
[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-truncate [-w] <length> <path> ...]
[-usage [cmd ...]]
Generic options supported are:
-conf <configuration file> specify an application configuration file
-D <property=value> define a value for a given property
-fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
-jt <local|resourcemanager:port> specify a ResourceManager
-files <file1,...> specify a comma-separated list of files to be copied to the map reduce cluster
-libjars <jar1,...> specify a comma-separated list of jar files to be included in the classpath
-archives <archive1,...> specify a comma-separated list of archives to be unarchived on the compute machines
The general command line syntax is:
command [genericOptions] [commandOptions]
[root@node101 ~]# hdfs dfs -help rm
-rm [-f] [-r|-R] [-skipTrash] [-safely] ... :
Delete all files that match the specified file pattern. Equivalent to the Unix
command "rm "
-f If the file does not exist, do not display a diagnostic message or
modify the exit status to reflect an error.
-[rR] Recursively deletes directories.
-skipTrash option bypasses trash, if enabled, and immediately deletes .
-safely option requires safety confirmation, if enabled, requires
confirmation before deleting large directory with more than
files. Delay is expected when
walking over large directory recursively to count the number of
files to be deleted before the confirmation.
[root@node101 ~]# hdfs dfs -ls /
[root@node101 ~]# hdfs dfs -mkdir -p /bigdata
# 创建test.txt空文件,里边没有任何内容
[root@node101 ~]# vi test.txt
# 查询test.txt文件
[root@node101 ~]# ls test.txt
test.txt
#剪切test.txt文件到hdfs上bigdata文件夹
[root@node101 ~]# hdfs dfs -moveFromLocal ./test.txt /bigdata
#查看hdfs上/bigdata文件夹,test.txt文件已上传
[root@node101 ~]# hdfs dfs -ls /bigdata
Found 1 items
-rw-r--r-- 3 root supergroup 31 2022-07-26 18:13 /bigdata/test.txt
#查询本地test.txt文件 报错,原因已经将test.txt剪切到hdfs
[root@node101 ~]# ls test.txt
ls: cannot access test.txt: No such file or directory
# 查看本地wc.txt文件
[root@node101 ~]# ls wc.txt
wc.txt
# 从本地上传wc.txt文件到hdfs上/bigdata目录
[root@node101 ~]# hdfs dfs -copyFromLocal wc.txt /bigdata
[root@node101 ~]# hdfs dfs -ls /bigdata
Found 2 items
-rw-rw-rw- 10 root root 45 2022-07-26 18:33 /bigdata/test.txt
-rw-r--r-- 3 root supergroup 42 2022-07-26 21:10 /bigdata/wc.txt
# 查看本地还存在wc.txt文件
[root@node101 ~]# ls wc.txt
wc.txt
# 查询hdfs上test.txt文件内容,此时为空
[root@node101 ~]# hdfs dfs -cat /bigdata/test.txt
# 在本地创建test2.txt并输入一些单词
[root@node101 ~]# vi test2.txt
#查看test2.txt内容
[root@node101 ~]# cat test2.txt
hadoop hive
hadoop spark
bigdata flink
hbase
# 追加test2.txt 内容到hdfs上的/bigdata/test.txt文件
[root@node101 ~]# hdfs dfs -appendToFile test2.txt /bigdata/test.txt
# 再次查看hdfs上/bigdata/test.txt文件,内容已经变化
[root@node101 ~]# hdfs dfs -cat /bigdata/test.txt
hadoop hive
hadoop spark
bigdata flink
hbase
# 查看文件权限
[root@node101 ~]# hdfs dfs -ls /bigdata/test.txt
-rw-r--r-- 3 root supergroup 45 2022-07-26 18:33 /bigdata/test.txt
# 修改文件权限
[root@node101 ~]# hdfs dfs -chmod 666 /bigdata/test.txt
# 再次查看文件权限
[root@node101 ~]# hdfs dfs -ls /bigdata/test.txt
-rw-rw-rw- 3 root supergroup 45 2022-07-26 18:33 /bigdata/test.txt
# 修改文件所属
[root@node101 ~]# hdfs dfs -chown root:root /bigdata/test.txt
# 再次查看文件所属
[root@node101 ~]# hdfs dfs -ls /bigdata/test.txt
-rw-rw-rw- 3 root root 45 2022-07-26 18:33 /bigdata/test.txt
# 查看hdfs上/bigdata目录下文件
[root@node101 ~]# hdfs dfs -ls /bigdata/
Found 1 items
-rw-rw-rw- 3 root root 45 2022-07-26 18:33 /bigdata/test.txt
# 拷贝本地test2.txt文件到hdfs
[root@node101 ~]# hdfs dfs -copyFromLocal test2.txt /bigdata
# 再次查看hdfs上/bigdata目录下文件,test2.txt已经上传
[root@node101 ~]# hdfs dfs -ls /bigdata/
Found 2 items
-rw-rw-rw- 3 root root 45 2022-07-26 18:33 /bigdata/test.txt
-rw-r--r-- 3 root supergroup 45 2022-07-26 19:05 /bigdata/test2.txt
# 删除本地test2.txt文件
[root@node101 ~]# rm -rf test2.txt
# 查看文件已删除
[root@node101 ~]# ls test2.txt
ls: cannot access test2.txt: No such file or directory
# 从hdfs拷贝test2.txt文件到本地
[root@node101 ~]# hdfs dfs -copyToLocal /bigdata/test2.txt
# 查看文件已经被拷贝到本地
[root@node101 ~]# ls test2.txt
test2.txt
# 创建一个hdfs新目录 /bigdata2
[root@node101 ~]# hdfs dfs -mkdir /bigdata2
# 查看/bigdata2目录下没有文件
[root@node101 ~]# hdfs dfs -ls /bigdata2
# 从/bigdata目录拷贝test2.txt文件到/bigdata2
[root@node101 ~]# hdfs dfs -cp /bigdata/test2.txt /bigdata2
# 再次查看bigdata2文件夹已经多了test2文件
[root@node101 ~]# hdfs dfs -ls /bigdata2
Found 1 items
-rw-r--r-- 3 root supergroup 45 2022-07-26 19:20 /bigdata2/test2.txt
# 查看bigdata文件夹下test2.txt文件依然在
[root@node101 ~]# hdfs dfs -ls /bigdata
Found 2 items
-rw-rw-rw- 3 root root 45 2022-07-26 18:33 /bigdata/test.txt
-rw-r--r-- 3 root supergroup 45 2022-07-26 19:05 /bigdata/test2.txt
# 删除bigdata2文件夹下的test2.txt文件
[root@node101 ~]# hdfs dfs -rm /bigdata2/test2.txt
Deleted /bigdata2/test2.txt
# 文件已删除,查看文件报错提示文件不存在
[root@node101 ~]# hdfs dfs -ls /bigdata2/test2.txt
ls: `/bigdata2/test2.txt': No such file or directory
# 从bigdata文件夹下移动test2.txt文件到bigdata2文件夹
[root@node101 ~]# hdfs dfs -mv /bigdata/test2.txt /bigdata2
# 查看bigdata目录下的test2.txt文件已不存在
[root@node101 ~]# hdfs dfs -ls /bigdata
Found 1 items
-rw-rw-rw- 3 root root 45 2022-07-26 18:33 /bigdata/test.txt
# 查看bigdata2文件加下已有test2.txt文件
[root@node101 ~]# hdfs dfs -ls /bigdata2
Found 1 items
-rw-r--r-- 3 root supergroup 45 2022-07-26 19:05 /bigdata2/test2.txt
[root@node101 ~]# hdfs dfs -tail /bigdata/test.txt
hadoop hive
hadoop spark
bigdata flink
hbase
# 查看hdfs上/bigdata/test.txt文件内容
[root@node101 ~]# hdfs dfs -cat /bigdata/test.txt
hadoop hive
hadoop spark
bigdata flink
hbase
# 查看hdfs上/bigdata/wc.txt文件内容
[root@node101 ~]# hdfs dfs -cat /bigdata/wc.txt
lwp spark flink lwp
hadoop flink hive
mr
# 合并/bigdata/test.txt和/bigdata/wc.txt文件内容 到本地merge.txt
[root@node101 ~]# hdfs dfs -getmerge /bigdata/* merge.txt
# 查看合并后的文件内容
[root@node101 ~]# cat merge.txt
hadoop hive
hadoop spark
bigdata flink
hbase
lwp spark flink lwp
hadoop flink hive
mr
[root@node101 ~]# hdfs dfs -df /
Filesystem Size Used Available Use%
hdfs://node101:9000 109443035136 1231085568 91952766976 1%
[root@node101 ~]# hdfs dfs -df -h /
Filesystem Size Used Available Use%
hdfs://node101:9000 101.9 G 1.1 G 85.6 G 1%
[root@node101 ~]# hdfs dfs -du -s -h /bigdata
45 /bigdata
[root@node101 ~]# hdfs dfs -du -h /bigdata
45 /bigdata/test.txt
[root@node101 ~]# hdfs dfs -count /bigdata
1 2 87 /bigdata
目录数量 文件数量 文件总大小 统计目录
[root@node101 ~]# hdfs dfs -expunge
[root@node101 ~]# hdfs dfs -setrep 10 /bigdata/test.txt
Replication 10 set: /bigdata/test.txt
在NameNode页面查看test.txt文件元数据信息replication为10
![图片.png](https://img-blog.csdnimg.cn/img_convert/497febe106eae9ac1de255cf59d4e63c.png#clientId=u2865cb81-e3cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=741&id=u164d3e47&margin=[object Object]&name=图片.png&originHeight=741&originWidth=1736&originalType=binary&ratio=1&rotation=0&showTitle=false&size=218999&status=done&style=none&taskId=ua19cf7dd-c379-40c7-b9f9-d04e52befa6&title=&width=1736)
**需要注意:**这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的
数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到10台时,副本数才能达到10。
在多人共用HDFS的环境下,配额设置非常重要。特别是在 Hadoop 处理大量资料的环境,如果没有配额管理,很容易把所有的空间用完造成别人无法存取。HDFS 的配额设定是针对目录而不是针对账号,可以让每个账号仅操作某一个目录,然后对目录设置配置。
HDFS 文件的限额配置允许我们以文件个数,或者文件大小来限制我们在某个目录下上传的文件数量或者文件内容总量,以便达到我们类似百度网盘网盘等限制每个用户允许上传的最大的文件的量。
# 查看配额信息
[root@node101 ~]# hdfs dfs -count -q -h /
8.0 E 8.0 E none inf 82 382 386.5 M /
数量配额
# 新建hdfs上/bigdata3文件夹
[root@node101 ~]# hdfs dfs -mkdir /bigdata3
# 上传两个文件到/bigdata3目录下
[root@node101 ~]# hdfs dfs -put test2.txt wc.txt /bigdata3
# 删除/bigdata3目录下两个文件
[root@node101 ~]# hdfs dfs -rm -r -f /bigdata3/*
Deleted /bigdata3/test2.txt
Deleted /bigdata3/wc.txt
# 对/bigdata3文件夹做配额限制,限制最多上传两个文件
[root@node101 ~]# hdfs dfsadmin -setQuota 2 /bigdata3
# 再次上传两个文件,发现上传失败,有文件数量限制,只上传成功了一个文件
[root@node101 ~]# hdfs dfs -put test2.txt wc.txt /bigdata3
put: The NameSpace quota (directories and files) of directory /bigdata3 is exceeded: quota=2 file count=3
[root@node101 ~]# hdfs dfs -ls /bigdata3
Found 1 items
-rw-r--r-- 3 root supergroup 45 2022-07-26 21:43 /bigdata3/test2.txt
# 清除/bigdata3配额设置
[root@node101 ~]# hdfs dfsadmin -clrQuota /bigdata3
# 再次上传文件成功
[root@node101 ~]# hdfs dfs -put test2.txt wc.txt /bigdata3
put: `/bigdata3/test2.txt': File exists
[root@node101 ~]# hdfs dfs -ls /bigdata3
Found 2 items
-rw-r--r-- 3 root supergroup 45 2022-07-26 21:43 /bigdata3/test2.txt
-rw-r--r-- 3 root supergroup 42 2022-07-26 21:48 /bigdata3/wc.txt
空间大小配额
在设置空间配额时,设置的空间至少是 block_size * 3 大小
# 设置空间配额
[root@node101 ~]# hdfs dfsadmin -setSpaceQuota 10K /bigdata3
# 生成任意大小文件
[root@node101 ~]# dd if=/dev/zero of=test3.txt bs=1M count=2
2+0 records in
2+0 records out
2097152 bytes (2.1 MB) copied, 0.00387978 s, 541 MB/s
# test3.txt文件超过设置的空间配额,上传失败
[root@node101 ~]# hdfs dfs -put test3.txt /bigdata3
put: The DiskSpace quota of /bigdata3 is exceeded: quota = 10240 B = 10 KB but diskspace consumed = 402653184 B = 384 MB
# 请出空间配额限制,上传文件成功
[root@node101 ~]# hdfs dfsadmin -clrSpaceQuota /bigdata3
[root@node101 ~]# hdfs dfs -put test3.txt /bigdata3
[root@node101 ~]# hdfs dfs -ls /bigdata3
Found 1 items
-rw-r--r-- 3 root supergroup 2097152 2022-07-26 22:00 /bigdata3/test3.txt
安全模式是hadoop的一种保护机制,用于保证集群中的数据块的安全性。当集群启动的时候,会首先进入安全模式。当系统处于安全模式时会检查数据块的完整性。
假设我们设置的副本数(即参数dfs.replication)是3,那么在datanode上就应该有3个副本存在,假设只存在2个副本,那么比例就是2/3=0.666。hdfs默认的副本率0.999。我们的副本率0.666明显小于0.999,因此系统会自动的复制副本到其他dataNode,使得副本率不小于0.999。如果系统中有5个副本,超过我们设定的3个副本,那么系统也会删除多于的2个副本。
**在安全模式状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。**在当整个系统达到安全标准时,HDFS自动离开安全模式。30s安全模式操作命令
hdfs dfsadmin -safemode get #查看安全模式状态
hdfs dfsadmin -safemode enter #进入安全模式
hdfs dfsadmin -safemode leave #离开安全模式
![图片.png](https://img-blog.csdnimg.cn/img_convert/880bbc9992215cd0abf584cca9ba6380.png#clientId=u2865cb81-e3cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=396&id=u3c7e6a5a&margin=[object Object]&name=图片.png&originHeight=396&originWidth=819&originalType=binary&ratio=1&rotation=0&showTitle=false&size=40015&status=done&style=none&taskId=u2bea70b6-531e-4f2e-b799-f4714390961&title=&width=819)
![图片.png](https://img-blog.csdnimg.cn/img_convert/1484864601fb69b29b46ee1726e3f0b0.png#clientId=u2865cb81-e3cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=659&id=ue0ecf005&margin=[object Object]&name=图片.png&originHeight=659&originWidth=618&originalType=binary&ratio=1&rotation=0&showTitle=false&size=40609&status=done&style=none&taskId=u860ac8ed-14c7-464c-8e82-5f0b52fcfe7&title=&width=618)
![图片.png](https://img-blog.csdnimg.cn/img_convert/d346f43281aaa8179e35dc8ee8881536.png#clientId=u2865cb81-e3cf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=658&id=u9wYX&margin=[object Object]&name=图片.png&originHeight=658&originWidth=1124&originalType=binary&ratio=1&rotation=0&showTitle=false&size=86138&status=done&style=none&taskId=u82a07e5d-d40e-4e5f-83ee-70367d4f6a2&title=&width=1124)
org.apache.hadoop
hadoop-client
2.9.2
org.apache.hadoop
hadoop-hdfs
2.9.2
org.apache.hadoop
hadoop-common
2.9.2
junit
junit
RELEASE
org.apache.logging.log4j
log4j-core
2.8.2
为了便于控制程序运行打印的日志数量,需要在项目的src/main/resources目录下,新建一个文件,命
名为“log4j.properties”,文件内容:
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
package com.hadoop.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class HDFSClient {
@Test
//测试创建目录
public void testMkdirs() throws URISyntaxException, IOException, InterruptedException {
//1.获取hadoop集群的configuration对象
Configuration configuration = new Configuration();
//2.根据configuration获取FileSystem对象
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node101:9000"), configuration, "root");
//3.创建文件夹
fileSystem.mkdirs(new Path("/bigdata4"));
//4.释放FileSystem对象(类似于关闭数据库连接)
fileSystem.close();
}
}
题,报错如下:
![图片.png](https://img-blog.csdnimg.cn/img_convert/d2a740d9ec08940e8f68733c8aa809e7.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=259&id=u20c9e8bb&margin=[object Object]&name=图片.png&originHeight=259&originWidth=1661&originalType=binary&ratio=1&rotation=0&showTitle=false&size=59191&status=done&style=none&taskId=uc8ca18b7-e612-43c4-a0d2-41e47cc4ff0&title=&width=1661)2. windows解压安装Hadoop后,在调用相关API操作HDFS集群时可能会报错,这是由于Hadoop安装缺少windows操作系统相关文件所致,如下图:
![图片.png](https://img-blog.csdnimg.cn/img_convert/0a312c9bed4ff5e358c0f34d1278da27.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=256&id=u9aa57a63&margin=[object Object]&name=图片.png&originHeight=256&originWidth=1698&originalType=binary&ratio=1&rotation=0&showTitle=false&size=61565&status=done&style=none&taskId=ue15620fa-c1d2-4332-85eb-abf9f005bc8&title=&width=1698)解决方案:
把winutils.exe拷贝放到windows系统Hadoop安装目录的bin目录下即可!!
@Test
public void testCopyFromLocalFile() throws IOException,
InterruptedException, URISyntaxException {
// 1 获取文件系统
Configuration configuration = new Configuration();
configuration.set("dfs.replication", "2");
FileSystem fs = FileSystem.get(new URI("hdfs://node101:9000"),
configuration, "root");
// 2 上传文件
fs.copyFromLocalFile(new Path("e:/wc.txt"), new Path("/wc.txt"));
// 3 关闭资源
fs.close();
System.out.println("end");
}
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
参数优先级排序:(1)代码中设置的值 >(2)用户自定义配置文件 >(3)服务器的默认配置
package com.hadoop.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
public class HDFSClient {
Configuration configuration = null;
FileSystem fs = null;
@Before
public void init() throws URISyntaxException, IOException, InterruptedException {
//获取Hadoop集群的configuration对象
configuration = new Configuration();
//根据configuration获取FileSystem对象
fs = FileSystem.get(new URI("hdfs://node101:9000"), configuration, "root");
}
@After
public void destroy() throws IOException {
//释放FileSystem对象(类似数据库链接)
fs.close();
}
}
//创建目录
@Test
public void testMkdirs() throws URISyntaxException, IOException, InterruptedException {
fs.mkdirs(new Path("/bigdata4"));
}
//上传文件
@Test
public void copyFromLocalToHDFS() throws IOException {
//把D盘wc.txt文件上传到hdfs的/bigdata4文件夹
fs.copyFromLocalFile(new Path("d:/wc.txt"),new Path("/bigdata4/wc.txt"));
}
//下载文件
@Test
public void copyFromHDFSToLocal() throws IOException {
//把/bigdata4文件夹下的wc.txt文件下载到E盘
fs.copyToLocalFile(new Path("/bigdata4/wc.txt"),new Path("e:/wc.txt"));
}
//删除文件或目录
@Test
public void deleteFile() throws IOException {
//删除hdfs的bigdata4文件夹
fs.delete(new Path("/bigdata4"),true);
}
遍历根目录获取所有文件及文件夹信息
//遍历hdfs根目录达到文件及文件夹信息:名称、权限、长度等
@Test
public void listFiles() throws IOException {
//得到一个迭代器:装有指定目录下所有文件信息
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"),true);
while(listFiles.hasNext()){
LocatedFileStatus fileStatus = listFiles.next();
// 文件名称
String name = fileStatus.getPath().getName();
//文件长度
long len = fileStatus.getLen();
//权限
FsPermission permission = fileStatus.getPermission();
//分组
String group = fileStatus.getGroup();
//所属用户
String owner = fileStatus.getOwner();
System.out.println(name+"\t"+len+"\t"+permission+"\t"+group+"\t"+owner);
//块信息
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
//获取块存储的节点信息
String[] hosts = blockLocation.getHosts();
for (String host : hosts) {
System.out.println("块所在主机名称"+host);
}
}
System.out.println("----------------------------------------------------------------------");
}
}
//文件及文件夹判断
@Test
public void isFile() throws IOException {
FileStatus[] fileStatuses = fs.listStatus(new Path("/bigdata"));
for (FileStatus fileStatus : fileStatuses) {
//判断是否是文件
boolean fileFlag = fileStatus.isFile();
if(fileFlag){
System.out.println("文件: "+fileStatus.getPath().getName());
}else{
System.out.println("文件夹:"+fileStatus.getPath().getName());
}
}
}
//使用IO流操作上传文件到HDFS
@Test
public void uploadFileIO() throws IOException {
//1.读取本地文件的输入流
FileInputStream fileInputStream = new FileInputStream(new File("e:/wc.txt"));
//2.准备些数据到hdfs 的输出流
FSDataOutputStream fileOutputStream = fs.create(new Path("/bigdata3/wc.txt"));
//3.输入流数据拷贝到输出流:数组的大小,以及是否关闭流底层有默认值
IOUtils.copyBytes(fileInputStream,fileOutputStream,configuration);
//4.可以再次关闭流
IOUtils.closeStream(fileOutputStream);
IOUtils.closeStream(fileInputStream);
}
//使用IO流下载文件到本地
@Test
public void downLoadFileIO() throws IOException {
//1.读取hdfs文件输入流
FSDataInputStream in = fs.open(new Path("/bigdata3/test3.txt"));
//2.获取本地文件输出流
FileOutputStream out = new FileOutputStream(new File("e:/test3.txt"));
//3.流拷贝
IOUtils.copyBytes(in, out, configuration);
//4.可以再次关闭流
IOUtils.closeStream(out);
IOUtils.closeStream(in);
}
//seek定位读取hdfs指定文件,使用io流读取/bigdata3/wc.txt文件并把内容输出两次,本质就是读取文件内容两次并输出
@Test
public void seekReadFile() throws IOException {
//1.创建一个读取hdfs文件的输入流
FSDataInputStream in = fs.open(new Path("/bigdata3/wc.txt"));
//2.控制台数据System.out
//3.实现流拷贝,输入流——》控制台输出
IOUtils.copyBytes(in,System.out,4096,false);
in.seek(0);
IOUtils.copyBytes(in,System.out,4096,false);
IOUtils.closeStream(in);
}
在本地网络中,两个节点被称为“彼此近邻”是什么意思?在海量数据处理中,其主要限制因素是节点之间数据的传输速率——带宽很稀缺。这里的想法是将两个节点间的带宽作为距离的衡量标准。
节点距离:两个节点到达最近的共同祖先的距离总和。
例如,假设有数据中心d1机架r1中的节点n1。该节点可以表示为/d1/r1/n1。利用这种标记,这里给出四种距离描述。
Distance(/d1/r1/n1, /d1/r1/n1)=0(同一节点上的进程)
Distance(/d1/r1/n1, /d1/r1/n3)=2(同一机架上的不同节点)
Distance(/d1/r1/n1, /d1/r3/n3)=4(同一数据中心不同机架上的节点)
Distance(/d1/r1/n1, /d2/r4/n3)=6(不同数据中心的节点)
机架结构图:
![图片.png](https://img-blog.csdnimg.cn/img_convert/867f8b89858dff18525a75102e923a28.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=382&id=ue38803a8&margin=[object Object]&name=图片.png&originHeight=382&originWidth=921&originalType=binary&ratio=1&rotation=0&showTitle=false&size=28149&status=done&style=none&taskId=ua968e78c-bf5f-4fc1-b30a-3091c79d5c5&title=&width=921)
Hadoop2.9.2 副本节点选择
第一个副本在client所处的节点上。如果客户端在集群外,随机选一个。
第二个副本和第一个副本位于相同机架,随机节点。
第三个副本位于不同机架,随机节点。
![图片.png](https://img-blog.csdnimg.cn/img_convert/d28bdc9d8250bf67265a5edbd3c26d2f.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=354&id=u015daf4c&margin=[object Object]&name=图片.png&originHeight=354&originWidth=615&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13070&status=done&style=none&taskId=u0b4e494a-5b26-461c-80cc-07217871826&title=&width=615)
![图片.png](https://img-blog.csdnimg.cn/img_convert/28dbb7af526d63940922e7017a8c69e2.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=666&id=uf68227fd&margin=[object Object]&name=图片.png&originHeight=666&originWidth=1058&originalType=binary&ratio=1&rotation=0&showTitle=false&size=60998&status=done&style=none&taskId=ub8855c91-32d5-40a2-89ff-ac9599d2a26&title=&width=1058) 读数据流程图
![图片.png](https://img-blog.csdnimg.cn/img_convert/bfcc6ffba6fce3e3bc113dd32574ee2a.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=580&id=u7cb9c9c5&margin=[object Object]&name=图片.png&originHeight=580&originWidth=919&originalType=binary&ratio=1&rotation=0&showTitle=false&size=114673&status=done&style=none&taskId=u6e2ba2c8-2169-4dc0-a5c8-43c95f5bba8&title=&width=919) 写数据流程图
验证package代码
@Test
public void testUploadPacket() throws IOException {
//1 准备读取本地文件的输入流
final FileInputStream in = new FileInputStream(new File("e:/wc.txt"));
//2 准备好写出数据到hdfs的输出流
final FSDataOutputStream out = fs.create(new Path("/bigdata3/wc.txt"), new Progressable() {
public void progress() {
//这个progress方法就是每传输64KB(packet)就会执行一次
System.out.println("&");
}
});
//3 实现流拷贝
IOUtils.copyBytes(in, out, configuration);
//默认关闭流选项是true,所以会自动关闭
//4 关流 可以再次关闭也可以不关了
}
HDFS 将所有的文件全部抽象成为 block 块来进行存储,不管文件大小,全部一视同仁都是以 block 块的统一大小和形式进行存储,方便我们的分布式文件系统对文件的管理。
HDFS中的文件物理上实际以块(block)的形式存储,可以通过 hdfs-site.xml 中dfs.blocksize参数设置,这个参数在hadoop2.x版本中默认是128M,老版本为64M
<property>
<name>dfs.block.size</name>
<value>块大小 以字节为单位</value> //只写数值就可以
</property>
为了保证block块的安全性,也就是数据的安全性,在hadoop2当中,文件默认保存三个副本,我们可以更改副本数以提高数据的安全性
在hdfs-site.xml当中修改以下配置属性,即可更改文件的副本数
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
**通常 DataNode 从磁盘中读取块,但对于访问频繁的文件,其对应的块可能被显示的缓存在 DataNode 的内存中,以堆外块缓存的形式存在。**默认情况下,一个块仅缓存在一个DataNode的内存中,当然可以针对每个文件配置DataNode的数量。作业调度器通过在缓存块的DataNode上运行任务,可以利用块缓存的优势提高读操作的性能。
例如:
连接(join)操作中使用的一个小的查询表就是块缓存的一个很好的候选。用户或应用通过在缓存池中增加一个cache directive来告诉namenode需要缓存哪些文件及存多久。缓存池(cache pool)是一个拥有管理缓存权限和资源使用的管理性分组。
例如:
一个文件 130M,会被切分成2个block块,保存在两个block块里面,实际占用磁盘130M空间,而不是占用256M的磁盘空间
hdfs的文件权限机制与linux系统的文件权限机制类似!!
r:read w:write x:execute 权限x对于文件表示忽略,对于文件夹表示是否有权限访问其内容。
如果linux系统用户zhangsan使用hadoop命令创建一个文件,那么这个文件在HDFS当中的owner就是zhangsan
HDFS文件权限的目的,防止好人做错事,而不是阻止坏人做坏事。HDFS相信你告诉我你是谁,你就是谁!!
vim hdfs-site.xml
#添加如下属性
<property>
<name>dfs.permissions</name>
<value>true</value>
</property>
修改完成之后要分发到其它节点,同时要重启HDFS集群
基于HDFS权限本身比较鸡肋的特点,我们可以彻底放弃HDFS的权限校验,如果生产环境中我们可以考虑借助kerberos以及sentry等安全框架来管理大数据集群安全。所以我们直接修改HDFS的根目录权限为777
hadoop fs -chmod -R 777 /
计算机中存储数据两种:内存或者是磁盘
元数据存储磁盘:存储磁盘无法面对客户端对元数据信息的任意的快速低延迟的响应,但是安全性高
元数据存储内存:元数据存放内存,可以高效的查询以及快速响应客户端的查询请求,数据保存在内存,如果断点,内存中的数据全部丢失。
如果存储在NameNode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然是效率过低。因此,元数据需要存放在内存中。但如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的FsImage。
这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦NameNode节点断电,就会产生数据丢失。因此,引入Edits文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据。
但是,如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode节点完成,又会效率过低。因此,引入一个新的节点SecondaryNamenode,专门用于FsImage和Edits的合并。
HDFS元数据管理:内存+磁盘;NameNode内存+FsImage的文件(磁盘)
![图片.png](https://img-blog.csdnimg.cn/img_convert/f47405b51c6088096ba847e4e930c9ee.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=775&id=u0edbfa37&margin=[object Object]&name=图片.png&originHeight=775&originWidth=1706&originalType=binary&ratio=1&rotation=0&showTitle=false&size=187803&status=done&style=none&taskId=u16250927-d5c3-4eec-8afc-11b59bedc1f&title=&width=1706)
Fsimage:NameNode内存中元数据序列化后形成的文件。
Edits:记录客户端更新元数据信息的每一步操作(可通过Edits运算出元数据)。
NameNode启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载Edits和Fsimage到内存中,此时NameNode内存就持有最新的元数据信息。Client开始对NameNode发送元数据的增删改的请求,这些请求的操作首先会被记录到edits.inprogress中(查询元数据的操作不会被记录在Edits中,因为查询操作不会更改元数据信息),如果此时NameNode挂掉,重启后会从Edits中读取元数据的信息。然后,NameNode会在内存中执行元数据的增删改的操作。
由于Edits中记录的操作会越来越多,Edits文件会越来越大,导致NameNode在启动加载Edits时会很慢,所以需要对Edits和Fsimage进行合并(所谓合并,就是将Edits和Fsimage加载到内存中,照着Edits中的操作一步步执行,最终形成新的Fsimage)。SecondaryNameNode的作用就是帮助NameNode进行Edits和Fsimage的合并工作。
SecondaryNameNode首先会询问NameNode是否需要CheckPoint(触发CheckPoint需要满足两个条件中的任意一个,定时时间到和Edits中数据写满了)。直接带回NameNode是否检查结果。
SecondaryNameNode执行CheckPoint操作,首先会让NameNode滚动Edits并生成一个空的edits.inprogress,滚动Edits的目的是给Edits打个标记,以后所有新的操作都写入edits.inprogress,其他未合并的Edits和Fsimage会拷贝到SecondaryNameNode的本地,然后将拷贝的Edits和Fsimage加载到内存中进行合并,生成fsimage.chkpoint,然后将fsimage.chkpoint拷贝给NameNode,重命名为Fsimage后替换掉原来的Fsimage。NameNode在启动时就只需要加载之前未合并的Edits和Fsimage即可,因为合并过的Edits中的元数据信息已经被记录在Fsimage中。
NameNode在执行格式化之后,会在/opt/servers/hadoop-2.9.2/data/tmp/dfs/name/current
目录下产生如下文件
![图片.png](https://img-blog.csdnimg.cn/img_convert/b26d0a4af30bfa5cf4a27070f8d817c7.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=191&id=u876e2005&margin=[object Object]&name=图片.png&originHeight=191&originWidth=1190&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35151&status=done&style=none&taskId=ud9855242-c738-42e2-b1e4-8cbbf5f93b4&title=&width=1190)
官方地址
https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html
[root@node101 current]# hdfs
Usage: hdfs [--config confdir] [--loglevel loglevel] COMMAND
where COMMAND is one of:
oiv apply the offline fsimage viewer to an fsimage
基本语法
hdfs oiv -p 文件类型(xml) -i 镜像文件 -o 转换后文件输出路径
# 进入到fsimage所在文件夹
[root@node101 current]# pwd
/opt/servers/hadoop-2.9.2/data/tmp/dfs/name/current
# 将fsimage文件格式化成xml文件
[root@node101 current]# hdfs oiv -p XML -i fsimage_0000000000000005863 -o /opt/servers/fsimage.xml
22/07/27 21:08:11 INFO offlineImageViewer.FSImageHandler: Loading 4 strings
<?xml version="1.0"?>
<fsimage>
<version>
<layoutVersion>-63</layoutVersion>
<onDiskVersion>1</onDiskVersion>
<oivRevision>826afbeae31ca687bc2f8471dc841b66ed2c6704</oivRevision>
</version>
<NameSection>
<namespaceId>1393381414</namespaceId>
<genstampV1>1000</genstampV1>
<genstampV2>1024</genstampV2>
<genstampV1Limit>0</genstampV1Limit>
<lastAllocatedBlockId>1073741848</lastAllocatedBlockId>
<txid>265</txid>
</NameSection>
<INodeSection>
<inode>
<id>16398</id>
<type>DIRECTORY</type>
<name>history</name>
<mtime>1592376391028</mtime>
<permission>root:supergroup:0777</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16399</id>
<type>DIRECTORY</type>
<name>done_intermediate</name>
<mtime>1592375256896</mtime>
<permission>root:supergroup:1777</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16400</id>
<type>DIRECTORY</type>
<name>root</name>
<mtime>1592378079208</mtime>
<permission>root:supergroup:0777</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16413</id>
<type>FILE</type>
<name>job_1592375222804_0001-1592375231176-root-word+count-1592375281926-1-1-SUCCEEDED-default-1592375261492.jhist</name>
<replication>3</replication>
<mtime>1592375282039</mtime>
<atime>1592375281980</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>root:supergroup:0777</permission>
<blocks>
<block>
<id>1073741834</id>
<genstamp>1010</genstamp>
<numBytes>33584</numBytes>
</block>
</blocks>
<storagePolicyId>0</storagePolicyId>
</inode>
<inode>
<id>16414</id>
<type>FILE</type>
<name>job_1592375222804_0001_conf.xml</name>
<replication>3</replication>
<mtime>1592375282121</mtime>
<atime>1592375282053</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>root:supergroup:0777</permission>
<blocks>
<block>
<id>1073741835</id>
<genstamp>1011</genstamp>
<numBytes>196027</numBytes>
</block>
</blocks>
<storagePolicyId>0</storagePolicyId>
</inode>
<inode>
<id>16415</id>
<type>DIRECTORY</type>
<name>done</name>
<mtime>1592376776670</mtime>
<permission>root:supergroup:0777</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16427</id>
<type>DIRECTORY</type>
<name>logs</name>
<mtime>1592378009623</mtime>
<permission>root:root:0770</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16428</id>
<type>DIRECTORY</type>
<name>application_1592376944601_0001</name>
<mtime>1592378045481</mtime>
<permission>root:root:0770</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16430</id>
<type>DIRECTORY</type>
<name>wcoutput</name>
<mtime>1592378037463</mtime>
<permission>root:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16436</id>
<type>FILE</type>
<name>part-r-00000</name>
<replication>3</replication>
<mtime>1592378037264</mtime>
<atime>1592378037074</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>root:supergroup:0644</permission>
<blocks>
<block>
<id>1073741842</id>
<genstamp>1018</genstamp>
<numBytes>43</numBytes>
</block>
</blocks>
<storagePolicyId>0</storagePolicyId>
</inode>
<inode>
<id>16445</id>
<type>FILE</type>
<name>linux123_39919</name>
<replication>3</replication>
<mtime>1592378045469</mtime>
<atime>1592378045331</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>root:root:0640</permission>
<blocks>
<block>
<id>1073741848</id>
<genstamp>1024</genstamp>
<numBytes>56910</numBytes>
</block>
</blocks>
<storagePolicyId>0</storagePolicyId>
</inode>
<inode>
<id>16446</id>
<type>DIRECTORY</type>
<name>0617</name>
<mtime>1592387393490</mtime>
<permission>root:supergroup:0755</permission>
<nsquota>-1</nsquota>
<dsquota>-1</dsquota>
</inode>
<inode>
<id>16449</id>
<type>FILE</type>
<name>banzhang.txt</name>
<replication>1</replication>
<mtime>1592388309046</mtime>
<atime>1592388309026</atime>
<preferredBlockSize>134217728</preferredBlockSize>
<permission>root:supergroup:0644</permission>
<storagePolicyId>0</storagePolicyId>
</inode>
</INodeSection>
</fsimage>
![图片.png](https://img-blog.csdnimg.cn/img_convert/012f1ae2297ebd6c5e4a1826c02dda90.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=430&id=ube9358ec&margin=[object Object]&name=图片.png&originHeight=430&originWidth=807&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38597&status=done&style=none&taskId=ua8b1bc0d-8a57-4b67-bf66-9bf64e7f235&title=&width=807) 在内存元数据中是有记录块所对应的dn信息,但是fsimage中就剔除了这个信息;HDFS集群在启动的时候会加载image以及edits文件,block对应的dn信息都没有记录,集群启动时会有一个安全模式(safemode),安全模式就是为了让dn汇报自己当前所持有的block信息给nn来补全元数据。后续每隔一段时间dn都要汇报自己持有的block信息。
[root@node101 current]# hdfs
Usage: hdfs [--config confdir] [--loglevel loglevel] COMMAND
where COMMAND is one of:
oev apply the offline edits viewer to an edits file
基本语法
hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
# 进入到fsimage所在文件夹
[root@node101 current]# pwd
/opt/servers/hadoop-2.9.2/data/tmp/dfs/name/current
# 将fsimage文件格式化成xml文件
[root@node101 current]# hdfs oev -p XML -i edits_0000000000000000266-
0000000000000000267 -o /opt/servers/edits.xml
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
<EDITS_VERSION>-63</EDITS_VERSION>
<RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA>
<TXID>113</TXID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>114</TXID>
<SRC>/wcoutput/_SUCCESS</SRC>
<MODE>493</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>115</TXID>
<SRC>/wcoutput/part-r-00000</SRC>
<MODE>493</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>116</TXID>
<SRC>/wcoutput</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>117</TXID>
<SRC>/wcoutput/_SUCCESS</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>118</TXID>
<SRC>/wcoutput/part-r-00000</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_DELETE</OPCODE>
<DATA>
<TXID>119</TXID>
<LENGTH>0</LENGTH>
<PATH>/wcoutput/part-r-00000</PATH>
<TIMESTAMP>1592377324171</TIMESTAMP>
<RPC_CLIENTID></RPC_CLIENTID>
<RPC_CALLID>-2</RPC_CALLID>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>120</TXID>
<SRC>/</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>121</TXID>
<SRC>/tmp</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>122</TXID>
<SRC>/tmp/hadoop-yarn</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>123</TXID>
<SRC>/tmp/hadoop-yarn/staging</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>124</TXID>
<SRC>/tmp/hadoop-yarn/staging/history</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>125</TXID>
<SRC>/tmp/hadoop-yarn/staging/history/done</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
<RECORD>
<OPCODE>OP_SET_PERMISSIONS</OPCODE>
<DATA>
<TXID>126</TXID>
<SRC>/tmp/hadoop-yarn/staging/history/done/2020</SRC>
<MODE>511</MODE>
</DATA>
</RECORD>
</EDITS>
nn启动时需要加载fsimage文件以及那些没有被2nn进行合并的edits文件,nn如何判断哪些edits已经被合并了呢?
可以通过fsimage文件自身的编号来确定哪些已经被合并。
hdfs-default.xml文件中的设置
<!-- SecondaryNameNode每隔一小时执行一次 -->
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
<!-- 一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次 -->
<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 >
<!--fsimage文件存储的路径-->
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///opt/servers/hadoopDatas/namenodeDatas
</property>
<!-- edits文件存储的路径 -->
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///opt/servers/hadoopDatas/dfs/nn/edits
</property>
NameNode故障后,HDFS集群就无法正常工作,因为HDFS文件系统的元数据需要由NameNode来管理维护并与Client交互,如果元数据出现损坏和丢失同样会导致NameNode无法正常工作进而HDFS文件系统无法正常对外提供服务。
将2NN的元数据拷贝到NN的节点下
kill -9 NameNode的进程id
删除NameNode存储的元数据
拷贝SecondNameNode的元数据到原NameNode的数据存储目录
重新启动NameNode
此种方式会存在元数据的丢失。
搭建HDFS的HA(高可用)集群,解决NN的单点故障问题!!(借助Zookeeper实现HA,一个Active的NameNode,一个是Standby的NameNode)
NameNode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性
<property>
<name>dfs.namenode.name.dir</name>
<value>file://${hadoop.tmp.dir}/name1,file://${hadoop.tmp.dir}/name2</value>
</property>
![图片.png](https://img-blog.csdnimg.cn/img_convert/10e3e379311dd2be72f1f8a7d45a1828.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=405&id=u5422aa10&margin=[object Object]&name=图片.png&originHeight=405&originWidth=936&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46921&status=done&style=none&taskId=u7fb282e8-845a-4446-b33d-91c4d98dd6d&title=&width=936)
DataNode节点上的数据损坏了,却没有发现,是很危险的事情,解决数据完整性的方法:
![图片.png](https://img-blog.csdnimg.cn/img_convert/cc71c1ce25292b0b57ca2c87bd222f10.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=288&id=ua5516893&margin=[object Object]&name=图片.png&originHeight=288&originWidth=680&originalType=binary&ratio=1&rotation=0&showTitle=false&size=24943&status=done&style=none&taskId=ucf4f0b26-e6c3-4eb1-b3c3-49b2b0725df&title=&width=680)
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>
DataNode的目录结构和namenode不同的是,datanode的存储目录是初始阶段自动创建的,不需要额外格式化。
datanode也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本。具体配置如下:- 只需要在value中使用逗号分隔出多个存储目录即可
<!-- 定义dataNode数据存储的节点位置,实际工作中,一般先确定磁盘的挂载目录,然后多个目录用,进行分割 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///{hadoop_home}/hadoopDatas/datanodeDatas
</property>
需求说明:
随着公司业务的增长,数据量越来越大,原有的数据节点的容量已经不能满足存储数据的需求,需要在原有集群基础上动态添加新的数据节点。
cd /export/servers/hadoop-2.9.2/etc/hadoop/
scp ./* node04:$PWD
cd /opt/servers/hadoop-2.9.2/etc/hadoop/
vi dfs.hosts增加主机名称,包括新服役节点
node101
node102
node103
node104
node101执行以下命令 :
cd /opt/servers/hadoop-2.9.2/etc/hadoop
vim hdfs-site.xml
# 添加一下内容
<property>
<name>dfs.hosts</name>
<value>/opt/servers/hadoop-2.9.2/etc/hadoop/dfs.hosts</value>
</property>
<!--动态上下线配置: 如果配置文件中有, 就不需要配置-->
<property>
<name>dfs.hosts</name>
<value>/opt/servers/hadoop-2.9.2/etc/hadoop/accept_host</value>
</property>
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/servers/hadoop-2.9.2/etc/hadoop/deny_host</value>
</property>
[root@node101 hadoop]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
[root@node101 hadoop]# yarn rmadmin -refreshNodes
19/03/16 11:19:47 INFO client.RMProxy: Connecting to ResourceManager at node01/192.168.145.210:8033
# node101执行以下命令编辑slaves文件 :
cd /opt/servers/hadoop-2.9.2/etc/hadoop
vim slaves
# 添加一下内容:
node101
node102
node103
node104
# node104服务器执行以下命令,启动datanode和nodemanager :
cd /opt/servers/hadoop-2.9.2
sbin/hadoop-daemon.sh start datanode
sbin/yarn-daemon.sh start nodemanager
node101执行以下命令 :
cd /opt/servers/hadoop-2.9.2
sbin/start-balancer.sh
# node01执行以下命令 :
cd /opt/servers/hadoop-2.9.2/etc/hadoop
touch dfs.hosts.exclude
vim dfs.hosts.exclude
# 添加以下内容:
node104
# 特别注意:该文件当中一定要写真正的主机名或者ip地址都行
cd /opt/servers/hadoop-2.9.2/etc/hadoop
vim hdfs-site.xml
#添加一下内容:
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/servers/hadoop-2.9.2/etc/hadoop/dfs.hosts.exclude</value>
</property>
# 在namenode所在的机器执行以下命令,刷新namenode,刷新resourceManager :
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
# node104执行以下命令,停止该节点进程 :
cd /opt/servers/hadoop-2.9.2
sbin/hadoop-daemon.sh stop datanode
sbin/yarn-daemon.sh stop nodemanager
# namenode所在节点也就是node01执行以下命令删除退役节点 :
cd /opt/servers/hadoop-2.9.2/etc/hadoop
vim dfs.hosts
# 删除后的内容: 删除了node104
node101
node102
node103
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
# namenode所在机器也就是node01执行以下命令从slaves文件中删除退役节点 :
cd /opt/servers/hadoop-2.9.2/etc/hadoop
vim slaves
删除后的内容: 删除了 node104
node101
node102
node103
node101执行以下命令进行均衡负载
cd /opt/servers/hadoop-2.9.2/etc/hadoop
sbin/start-balancer.sh
所有的数据都是以一个个的block块存储的,只要我们能够将文件的所有block块全部找出来,拼接到一起,又会成为一个完整的文件,接下来我们就来通过命令将文件进行拼接:
![图片.png](https://img-blog.csdnimg.cn/img_convert/ff4d9db9051f02129d5acce7e016fb82.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=861&id=u55ff00b2&margin=[object Object]&name=图片.png&originHeight=861&originWidth=1710&originalType=binary&ratio=1&rotation=0&showTitle=false&size=618490&status=done&style=none&taskId=u7f7e5d53-4e7c-4321-9f71-e770a60a65c&title=&width=1710)![图片.png](https://img-blog.csdnimg.cn/img_convert/35aba36007b063ff55bce27853a870d3.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=266&id=u38e44c8a&margin=[object Object]&name=图片.png&originHeight=266&originWidth=774&originalType=binary&ratio=1&rotation=0&showTitle=false&size=130513&status=done&style=none&taskId=uad60aee1-9b3d-4d22-9cf2-2aa1d174114&title=&width=774)![图片.png](https://img-blog.csdnimg.cn/img_convert/e75131630628819d403e3feae97cc36a.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=287&id=u69ba26a0&margin=[object Object]&name=图片.png&originHeight=287&originWidth=791&originalType=binary&ratio=1&rotation=0&showTitle=false&size=126026&status=done&style=none&taskId=ud646bd78-6611-4964-8049-cdd82c5504d&title=&width=791)
# 根据我们hdfs-site.xml的配置,找到datanode所在的路径
<!-- 定义dataNode数据存储的节点位置,实际工作中,一般先确定磁盘的挂载目录,然后多个目录用,进行分割 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:////opt/servers/hadoop-2.9.2/hadoopDatas/datanodeDatas
</property>
# 进入到以下路径 : 此基础路径为 上述配置中value的路径
cd /opt/servers/hadoop-2.9.2/hadoopDatas/datanodeDatas/current/BP-557466926-1549868683602/current/finalized/subdir0/subdir3
将不同的各个block块按照顺序进行拼接起来,成为一个完整的文件
cat blk_1073742279 >> spark.tar.gz
cat blk_1073742280 >> spark.tar.gz
移动我们的jdk到/opt路径,然后进行解压
mv spark.tar.gz /opt/
cd /opt/
tar -zxf spark.tar.gz
正常解压,没有问题,说明我们的程序按照block块存储没有问题
在我们实际工作当中,极有可能会遇到将测试集群的数据拷贝到生产环境集群,或者将生产环境集群的数据拷贝到测试集群,那么就需要我们在多个集群之间进行数据的远程拷贝,hadoop自带也有命令可以帮我们实现这个功能
本地文件拷贝scp
cd /opt/softwares/
scp -r jdk-8u141-linux-x64.tar.gz root@node102:/opt/
集群之间的数据拷贝distcp
cd /opt/servers/hadoop-2.9.2/
bin/hadoop distcp hdfs://node101:9000/jdk-8u141-linux-x64.tar.gz hdfs://cluster2:9000/
主要解决HDFS集群存在大量小文件的问题!!
由于大量小文件会占用NameNode的内存,因此对于HDFS来说存储大量小文件造成NameNode内存资源的浪费!
Hadoop存档文件HAR文件,是一个更高效的文件存档工具,HAR文件是由一组文件通过archive工具创建而来,在减少了NameNode的内存使用的同时,可以对文件进行透明的访问,通俗来说就是HAR文件对NameNode来说是一个文件减少了内存的浪费,对于实际操作处理文件依然是一个一个独立的文件。
![图片.png](https://img-blog.csdnimg.cn/img_convert/030975241c878b80d371e3aacff99145.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=98&id=u30503f8d&margin=[object Object]&name=图片.png&originHeight=98&originWidth=796&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13166&status=done&style=none&taskId=uc374f9f9-2f30-40f1-9cf2-53ca914a136&title=&width=796)
把/user/input目录里面的所有文件归档成一个叫input.har的归档文件,并把归档后文件存储到/user/output路径下。
[root@node101 hadoop-2.9.2]$ bin/hadoop archive -archiveName input.har –p
/user/input /user/output
[root@node101 hadoop-2.9.2]$ hadoop fs -lsr /user/output/input.har
[root@node101 hadoop-2.9.2]$ hadoop fs -lsr har:///user/output/input.har
[root@node101 hadoop-2.9.2]$ hadoop fs -cp har:///user/output/input.har/* /user/har
快照顾名思义,就是相当于对我们的hdfs文件系统做一个备份,我们可以通过快照对我们指定的文件夹设置备份,但是添加快照之后,并不会立即复制所有文件,而是指向同一个文件。当写入发生时,才会产生新文件。
1、 开启指定目录的快照功能
hdfs dfsadmin -allowSnapshot 路径
2、禁用指定目录的快照功能(默认就是禁用状态)
hdfs dfsadmin -disallowSnapshot 路径
3、给某个路径创建快照snapshot
hdfs dfs -createSnapshot 路径
4、指定快照名称进行创建快照snapshot
hdfs dfs -createSanpshot 路径 名称
5、给快照重新命名
hdfs dfs -renameSnapshot 路径 旧名称 新名称
6、列出当前用户所有可快照目录
hdfs lsSnapshottableDir
7、比较两个快照的目录不同之处
hdfs snapshotDiff 路径1 路径2
8、删除快照snapshot
hdfs dfs -deleteSnapshot <path> <snapshotName>
1、开启与禁用指定目录的快照
[root@node101 hadoop-2.9.2]# hdfs dfsadmin -allowSnapshot /user
Allowing snaphot on /user succeeded
[root@node101 hadoop-2.9.2]# hdfs dfsadmin -disallowSnapshot /user
Disallowing snaphot on /user succeeded
2、对指定目录创建快照
注意:创建快照之前,先要允许该目录创建快照
[root@node101 hadoop-2.9.2]# hdfs dfsadmin -allowSnapshot /user
Allowing snaphot on /user succeeded
[root@node101 hadoop-2.9.2]# hdfs dfs -createSnapshot /user
Created snapshot /user/.snapshot/s20190317-210906.549
通过web浏览器访问快照
http://node101:50070/explorer.html#/user/.snapshot/s20190317-210906.549
3、指定名称创建快照
[root@node101 hadoop-2.9.2]# hdfs dfs -createSnapshot /user mysnap1
Created snapshot /user/.snapshot/mysnap1
4、重命名快照
hdfs dfs -renameSnapshot /user mysnap1 mysnap2
5、列出当前用户所有可以快照的目录
hdfs lsSnapshottableDir
6、比较两个快照不同之处
hdfs dfs -createSnapshot /user snap1
hdfs dfs -createSnapshot /user snap2
hdfs snapshotDiff snap1 snap2
7、删除快照
hdfs dfs -deleteSnapshot /user snap1
任何一个文件系统,基本上都会有垃圾桶机制,也就是删除的文件,不会直接彻底清掉,我们一把都是将文件放置到垃圾桶当中去,过一段时间之后,自动清空垃圾桶当中的文件,这样对于文件的安全删除比较有保证,避免我们一些误操作,导致误删除文件或者数据。
默认值fs.trash.interval=0,0表示禁用回收站,可以设置删除文件的存活时间。
默认值fs.trash.checkpoint.interval=0,检查回收站的间隔时间。
要求fs.trash.checkpoint.interval<=fs.trash.interval。
修改所有服务器的core-site.xml配置文件
<!-- 开启hdfs的垃圾桶机制,删除掉的数据可以从垃圾桶中回收,单位分钟 -->
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
回收站在集群的 /user/root/.Trash/ 这个路径下
//使用回收站的方式: 删除数据
@Test
public void deleteFile() throws Exception{
//1. 获取FileSystem对象
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node101:9000"), configuration, "root");
//2. 执行删除操作
// fileSystem.delete(); 这种操作会直接将数据删除, 不会进入垃圾桶
Trash trash = new Trash(fileSystem,configuration);
boolean flag = trash.isEnabled(); // 是否已经开启了垃圾桶机制
System.out.println(flag);
trash.moveToTrash(new Path("/quota"));
//3. 释放资源
fileSystem.close();
}
hdfs dfs -mv trashFileDir hdfsdir
trashFileDir :回收站的文件路径
hdfsdir :将文件移动到hdfs的哪个路径下
hdfs dfs -expunge
![图片.png](https://img-blog.csdnimg.cn/img_convert/1660fed03842903e0b6dc88319b46583.png#clientId=ue959e38b-648b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=656&id=ue2e27849&margin=[object Object]&name=图片.png&originHeight=656&originWidth=891&originalType=binary&ratio=1&rotation=0&showTitle=false&size=25306&status=done&style=none&taskId=u50a46b08-a1d5-4925-ae33-65842380489&title=&width=891)
LOGS.DIR=e:/logs/
LOG.PREFIX=access.log.
LOG.TMP.FOLDER=e:/log_tmp/
HDFS.TARGET.FOLDER=/collect_log/
BAK.FOLDER=e:/log_bak/
package com.hadoop.hdfs;
public class Constant {
public static final String LOGS_DIR="LOGS.DIR";
public static final String LOG_PREFIX="LOG.PREFIX";
public static final String LOG_TMP_FOLDER="LOG.TMP.FOLDER";
public static final String HDFS_TARGET_FOLDER="HDFS.TARGET.FOLDER";
public static final String BAK_FOLDER="BAK.FOLDER";
}
package com.hadoop.hdfs;
import java.io.IOException;
import java.util.Properties;
public class PropTool {
//volatile关键字禁止指令重排序,保证可见性可有序性,不保证原子性
private static volatile Properties prop = null;
public static Properties getProp() throws IOException {
if(prop==null){
synchronized ("lock"){
if(prop==null){
prop = new Properties();
prop.load(LogCollectorTask.class.getClassLoader().getResourceAsStream("collector.properties"));
}
}
}
return prop;
}
}
package com.hadoop.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.TimerTask;
public class LogCollectorTask extends TimerTask {
@Override
public void run() {
Properties prop = null;
try {
prop = PropTool.getProp();
} catch (IOException e) {
e.printStackTrace();
}
//采集业务逻辑
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String todayStr = dateFormat.format(new Date());
//1. 扫描指定目录,找到待上传文件,原始日志目录
File logsDir = new File(prop.getProperty(Constant.LOGS_DIR));
final String log_prefix = prop.getProperty(Constant.LOG_PREFIX);
File[] uploadFiles = logsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.startsWith(log_prefix);
}
});
// 2.把待上传文件转移到临时目录
//判断文件是否存在
File tmpFile = new File(prop.getProperty(Constant.LOG_TMP_FOLDER));
if(!tmpFile.exists()){
tmpFile.mkdirs();
}
for (File uploadFile : uploadFiles) {
uploadFile.renameTo(new File(tmpFile.getPath() + "/" + uploadFile.getName()));
}
//3.使用hdfs api上传日志文件 到指定目录
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS","hdfs://node101:9000");
FileSystem fs = null;
try {
fs = FileSystem.get(configuration);
//判断hdfs目标路径是否存在,备份目录是否存在
Path path = new Path(prop.getProperty(Constant.HDFS_TARGET_FOLDER) + todayStr);
if(!fs.exists(path)){}
fs.mkdirs(path);
File bakFolder = new File(prop.getProperty(Constant.BAK_FOLDER) + todayStr);
if(!bakFolder.exists()){
bakFolder.mkdirs();
}
File[] files = tmpFile.listFiles();
for (File file : files) {
//按照日期存放
fs.copyFromLocalFile(new Path(file.getPath()), new Path(prop.getProperty(Constant.HDFS_TARGET_FOLDER)
+ todayStr + "/" + file.getName()));
//4.上传后的文件转移到备份目录
file.renameTo(new File(bakFolder.getPath()+"/"+file.getName()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.hadoop.hdfs;
import java.util.Timer;
public class LogTimerUpload {
/*
- 定时采集已滚动完毕日志文件
- 将待采集文件上传到临时目录
- 备份日志文件
*/
public static void main(String[] args) {
// LogCollectorTask logLoad = new LogCollectorTask();
// logLoad.run();
//
Timer timer = new Timer();
//定时采集任务的调度
// task:采集的业务逻辑
//延迟时间
//周期时间
timer.schedule(new LogCollectorTask(),0,3600*1000);
}
}
参数 | 含义 | 默认值 | 推荐值 |
---|---|---|---|
dfs.blocksize | 块大小 | 2.X版本128M | 根据磁盘读取速度设置,寻址时间最好在读取时间的1% |
fs.trash.interval | 开启HDFS垃圾桶机制,删除掉的数据可以从垃圾桶中回收 单位为分钟 | ||
dfs.name.dir | NameNode 元数据存放位置 | 使用core-site.xml中的hadoop.tmp.dir/dfs/name | |
dfs.data.dir | DataNode在本地磁盘存放block的位置,可以是以逗号分隔的目录列表,DataNode循环向磁盘中写入数据,每个DataNode可单独指定与其它DataNode不一样 | ${hadoop.tmp.dir}/dfs/data | |
dfs.namenode.handler.count | NameNode用来处理来自DataNode的RPC请求的线程数量 | 10 | 建议设置为DataNode数量的10%,一般在10~200个之间 |
| dfs.datanode.handler.count | DataNode用来连接NameNode的RPC请求的线程数量,在DataNode上设定 | 3 | 取决于系统的繁忙程度
设置太小会导致性能下降甚至报错 |
| dfs.permissions | 如果是true则检查权限,否则不检查(每一个人都可以存取文件) ,于NameNode上设定 | true | true |
| dfs.replication | 在文件被写入的时候,每一块将要被复制多少份 | 3 | |
| hadoop.tmp.dir | HDFS与本地磁盘的临时文件 | /tmp/hadoop-${user.name} | |
| io.file.buffer.size | 设定在读写数据时的缓存大小,应该为硬件分页大小的2倍 | 默认是4096 | 建议为65536 ( 64K) |
参数 | 描述 | 默认 | 配置文件 | 例子值 |
---|---|---|---|---|
fs.default.name namenode | namenode RPC交互端口 | 8020/9000 | core-site.xml | hdfs://master:8020/ |
dfs.http.address | NameNode web管理端口 | 50070 | hdfs- site.xml | 0.0.0.0:50070 |
dfs.datanode.address | datanode 控制端口 | 50010 | hdfs -site.xml | 0.0.0.0:50010 |
dfs.datanode.ipc.address | datanode的RPC服务器地址和端口 | 50020 | hdfs-site.xml | 0.0.0.0:50020 |
dfs.datanode.http.address | datanode的HTTP服务器和端口 | 50075 | hdfs-site.xml | 0.0.0.0:50075 |