前言
hadoop学习心得今天主要学了关于Hadoop中hdfs的一些操作
提示:以下皆为本人学习心得,不能保证正确,欢迎大神指点交流。
一、HDFS
1、HDFS简介
HDFS(Hadoop Distributed File System),是一个分布式文件系统,用于存储文件,通过目录树来定位文件。
HDFS适合一次写入、多次读取的场景,且不支持文件的修改。一般用于做数据分析,而不适合用作网盘应用。
2、HDFS的优缺点
优点:
- 高容错性:数据保存为多个副本,一个副本丢失后,可以自动恢复。
- 适合处理大量数据。
- 可以构建在廉价的机器上,通过多副本机制提高可靠性。
缺点
- 不适合低延时数据访问,不能用来做实时运算
- 无法高效处理大量小文件
- 不支持并发写入、不支持文件随机修改。
3、HDFS的组成架构
-
NameNode
是HDFS架构中的老大,是作为管理者(Master)存在的。 1、管理HDFS的名称空间; 2、配置副本策略; 3、管理数据块(Block)映射信息; 4、处理客户端读写请求。
-
DataNode
是HDFS中的底层工作者(slaves)身份,负责执行实际的操作 1、存储实际的数据块 2、执行数据块的读/写操作
-
SecondaryNameNode
并不是NameNode2号,而是NameNode的副手角色,当NameNode宕机时不能马上替换NameNode。 1、辅助NameNode,分担其工作量 合并Fsimage和Edits,并推送给NameNode 2、经济情况下辅助恢复NameNode
-
Client
客户端 1、文件切分由客户端完成 2、与NameNode交互,获取文件位置信息 3、与DataNode交互,完成读写 4、Client可以通过命令管理hdfs,如NameNode的格式化 5、通过命令访问HDFS
二、HDFS shell 操作
1.基本语法
bin/hadoop fs <命令>
或
bin/hdfs dfs <命令>
一些常用命令(实际使用的时候可以通过自带的–help指令查询):
-help 查询指令
-ls 显示目录
-mkdir 创建目录
-cat 显示文件内容
-chgrp、-chown、-chmod 同linux系统对应指令
-cp 复制
-mv 移动
-get 下载文件到本地
-put 从本地发送文件到HDFS
-rm 删除文件
-rmdir 删除目录
-setrep 设置HDFS中文件的副本数
2.HDFS客户端操作(java代码编写
1、客户端环境准备
需要准备好版本对应的JDK与对应pc环境编译后的Hadoop
并配置好环境变量。
我所使用的是JDK1.8与Hadoop2.7.2
2、maven导入依赖
<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>
</dependencies>
如需要配置log4j在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
3、java代码编写
通过jutil提供的注解实现初始化和资源关闭代码块的封装,减轻开发学习中不必要的多余操作
//通过jutil可以方便的实现快速的初始化配置信息和关闭资源,如下
public class HDFSClient {
private Configuration conf = new Configuration();;
private FileSystem fs;
//通过Before注解可以让我们的测试代码运行前实现所需的初始化,更适合我们学习。
@Before
public void init() throws Exception {
//在test前通过hadoop提供的FileSystem配置好相应的
//HDFS地址,其中的hadoop201为我的集群的namenode所在host,9000是hadoop提供的代码访问端口
//conf 配置文件,有多种配置方法
//“kgg”为对应启动HDFS的linux的用户名,可以
fs = FileSystem.get(new URI("hdfs://hadoop201:9000"),conf,"kgg");
}
//此处为任何你要尝试的java代码
@Test
public void method(){}
//通过After注解实现资源的释放
@After
public void close() throws IOException{
if (fs != null) {
fs.close();
}
}
}
所实际起作用的代码编写,因为那些HDFS提供的API操作都只要调用其提供的方法即可,顾略过不表。
这里仅记录一个通过IO操作将HDFS的文件分块下载的代码
/**
* 分块读取的思路就是通过hadoop文件的固定分块大小来读取文件的操作
* 将数据从输入流分批次读固定大小到缓冲中然后写入输出流。
* 本次选用的文件是hadoop本身的压缩包,大小大于一块,HDFS会分两块存储,所以先读一块
* 然后再关闭输出流再读一块到新文件中。之后拼接判断文件是否出错。
* 如果要跳过前几块、直接seek跳跃文件指针即可。
*/
@Test
public void testCopyFromHDFS()throws Exception{
//打开输入流,因为文件从HDFS下载,所以通过Hadoop的FileSystem获取输入流
FSDataInputStream fis = fs.open(new Path("/h.tar.gz"));
//输出流,要下载到本地,所以用java自带的输出流
FileOutputStream fos = new FileOutputStream("e:/work/test/h.tar.gz.part1");
//创建字节字符串做缓存,长度为1024,这样一次就可以读取1024b即1kb数据
byte[] buf = new byte[1024];
//循环读取数据,循环1024*128次,即一共读取128m数据,也即一个HDFS中的数据块
for (int i=0;i<1024*128;i++){
fis.read(buf);
fos.write(buf);
}
//通过IOUtils关闭输出流并打开一个指向新文件的输出流
IOUtils.closeStream(fos);
fos = new FileOutputStream("e:/work/test/h.tar.gz.part2");
//因为剩下的数据只有不到一个数据块的操作了,所以不用计量读取数据,直接copyBytes即可
IOUtils.copyBytes(fis,fos,conf);
//不要忘记关闭流
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
总结
以上便是本篇文件的内容了,今天主要学习了HDFS的相关知识和一些客户端的shell操作指令。
同时学习了怎样用java代码实现对HDFS进行操作。
个人认为其中最要注意的一点还是要区分清楚HDFS的路径和本地路径的区别。