Hadoop是一个能够对大量数据进行分布式处理的软件框架。 Hadoop 以一种可靠、高效、可伸缩的方式进行数据处理。因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失败的节点重新分布处理,以并行的方式工作,通过并行处理加快处理速度,能够处理 PB 级数据。
Hadoop主要由HDFS、MapReduce和Hbase组成。 它是一个分布式系统基础架构,由Apache基金会开发。
由于Hadoop版本混乱多变以及Apache Hadoop版本衍化,截至2012年12月23日,Apache Hadoop版本分为两代,我们将第一代Hadoop称为Hadoop 1.0,第二代Hadoop称为Hadoop 2.0。
两个版本之间的差别
Hadoop1.0和Hadoop2.0版本之间还是存在很大的差异的。
整体上,1.0版本是由分布式存储系统HDFS和分布式计算框架MapReduce组成,其中HDFS由一个NameNode和多个DataNode组成,MapReduce由一个JobTracker和多个TaskTracker组成。
2.0版本中,引入HDFS Fedration,它让多个NameNode分管不同的目录进而实现访问隔离和横向拓展,同时解决了NameNode单点故障问题;引入资源管理框架Yarn,可以为各类应用程序进行资源管理和调度。
HDFS基本概念
数据块block
- HDFS(Hadoop Distributed File System)默认的最基本的存储单位是64M的数据块
- 每个区块至少分到三台DataNode上
- HDFS中的文件是被分成64M一块的数据块存储的
- HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间
元数据节点NameNode和数据节点DataNode
- namenode用来管理文件系统的命名空间
- datanode是文件系统中真正存储数据的地方
HDFS的基本命令
- 列出HDFS下的文件
$ hdfs dfs -ls
$ hdfs dfs -ls in //列出HDFS文件下名为in的文档中的文件
- 上传文件
$ /usr/local/hadoop$bin/hadoop dfs -put test1 test
// 将hadoop目录下的test1文件上传到HDFS上并重命名为test
- 下载文件到本地
$ /usr/local/hadoop$bin/hadoop dfs -get in getin
// 将HDFS中的in文件复制到本地系统并命名为getin
- 删除文件
$ /usr/local/hadoop$bin/hadoop dfs -rmr out
// 删除HDFS下名为out的文档
- 查看文件
$ /usr/local/hadoop$bin/hadoop dfs -cat in/*
// 删除HDFS下名为out的文档
- 创建目录
$ /usr/local/hadoop$bin/hadoop dfs -mkdir /user/hadoop/examples
// HDFS只能一级一级的新建目录
- 复制文件
$ /usr/local/hadoop$bin/hadoop dfs -copyFromLocal
HDFS的应用场景
HDFS适用于高吞吐量,一次写入,多次读取的应用场景。
不适合大量小文件的存储,低时间延迟,多用户读写操作的场景。
HDFS 文件读取
HDFS在读取文件的时候,
1. 首先创建RPC连接;
2. 从namenode 中获取文件数据块的位置;
3. 客户端与datanode之间建立socket链接,选择与客户端最近的datanode节点;
4. 下载文件的数据块。
HDFS文件写入
1. 创建RPC连接;
2. 创建文件元数据;
3. 为文件分配块;
4. 客户端与DataNode,DataNode之间建立socket(4,5,6),并且几者之间socket均建立成功才算成功,才能进行数据块的写入操作;
5. 每个DataNode接收完某个块会向NameNode进行报告;
6. 如果一个文件的每个块的三个副本中,只要有一个副本报告给NameNode,客户端发送消息给NameNode确认文件完成;
HDFS中的Java接口
从Hadoop URL中读取数据
InputStream in = null;
try{
in = new URL("hdfs://host/path").openStream();
}finally{
IOUtils.closeStream(in);
}
通过FileSystem API读取数据
String uri = "hdfs://host/path";
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
InputStream in = null;
try{
in = fs.open(new Path(uri));
IOUtils.copyBytes(in, System.out, 4096, false);
}finally{
IOUtils.closeStream(in);
}