第 1 章 HDFS 概述 1.1 HDFS 产出背景及定义 1.2 HDFS 优缺点 1.3 HDFS 组成架构 1.4 HDFS 文件块大小 (面试重点) 第 2 章 HDFS 的 Shell 操作 (开发重点) 第 3 章 HDFS 客户端操作(开发重点)3.1 HDFS 客户端环境准备 3.2 HDFS 的 API 操作 3.2.1 HDFS 文件上传(测试参数优先级)3.2.2 HDFS 文件下载 3.2.3 HDFS 文件夹删除 3.2.4 HDFS 文件名更改 3.2.5 HDFS 文件详情查看 3.2.6 HDFS 文件和文件夹判断 3.3 HDFS 的 I/O 流操作(自定义框架使用)3.3.1 HDFS 文件上传 3.3.2 HDFS 文件下载 3.3.3 定位文件读取第 4 章 HDFS 的数据流(面试重点)4.1 HDFS 写数据流程 4.1.1 剖析文件写入 4.1.2 网络拓扑 - 节点距离计算 4.1.3 机架感知(副本存储节点选择)4.2 HDFS 读数据流程第 5 章 NameNode 和 SecondaryNameNode(面试开发重点)5.1 NN 和 2NN 工作机制 5.2 Fsimage 和 Edits 解析 5.3 CheckPoint 时间设置 5.4 NameNode 故障处理(开发重点: 偏运维)5.5 集群安全模式 5.6 NameNode 多目录配置
第 1 章 HDFS 概述
1.1 HDFS 产出背景及定义
其他文件管理系统:
1.2 HDFS 优缺点
优点
缺点
1.3 HDFS 组成架构
1)NameNode(nn)和 DataNode(dn)
2)Client 和 Secondary NameNode(2nn)
1.4 HDFS 文件块大小(面试重点)
思考: 为什么块的大小不能设置太小, 也不能设置太大?
传统硬盘 HDD(Hard Disk Drive)传输速率: 100MB/s
固态硬盘 SSD(Solid State Drive)传输速率: 500MB/s
混合硬盘 HHD(Hybrid Harddrive)传输速率: 300MB/s
PCIe 固态硬盘 SSD(Solid State Drive)传输速率: 1500MB/s
第 2 章 HDFS 的 Shell 操作(开发重点)
1, 基本语法
bin/hadoop fs 具体命令 OR bin/hdfs dfs 具体命令
dfs 是 fs 的实现类.
2, 命令大全
- [[atguigu@hadoop102 hadoop-2.7.2]$ bin/hadoop fs
- 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] <localsrc> ... <dst>]
- [-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
- [-count [-q] [-h] <path> ...]
- [-cp [-f] [-p | -p[topax]] <src> ... <dst>]
- [-createSnapshot <snapshotDir> [<snapshotName>]]
- [-deleteSnapshot <snapshotDir> <snapshotName>]
- [-df [-h] [<path> ...]]
- [-du [-s] [-h] <path> ...]
- [-expunge]
- [-find <path> ... <expression> ...]
- [-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
- [-getfacl [-R] <path>]
- [-getfattr [-R] {-n name | -d} [-e en] <path>]
- [-getmerge [-nl] <src> <localdst>]
- [-help [cmd ...]]
- [-ls [-d] [-h] [-R] [<path> ...]]
- [-mkdir [-p] <path> ...]
- [-moveFromLocal <localsrc> ... <dst>]
- [-moveToLocal <src> <localdst>]
- [-mv <src> ... <dst>]
- [-put [-f] [-p] [-l] <localsrc> ... <dst>]
- [-renameSnapshot <snapshotDir> <oldName> <newName>]
- [-rm [-f] [-r|-R] [-skipTrash] <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> use value for given property
- -fs <local|namenode:port> specify a namenode
- -jt <local|resourcemanager:port> specify a ResourceManager
- -files <comma separated list of files> specify comma separated files to be copied to the map reduce cluster
- -libjars <comma separated list of jars> specify comma separated jar files to include in the classpath.
- -archives <comma separated list of archives> specify comma separated archives to be unarchived on the compute machines.
- The general command line syntax is
- bin/hadoop command [genericOptions] [commandOptions]
- [atguigu@hadoop102 hadoop-2.7.2]$
3.常用命令实操
(0)启动 Hadoop 集群(方便后续的测试)
- [atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh
- [atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
(1)-help: 输出这个命令参数
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -help rm
(2)-ls: 显示目录信息
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -ls /
(3)-mkdir: 在 HDFS 上创建目录
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir -p /sanguo/shuguo/
(4)-moveFromLocal: 从本地系统中剪切粘贴文件到 HDFS 上(本地系统中不存在该文件)
- [atguigu@hadoop102 hadoop-2.7.2]$ touch kongming.txt
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -moveFromLocal ./kongming.txt /sanguo/shuguo/
(5)-appendToFile: 追加一个文件到已经存在的文件末尾
- [atguigu@hadoop102 hadoop-2.7.2]$ touch liubei.txt
- [atguigu@hadoop102 hadoop-2.7.2]$ VIM liubei.txt
输入
- san gu mao lu
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt
(6)-cat: 显示文件内容
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cat /sanguo/shuguo/kongming.txt
(7)-chgrp ,-chmod,-chown: 跟 Linux 文件系统中的用法一样, 修改文件所属权限
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chmod 666 /sanguo/shuguo/kongming.txt
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chown atguigu:atguigu /sanguo/shuguo/kongming.txt
(8)-copyFromLocal: 从本地文件系统中拷贝文件到 HDFS 路径中去(本地系统中还存在该文件)
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyFromLocal README.txt /
(9)-copyToLocal: 从 HDFS 拷贝到本地系统中
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyToLocal /sanguo/shuguo/kongming.txt ./
(10)-cp: 从 HDFS 的一个路径拷贝到 HDFS 的另一个路径(文件还在旧的 HDFS 中)
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt
(11)-mv: 在 HDFS 目录中移动文件(文件不在旧的 HDFS 中, 在新的 HDFS 中)
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mv /zhuge.txt /sanguo/shuguo/
(12)-get: 等同于 copyToLocal, 就是从 HDFS 下载文件到本地系统中
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -get /sanguo/shuguo/kongming.txt ./
(13)-getmerge: 合并下载多个文件, 比如 HDFS 的目录 /user/atguigu/test/ 下有多个文件: log.1,log.2,log.3,......
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -getmerge /sanguo/shuguo/* ./zaiyiqi.txt
- (14)-put: 等同于 copyFromLocal, 就是从本地文件系统中拷贝文件到 HDFS 路径中去
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -put ./zaiyiqi.txt /sanguo/shuguo/
- (15)-tail: 显示一个文件的末尾几行(因为日志文件一般是在文件的末尾不断地追加, 即监控新产生的数据变化)
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -tail /sanguo/shuguo/kongming.txt
- (16)-rm: 删除文件或文件夹
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rm /sanguo/shuguo/zaiyiqi.txt
- (17)-rmdir: 删除空目录
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir /test
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rmdir /test
- (18)-du: 统计文件夹的大小信息
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -s -h /user/atguigu/test/
- 2.7 K /user/atguigu/test
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -h /user/atguigu/test/
- 1.3 K /user/atguigu/test/README.txt
- 1.4 K /user/atguigu/test/zaiyiqi.txt
- (19)-setrep: 设置 HDFS 中文件的副本数量
- [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -setrep 10 /kongming.txt
- HDFS 副本数量
- 这里设置的副本数只是记录在 NameNode 的元数据中, 是否真的会有这么多副本, 还得看 DataNode 的数量. 因为目前只有 3 台设备, 最多也就 3 个副本, 只有节点数的增加到 10 台时, 副本数才能达到 10.
- 第 3 章 HDFS 客户端操作(开发重点)
- 3.1 HDFS 客户端环境准备
- 1, 根据自己电脑的操作系统拷贝对应的编译后的 hadoop jar 包到非中文路径(例如: D:\Develop\hadoop-2.7.2), 如下图所示.
- 2, 配置 HADOOP_HOME 环境变量, 如下图所示:
- 3, 配置 Path 环境变量, 如下图所示:
- 4, 创建一个 Maven 工程 HdfsClientDemo
- 5, 导入相应的依赖坐标 + 日志添加
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.8.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-common</artifactId>
- <version>2.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-client</artifactId>
- <version>2.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-hdfs</artifactId>
- <version>2.7.2</version>
- </dependency>
- <dependency>
- <groupId>jdk.tools</groupId>
- <artifactId>jdk.tools</artifactId>
- <version>1.8</version>
- <scope>system</scope>
- <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
- </dependency>
- </dependencies>
- 注意: 如果 Eclipse/Idea 打印不出日志, 在控制台上只显示
- log4j:WARN No appenders could be found for logger (org.apache.hadoop.util.Shell).
- log4j:WARN Please initialize the log4j system properly.
- log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
- 需要在项目的 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
- 6, 创建包名: com.atguigu.hdfs
- 7, 创建 HdfsClient 类
- public class HdfsClient {
- /**
- * 测试创建多级文件夹: 在 hdfs 系统上创建多级文件夹
- */
- @Test
- public void testMkdirs() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- // 配置在集群上运行
- configuration.set("fs.defaultFS", "hdfs://hadoop102:9000");
- FileSystem fs = FileSystem.get(configuration);
- // 2 , 创建目录
- fs.mkdirs(new Path("/0529/dashen"));
- // 3 , 关闭资源
- fs.close();
- }
- }
- 8, 执行程序
- 运行时需要配置用户名称, 右键 -> Run Configurations, 如下图所示:
- 客户端去操作 HDFS 时, 是有一个用户身份的. 默认情况下, HDFS 客户端 API 会从 JVM 中获取一个参数来作为自己的用户身份:-DHADOOP_USER_NAME=atguigu,atguigu 为用户名称.
- 9, 另一种[配置在集群上运行] 的方式, 可以不用手动配置用户名称
- public class HdfsClient {
- /**
- * 测试创建多级文件夹: 在 hdfs 系统上创建多级文件夹
- */
- @Test
- public void testMkdirs() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- // 配置在集群上运行
- // configuration.set("fs.defaultFS", "hdfs://hadoop102:9000");
- // FileSystem fs = FileSystem.get(configuration);
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2 , 创建目录
- fs.mkdirs(new Path("/0529/dashen"));
- // 3 , 关闭资源
- fs.close();
- }
- }
- 3.2 HDFS 的 API 操作
- 3.2.1 HDFS 文件上传(测试参数优先级)
- 1, 编写源代码
- /**
- * 测试文件上传: 从本地系统上传文件至 hdfs 文件系统上
- */
- @Test
- public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- configuration.set("dfs.replication", "2");
- // 2, 本地系统执行上传文件操作
- fs.copyFromLocalFile(new Path("D:/temp/atguigu/0529/banzhang.txt"), new Path("/banzhang.txt"));
- // 3, 关闭资源
- fs.close();
- }
- 2, 在 / HdfsClientDemo/src/main/resources / 目录下新建 hdfs-site.xml 文件, 文件内容如下, 然后再次执行上传文件操作
- <?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>
- 3.参数优先级
- 参数优先级排序:(1)客户端代码中设置的值>(2)ClassPath 下的用户自定义配置文件设置的值>(3)hdfs 服务器的默认配置的值
- 效果如下图所示:
- 3.2.2 HDFS 文件下载
- 示例代码如下:
- /**
- * 测试文件下载: 将 hdfs 文件系统上的文件下载到本地系统上
- */
- @Test
- public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统对象
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 执行下载文件操作
- // fs.copyToLocalFile(new Path("/banhua.txt"), new Path("D:/temp/atguigu/0529/banhua.txt"));
- // boolean delSrc 指是否将源文件删除, 默认值是 false, 表示不删除源文件
- // Path src 指要下载的文件路径
- // Path dst 指将文件下载到的路径
- // boolean useRawLocalFileSystem 是否开启文件校验, 即是否生成 .xxx.crc 检验文件, 默认值是 false, 表示生成检验文件
- fs.copyToLocalFile(false, new Path("/bancao.txt"), new Path("D:/temp/atguigu/0529/bancao.txt"), true);
- // 3, 关闭资源
- fs.close();
- }
- 3.2.3 HDFS 文件夹删除
- 示例代码如下:
- /**
- * 测试 [文件夹 / 文件] 删除: 将 hdfs 文件系统上的 [文件夹 / 文件] 删除
- */
- @Test
- public void testDelete() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统对象
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 执行删除文件操作
- // boolean recursive 指的是递归的意思, 设置成 true, 表示递归删除文件夹
- fs.delete(new Path("/0529/"), true);
- // 3, 关闭资源
- fs.close();
- }
- 3.2.4 HDFS 文件名更改
- 示例代码如下:
- /**
- * 文件名更改: 将 hdfs 文件系统上的文件更改名称
- */
- @Test
- public void testRename() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统对象
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 执行文件名更改操作
- fs.rename(new Path("/banzhang.txt"), new Path("/yanjing.txt"));
- // 3, 关闭资源
- fs.close();
- }
- 3.2.5 HDFS 文件详情查看
- 查看文件名称, 权限, 长度, 块信息
- 示例代码如下:
- /**
- * 查看文件详情
- */
- @Test
- public void testListFiles() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统对象
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 获取文件详情
- RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
- while (listFiles.hasNext()) {
- LocatedFileStatus fileStatus = listFiles.next();
- // 输出详情
- System.out.println(fileStatus.getPath().getName()); // 文件名称
- System.out.println(fileStatus.getPermission()); // 权限
- System.out.println(fileStatus.getLen()); // 长度
- System.out.println(fileStatus.getGroup()); // 分组
- // 获取存储的块信息
- BlockLocation[] blockLocations = fileStatus.getBlockLocations();
- for (BlockLocation blockLocation : blockLocations) {
- // 获取块存储的主机节点
- String[] hosts = blockLocation.getHosts();
- for (String host : hosts) {
- System.out.println(host);
- }
- }
- System.out.println("---------------------");
- }
- // 3, 关闭资源
- fs.close();
- }
- 3.2.6 HDFS 文件和文件夹判断
- 示例代码如下:
- /**
- * 判断是文件还是文件夹
- */
- @Test
- public void testListStatus() throws IOException, InterruptedException, URISyntaxException {
- Configuration configuration = new Configuration();
- // 1, 获取 hdfs 文件系统对象
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 判断是文件还是文件夹
- FileStatus[] listStatus = fs.listStatus(new Path("/"));
- for (FileStatus fileStatus : listStatus) {
- // 如果是文件
- if (fileStatus.isFile()) {
- System.out.println("f:" + fileStatus.getPath().getName());
- } else {
- System.out.println("d:" + fileStatus.getPath().getName());
- }
- }
- // 3, 关闭资源
- fs.close();
- }
- 3.3 HDFS 的 I/O 流操作(自定义框架使用)
- 上面我们学的 API 操作 HDFS 系统都是框架封装好的. 那么如果我们想自己实现上述 API 的操作该怎么实现呢?
- 我们可以采用 IO 流的方式实现数据的上传和下载.
- 3.3.1 HDFS 文件上传
- 1, 需求: 把本地 D:\temp\atguigu\0529 \ 上的 banhua.txt 文件上传到 HDFS 根目录
- 2, 编写代码
- /**
- * 把本地 D:\temp\atguigu\0529\ 上的 banhua.txt 文件上传到 HDFS 根目录
- */
- @Test
- public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 创建输入流
- FileInputStream fis = new FileInputStream(new File("D:/temp/atguigu/0529/banhua.txt"));
- // 3, 创建输出流
- FSDataOutputStream fos = fs.create(new Path("/banzhang.txt"));
- // 4, 流对拷
- IOUtils.copyBytes(fis, fos, configuration);
- // 5, 关闭资源
- IOUtils.closeStream(fos);
- IOUtils.closeStream(fis);
- fs.close();
- }
- 3.3.2 HDFS 文件下载
- 1, 需求: 从 HDFS 上下载 banhua.txt 文件到本地 D:\temp\atguigu\0529 \ 上
- 2, 编写代码
- * 从 HDFS 上下载 banhua.txt 文件到本地 D:\temp\atguigu\0529\ 上
- */
- @Test
- public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 创建输入流
- FSDataInputStream fis = fs.open(new Path("/banhua.txt"));
- // 3, 创建输出流
- FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/banhua.txt"));
- // 4, 流对拷
- IOUtils.copyBytes(fis, fos, configuration);
- // 5, 关闭资源
- IOUtils.closeStream(fos);
- IOUtils.closeStream(fis);
- fs.close();
- }
3.3.3 定位文件读取
1, 需求: 分块读取 HDFS 上的大文件, 比如根目录下的 / hadoop-2.7.2.tar.gz
2, 编写代码
(1)下载第一块
- /**
- * 分块读取 HDFS 上的大文件, 比如根目录下的 / hadoop-2.7.2.tar.gz, 下载第一块
- */
- @Test
- public void readFileSeek1() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 获取输入流
- FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
- // 3, 创建输出流
- FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/hadoop-2.7.2.tar.gz.part1"));
- // 4, 流的对拷
- byte[] buf = new byte[1024];
- for (int i = 0; i < 1024 * 128; i++) {
- fis.read(buf);
- fos.write(buf);
- }
- // 5, 关闭资源
- IOUtils.closeStream(fis);
- IOUtils.closeStream(fos);
- fs.close();
- }
(2)下载第二块
- /**
- * 分块读取 HDFS 上的大文件, 比如根目录下的 / hadoop-2.7.2.tar.gz, 下载第二块
- */
- @Test
- public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException {
- // 1, 获取 hdfs 文件系统对象
- Configuration configuration = new Configuration();
- FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
- // 2, 获取输入流
- FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
- // 3, 定位输入数据位置
- fis.seek(1024*1024*128);
- // 4, 创建输出流
- FileOutputStream fos = new FileOutputStream(new File("D:/temp/atguigu/0529/hadoop-2.7.2.tar.gz.part2"));
- // 5, 流的对拷
- IOUtils.copyBytes(fis, fos, configuration);
- // 6, 关闭资源
- IOUtils.closeStream(fis);
- IOUtils.closeStream(fos);
- fs.close();
- }
(3)合并文件
在 Windows 命令窗口中进入到目录 D:\temp\atguigu\0529\, 然后执行如下命令, 对数据进行合并
type hadoop-2.7.2.tar.gz.part2 >> hadoop-2.7.2.tar.gz.part1
合并完成后, 将 hadoop-2.7.2.tar.gz.part1 重新命名为 hadoop-2.7.2.tar.gz. 解压发现该 tar 包非常完整.
第 4 章 HDFS 的数据流(面试重点)
4.1 HDFS 写数据流程
4.1.1 剖析文件写入
HDFS 写数据流程, 如下图所示.
详解如下:
1)客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件, NameNode 检查目标文件是否已存在, 父目录是否存在.
2)NameNode 返回是否可以上传.
3)客户端请求第一个 Block 上传到哪几个 DataNode 服务器上.
4)NameNode 返回 3 个 DataNode 节点, 分别为 dn1,dn2,dn3.
5)客户端通过 FSDataOutputStream 模块请求 dn1 上传数据, dn1 收到请求会继续调用 dn2, 然后 dn2 调用 dn3, 将这个通信管道建立完成.
6)dn1,dn2,dn3 逐级应答客户端.
7)客户端开始往 dn1 上传第一个 Block(先从磁盘读取数据放到一个本地内存缓存), 以 Packet 为单位, dn1 收到一个 Packet 就会传给 dn2,dn2 传给 dn3;dn1 每传一个 packet 会放入一个应答队列等待应答.
8)当一个 Block 传输完成之后, 客户端再次请求 NameNode 上传第二个 Block 的服务器.(重复执行 3-7 步).
4.1.2 网络拓扑 - 节点距离计算
在 HDFS 写数据的过程中, NameNode 会选择距离待上传数据最近距离的 DataNode 接收数据. 那么这个最近距离怎么计算呢?
节点距离: 两个节点到达最近的共同祖先的距离总和.
网络拓扑概念:
例如, 假设有数据中心 d1 机架 r1 中的节点 n1. 该节点可以表示为 / d1/r1/n1. 利用这种标记, 这里给出四种距离描述, 如上图所示.
大家算一算每两个节点之间的距离, 如下图所示.
4.1.3 机架感知(副本存储节点选择)
1, 官方 ip 地址
机架感知说明: http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication
For the common case, when the replication factor is three, HDFS's placement policy is to put one replica on one node in the local Rack, another on a different node in the local Rack, and the last on a different node in a different Rack. This policy cuts the inter-Rack write traffic which generally improves write performance. The chance of Rack failure is far Less than that of node failure; this policy does not impact data reliability and availability guarantees. However, it does reduce the aggregate network bandwidth used when reading data since a block is placed in only two unique racks rather than three. With this policy, the replicas of a file do not evenly distribute across the racks. One third of replicas are on one node, two thirds of replicas are on one Rack, and the other third are evenly distributed across the remaining racks. This policy improves write performance without compromising data reliability or read performance.
翻译如下:
对于常见情况, 当复制因子为 3 时, HDFS 的放置策略是将一个副本放在本地机架中的一个节点上, 另一个放在本地机架中的另一个节点上, 将最后一个放在另一个机架中的另一个节点上. 此策略可以减少机架间写入流量, 从而提高写入性能. 机架故障的可能性远小于节点故障的可能性; 此策略不会影响数据可靠性和可用性保证. 但是, 它确实减少了读取数据时使用的聚合网络带宽, 因为块只放在两个唯一的机架而不是三个. 使用此策略时, 文件的副本不会均匀分布在机架上. 三分之一的副本位于一个节点上, 三分之二的副本位于一个机架上, 另外三个副本均匀分布在剩余的机架上.
2,Hadoop2.7.2 副本节点选择
4.2 HDFS 读数据流程
HDFS 的读数据流程, 如下图所示.
详解如下:
1)客户端通过 Distributed FileSystem 向 NameNode 请求下载文件, NameNode 通过查询元数据, 找到文件块所在的 DataNode 地址.
2)挑选一台 DataNode(就近原则, 然后随机)服务器, 请求读取数据.
3)DataNode 开始传输数据给客户端(从磁盘里面读取数据输入流, 以 Packet 为单位来做校验).
4)客户端以 Packet 为单位接收, 先在本地缓存, 然后写入目标文件.
第 5 章 NameNode 和 SecondaryNameNode(面试开发重点)
5.1 NN 和 2NN 工作机制
思考: NameNode 中的元数据是存储在哪里的?
首先, 我们做个假设, 如果存储在 NameNode 节点的磁盘中, 因为经常需要进行随机访问, 还有响应客户请求, 必然是效率过低. 因此, 元数据需要存放在内存中. 但如果只存在内存中, 一旦断电, 元数据丢失, 整个集群就无法工作了. 因此产生在磁盘中备份元数据的 FsImage.
这样又会带来新的问题, 当在内存中的元数据更新时, 如果同时更新 FsImage, 就会导致效率过低, 但如果不更新, 就会发生一致性问题, 一旦 NameNode 节点断电, 就会产生数据丢失. 因此, 引入 Edits 文件(只进行追加操作, 效率很高). 每当元数据有更新或者添加元数据时, 修改内存中的元数据并追加到 Edits 中. 这样, 一旦 NameNode 节点断电, 可以通过 FsImage 和 Edits 的合并, 合成元数据.
但是, 如果长时间添加数据到 Edits 中, 会导致该文件数据过大, 效率降低, 而且一旦断电, 恢复元数据需要的时间过长. 因此, 需要定期进行 FsImage 和 Edits 的合并, 如果这个操作由 NameNode 节点完成, 又会效率过低. 因此, 引入一个新的节点 SecondaryNamenode, 专门用于 FsImage 和 Edits 的合并.
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.
NN 和 2NN 工作机制详解:
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 中.
5.2 Fsimage 和 Edits 解析
1, 概念
2,oiv 查看 Fsimage 文件
(1)查看 oiv 和 oev 命令
- [atguigu@hadoop102 current]$ hdfs
- Usage: hdfs [--config confdir] [--loglevel loglevel] COMMAND
- where COMMAND is one of:
- dfs run a filesystem command on the file systems supported in Hadoop.
- classpath prints the classpath
- namenode -format format the DFS filesystem
- secondarynamenode run the DFS secondary namenode
- namenode run the DFS namenode
- journalnode run the DFS journalnode
- zkfc run the ZK Failover Controller daemon
- datanode run a DFS datanode
- dfsadmin run a DFS admin client
- haadmin run a DFS HA admin client
- fsck run a DFS filesystem checking utility
- balancer run a cluster balancing utility
- jmxget get JMX exported values from NameNode or DataNode.
- mover run a utility to move block replicas across
- storage types
- oiv apply the offline fsimage viewer to an fsimage
- oiv_legacy apply the offline fsimage viewer to an legacy fsimage
- oev apply the offline edits viewer to an edits file
- fetchdt fetch a delegation token from the NameNode
- getconf get config values from configuration
- groups get the groups which users belong to
- snapshotDiff diff two snapshots of a directory or diff the
- current directory contents with a snapshot
- lsSnapshottableDir list all snapshottable dirs owned by the current user
- Use -help to see options
- portmap run a portmap service
- nfs3 run an NFS version 3 gateway
- cacheadmin configure the HDFS cache
- crypto configure HDFS encryption zones
- storagepolicies list/get/set block storage policies
- version print the version
- Most commands print help when invoked w/o parameters.
- [atguigu@hadoop102 current]$
(2)基本语法
hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
(3)案例实操
- [atguigu@hadoop102 current]$ pwd
- /opt/module/hadoop-2.7.2/data/tmp/dfs/name/current
- [atguigu@hadoop102 current]$ hdfs oiv -p xml -i fsimage_0000000000000000124 -o fsimage.xml
- [atguigu@hadoop102 current]$ cat fsimage.xml
将显示的 xml 文件内容拷贝到 Eclipse 中创建的 xml 文件中, 并格式化. 部分显示结果如下.
- <inode>
- <id>16385</id>
- <type>DIRECTORY</type>
- <name></name>
- <mtime>1549193480818</mtime>
- <permission>atguigu:supergroup:rwxr-xr-x</permission>
- <nsquota>9223372036854775807</nsquota>
- <dsquota>-1</dsquota>
- </inode>
- <inode>
- <id>16386</id>
- <type>FILE</type>
- <name>wc.input</name>
- <replication>3</replication>
- <mtime>1549109263472</mtime>
- <atime>1549191451377</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741825</id>
- <genstamp>1001</genstamp>
- <numBytes>43</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16394</id>
- <type>FILE</type>
- <name>kongming.txt</name>
- <replication>10</replication>
- <mtime>1549172409335</mtime>
- <atime>1549172409063</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741832</id>
- <genstamp>1009</genstamp>
- <numBytes>28</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16398</id>
- <type>FILE</type>
- <name>yanjing.txt</name>
- <replication>3</replication>
- <mtime>1549182842815</mtime>
- <atime>1549191453687</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741833</id>
- <genstamp>1010</genstamp>
- <numBytes>29</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16399</id>
- <type>FILE</type>
- <name>banhua.txt</name>
- <replication>1</replication>
- <mtime>1549183347279</mtime>
- <atime>1549191440485</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741834</id>
- <genstamp>1011</genstamp>
- <numBytes>29</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16400</id>
- <type>FILE</type>
- <name>bancao.txt</name>
- <replication>2</replication>
- <mtime>1549183571406</mtime>
- <atime>1549191438143</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741835</id>
- <genstamp>1012</genstamp>
- <numBytes>29</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16401</id>
- <type>FILE</type>
- <name>banzhang.txt</name>
- <replication>1</replication>
- <mtime>1549192955364</mtime>
- <atime>1549192955243</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741836</id>
- <genstamp>1013</genstamp>
- <numBytes>12</numBytes>
- </block>
- </blocks>
- </inode>
- <inode>
- <id>16402</id>
- <type>FILE</type>
- <name>hadoop-2.7.2.tar.gz</name>
- <replication>3</replication>
- <mtime>1549193480811</mtime>
- <atime>1549193471067</atime>
- <perferredBlockSize>134217728</perferredBlockSize>
- <permission>atguigu:supergroup:rw-r--r--</permission>
- <blocks>
- <block>
- <id>1073741837</id>
- <genstamp>1014</genstamp>
- <numBytes>134217728</numBytes>
- </block>
- <block>
- <id>1073741838</id>
- <genstamp>1015</genstamp>
- <numBytes>63439959</numBytes>
- </block>
- </blocks>
- </inode>
思考: 可以看出, Fsimage 中没有记录块所对应 DataNode, 为什么?
答: 是因为在集群启动后, 要求 DataNode 上报数据块信息, 并间隔一段时间后再次上报. 所以我们要先启动集群.
3,oev 查看 Edits 文件
(1)基本语法
hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
(2)案例实操
- [atguigu@hadoop102 current]$ hdfs oev -p xml -i edits_0000000000000000103-0000000000000000108 -o edits.xml
- [atguigu@hadoop102 current]$ cat edits.xml
将显示的 xml 文件内容拷贝到 Eclipse 中创建的 xml 文件中, 并格式化. 显示结果如下.
- <?xml version="1.0" encoding="UTF-8"?>
- <EDITS>
- <EDITS_VERSION>-63</EDITS_VERSION>
- <RECORD>
- <OPCODE>OP_START_LOG_SEGMENT</OPCODE>
- <DATA>
- <TXID>103</TXID>
- </DATA>
- </RECORD>
- <RECORD>
- <OPCODE>OP_TIMES</OPCODE>
- <DATA>
- <TXID>104</TXID>
- <LENGTH>0</LENGTH>
- <PATH>/bancao.txt</PATH>
- <MTIME>-1</MTIME>
- <ATIME>1549191438143</ATIME>
- </DATA>
- </RECORD>
- <RECORD>
- <OPCODE>OP_TIMES</OPCODE>
- <DATA>
- <TXID>105</TXID>
- <LENGTH>0</LENGTH>
- <PATH>/banhua.txt</PATH>
- <MTIME>-1</MTIME>
- <ATIME>1549191440485</ATIME>
- </DATA>
- </RECORD>
- <RECORD>
- <OPCODE>OP_TIMES</OPCODE>
- <DATA>
- <TXID>106</TXID>
- <LENGTH>0</LENGTH>
- <PATH>/wc.input</PATH>
- <MTIME>-1</MTIME>
- <ATIME>1549191451377</ATIME>
- </DATA>
- </RECORD>
- <RECORD>
- <OPCODE>OP_TIMES</OPCODE>
- <DATA>
- <TXID>107</TXID>
- <LENGTH>0</LENGTH>
- <PATH>/yanjing.txt</PATH>
- <MTIME>-1</MTIME>
- <ATIME>1549191453687</ATIME>
- </DATA>
- </RECORD>
- <RECORD>
- <OPCODE>OP_END_LOG_SEGMENT</OPCODE>
- <DATA>
- <TXID>108</TXID>
- </DATA>
- </RECORD>
- </EDITS>
思考: NameNode 如何确定下次开机启动的时候合并哪些 Edits?
答: 根据 seen_txid 里面记录最新的 Fsimage(镜像文件)的值去合并 Edits(编辑日志).
5.3 CheckPoint 时间设置
(1)通常情况下, SecondaryNameNode 每隔一小时执行一次.
- [hdfs-default.xml]
- <property>
- <name>dfs.namenode.checkpoint.period</name>
- <value>3600</value>
- <description>SecondaryNameNode 每隔一小时执行一次</description>
- </property>
(2)当操作次数达到 1 百万时, SecondaryNameNode 执行一次.
- <property>
- <name>dfs.namenode.checkpoint.txns</name>
- <value>1000000</value>
- <description > 操作动作次数</description>
- </property>
(3)一分钟检查一次操作次数.
- <property>
- <name>dfs.namenode.checkpoint.check.period</name>
- <value>60</value>
- <description>1 分钟检查一次操作次数</description>
- </property >
该文件截图如下:
5.4 NameNode 故障处理(开发重点: 偏运维)
NameNode 故障后, 可以采用如下两种方法恢复数据.
方法一: 将 SecondaryNameNode 中数据拷贝到 NameNode 存储数据的目录.
1,kill -9 NameNode 进程
2, 删除 NameNode 存储的数据目录中的数据(目录位置:/opt/module/hadoop-2.7.2/data/tmp/dfs/name/)
[atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
3, 拷贝 SecondaryNameNode 中数据到原 NameNode 存储数据目录
- [atguigu@hadoop102 name]$ pwd
- /opt/module/hadoop-2.7.2/data/tmp/dfs/name
- [atguigu@hadoop102 name]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/* ./
4, 重新启动 NameNode
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
方法二: 使用 - importCheckpoint 选项启动 NameNode 守护进程, 从而将 SecondaryNameNode 中数据拷贝到 NameNode 目录中.
1, 修改 hdfs-site.xml 中的内容, 新增如下, 然后分发到其他节点
- [atguigu@hadoop102 hadoop-2.7.2]$ VIM etc/hadoop/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>
- [atguigu@hadoop102 hadoop-2.7.2]$ xsync etc/hadoop/
2,kill -9 NameNode 进程
3, 删除 NameNode 存储的数据目录中的数据(目录位置:/opt/module/hadoop-2.7.2/data/tmp/dfs/name/)
[atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*
4, 如果 SecondaryNameNode 不和 NameNode 在一个主机节点上, 需要将 SecondaryNameNode 存储数据的目录 namesecondary 拷贝到 NameNode 存储数据的平级目录 name, 并删除 in_use.lock 文件
- [atguigu@hadoop102 dfs]$ pwd
- /opt/module/hadoop-2.7.2/data/tmp/dfs
- [atguigu@hadoop102 dfs]$ ll
总用量 8
drwx------. 3 atguigu atguigu 4096 2 月 4 10:37 data
drwxrwxr-x. 2 atguigu atguigu 4096 2 月 4 10:59 name
- [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/ ./
- [atguigu@hadoop102 dfs]$ ll
总用量 12
drwx------. 3 atguigu atguigu 4096 2 月 4 10:37 data
drwxrwxr-x. 2 atguigu atguigu 4096 2 月 4 10:59 name
drwxrwxr-x. 3 atguigu atguigu 4096 2 月 4 11:04 namesecondary
- [atguigu@hadoop102 dfs]$
- [atguigu@hadoop102 dfs]$ rm -rf namesecondary/in_use.lock
5, 导入检查点数据(设置的是 2 分钟, 等待一会 ctrl+c 结束掉)
[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode -importCheckpoint
6, 启动 NameNode
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
方式二比方式一要检查的东西多一些, 方式一比较直接.
5.5 集群安全模式
1, 概述
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 (功能描述:[等待]安全模式状态)
演示如下图所示:
3, 案例
模拟等待安全模式
(1)查看当前模式
(2)先进入安全模式
(3)创建并执行下面的脚本
在 / opt/module/hadoop-2.7.2 路径上, 编辑一个脚本 safemode.sh
- [atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode get
- Safe mode is OFF
- [atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode enter
- Safe mode is ON
- [atguigu@hadoop102 hadoop-2.7.2]$ touch safemode.sh
- [atguigu@hadoop102 hadoop-2.7.2]$ VIM safemode.sh
- [atguigu@hadoop102 hadoop-2.7.2]$ cat safemode.sh
- #!/bin/bash
- hdfs dfsadmin -safemode wait
- hdfs dfs -put /opt/module/hadoop-2.7.2/README.txt /
- [atguigu@hadoop102 hadoop-2.7.2]$ bash ./safemode.sh
(4)再打开一个窗口, 执行该脚本
[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs dfsadmin -safemode leave
(5)观察
(a)再观察上一个窗口
Safe mode is OFF
(b)HDFS 集群上已经有上传的数据了.
5.6 NameNode 多目录配置
1,NameNode 的本地目录可以配置成多个, 且每个目录存放内容相同, 增加了可靠性.
2, 具体配置如下:
(1)在 hdfs-site.xml 文件中增加如下内容, 保存退出后, 然后进行分发操作
- [atguigu@hadoop102 hadoop-2.7.2]$ VIM etc/hadoop/hdfs-site.xml
- <property>
- <name>dfs.namenode.name.dir</name>
- <value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</value>
- </property>
- [atguigu@hadoop102 hadoop-2.7.2]$ xsync etc/hadoop/
(2)停止集群, 删除 data 和 logs 中所有数据.
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/stop-dfs.sh 关闭全部 NameNode 和 DataNode
[atguigu@hadoop103 hadoop-2.7.2]$ sbin/stop-yarn.sh 关闭全部 ResourceManager 和 NodeManager
- [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf data/ logs/
- [atguigu@hadoop103 hadoop-2.7.2]$ rm -rf data/ logs/
- [atguigu@hadoop104 hadoop-2.7.2]$ rm -rf data/ logs/
(3)格式化集群并启动.
[atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode -format
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh 开启全部 NameNode 和 DataNode
(4)查看结果
[atguigu@hadoop102 dfs]$ ll
总用量 8
drwxrwxr-x. 3 atguigu atguigu 4096 2 月 4 12:50 name1
drwxrwxr-x. 3 atguigu atguigu 4096 2 月 4 12:50 name2
- [atguigu@hadoop102 dfs]$ cd name1/
- [atguigu@hadoop102 name1]$ cd current/
- [atguigu@hadoop102 current]$ ll
总用量 16
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:50 fsimage_0000000000000000000
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:50 fsimage_0000000000000000000.md5
-rw-rw-r--. 1 atguigu atguigu 2 2 月 4 12:50 seen_txid
-rw-rw-r--. 1 atguigu atguigu 205 2 月 4 12:50 VERSION
- [atguigu@hadoop102 current]$ cd ..
- [atguigu@hadoop102 name1]$ cd ..
- [atguigu@hadoop102 dfs]$ cd name2/
- [atguigu@hadoop102 name2]$ cd current/
- [atguigu@hadoop102 current]$ ll
总用量 16
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:50 fsimage_0000000000000000000
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:50 fsimage_0000000000000000000.md5
-rw-rw-r--. 1 atguigu atguigu 2 2 月 4 12:50 seen_txid
-rw-rw-r--. 1 atguigu atguigu 205 2 月 4 12:50 VERSION
- [atguigu@hadoop102 current]$ cd ..
- [atguigu@hadoop102 name2]$ cd ..
- [atguigu@hadoop102 dfs]$ ll
总用量 12
drwx------. 3 atguigu atguigu 4096 2 月 4 12:53 data
drwxrwxr-x. 3 atguigu atguigu 4096 2 月 4 12:53 name1
drwxrwxr-x. 3 atguigu atguigu 4096 2 月 4 12:53 name2
[atguigu@hadoop102 dfs]$ ll name1/current/
总用量 1052
-rw-rw-r--. 1 atguigu atguigu 42 2 月 4 12:54 edits_0000000000000000001-0000000000000000002
-rw-rw-r--. 1 atguigu atguigu 1048576 2 月 4 12:55 edits_inprogress_0000000000000000003
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:50 fsimage_0000000000000000000
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:50 fsimage_0000000000000000000.md5
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:54 fsimage_0000000000000000002
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:54 fsimage_0000000000000000002.md5
-rw-rw-r--. 1 atguigu atguigu 2 2 月 4 12:54 seen_txid
-rw-rw-r--. 1 atguigu atguigu 205 2 月 4 12:50 VERSION
[atguigu@hadoop102 dfs]$ ll name2/current/
总用量 1052
-rw-rw-r--. 1 atguigu atguigu 42 2 月 4 12:54 edits_0000000000000000001-0000000000000000002
-rw-rw-r--. 1 atguigu atguigu 1048576 2 月 4 12:55 edits_inprogress_0000000000000000003
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:50 fsimage_0000000000000000000
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:50 fsimage_0000000000000000000.md5
-rw-rw-r--. 1 atguigu atguigu 354 2 月 4 12:54 fsimage_0000000000000000002
-rw-rw-r--. 1 atguigu atguigu 62 2 月 4 12:54 fsimage_0000000000000000002.md5
-rw-rw-r--. 1 atguigu atguigu 2 2 月 4 12:54 seen_txid
-rw-rw-r--. 1 atguigu atguigu 205 2 月 4 12:50 VERSION
[atguigu@hadoop102 dfs]$
来源: https://www.cnblogs.com/chenmingjun/p/10353274.html