Hadoop是Apache开源组织的一个分布式计算开源框架,实现在大量计算机组成的集群中对海量计算机进行分布式计算。Hadoop框架中最核心的设计是HDFS和MapReduce,HDFS实现存储,MapReduce实现原理分析处理。
一、HDFS
HDFS(Hadoop分布式文件系统),可以提供高吞吐量的数据访问,适合那些有超大数据集的应用程序。
HDFS的设计特点:
1、大数据文件,非常适合上T级别的大文件或者一堆大数据文件的存储。
2、文件分块存储,HDFS会将一个完整的大文件平均分块存储到不同计算器上,它的意义在于读取文件时可以同时从多个主机取不同区块的文件,多主机读取比单主机读取效率要高得多。
3、流式数据访问,一次写入多次读写,这种模式跟传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。
4、廉价硬件,HDFS可以应用在普通PC机上,这种机制能够让给一些公司用几十台廉价的计算机就可以撑起一个大数据集群。
5、硬件故障,HDFS认为所有计算机都可能会出问题,为了防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其它某几个主机上,如果其中一台主机失效,可以迅速找另一块副本取文件。
HDFS的master/slave构架:
一个HDFS集群是由一个Namenode和一定数目的Datanode组成。Namenode是一个中心服务器,主要存储元数据信息,主要包括文件目录、块和文件对应关系、块和Datanode对应关系。Datanode在集群中一般是一个节点一个,负责存储数据信息。
HDFS的关键元素:
1、Block:将一个文件进行分块,通常是64M。
2、NameNode:保存整个文件系统的目录信息、文件信息及分块信息,这是由唯一一台主机专门保存,当然这台主机如果出错,NameNode就失效了。在Hadoop2.*开始支持activity-standy模式----如果主NameNode失效,启动备用主机运行NameNode。
3、DataNode:分布在廉价的计算机上,用于存储Block块文件。
4、Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表。
二、MapReduce
MapReduce是一种编程模型,负责大规模数据集的并行运算,分为两部分:Map(映射)和Reduce(归约)。
当你向MapReduce框架提交一个计算作业时,它会首先把计算作业拆分成若干个Map任务,然后分配到不同的节点上去执行,每一个Map任务处理输入数据中的一部分,当Map任务完成后,它会生成一些中间文件,这些中间文件将会作为Reduce任务的输入数据。Reduce任务的主要目标就是把前面若干个Map的输出汇总到一起并输出。
MapReduce工作步骤大概如下:
1:首先对输入数据源进行切片
2:master调度worker执行map任务
3:worker读取输入源片段,执行map任务,并将输出保存在本地
4:master调度worker执行reduce任务,
5:worker读取map任务的输出文件,执行reduce任务,将任务输出保存到HDFS
三、Java API操作HDFS文件
1、从HDFS文件系统复制文件到本地
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.URI;
- import java.net.URISyntaxException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.io.IOUtils;
- public class OpenDemo {
- public static void main(String[] args) throws IOException, URISyntaxException {
- // 获得FileSystem对象
- FileSystem fileSystem = FileSystem.get(new URI("hdfs://Hadoop1:9000"), new Configuration());
- // 调用open方法进行下载,参数HDFS路径
- InputStream in = fileSystem.open(new Path("/hadoop/LICENSE.txt"));
- // 创建输出流,参数指定文件输出地址
- OutputStream out = new FileOutputStream("F://hadoop/LICENSE.txt");
- // 使用Hadoop提供的IOUtils,将in的内容copy到out,设置buffSize大小,是否关闭流设置true
- IOUtils.copyBytes(in, out, 4096, true);
- }
- }
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.URI;
- import java.net.URISyntaxException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.io.IOUtils;
- public class UpLoadDemo {
- public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
- // 获得FileSystem对象,指定使用root用户上传
- FileSystem fileSystem = FileSystem.get(new URI("hdfs://Hadoop1:9000"), new Configuration(), "root");
- // 创建输入流,参数指定文件输出地址
- InputStream in = new FileInputStream("C:\\Windows\\System32\\drivers\\etc\\hosts");
- // 调用create方法指定文件上传,参数HDFS上传路径
- OutputStream out = fileSystem.create(new Path("/hadoop/hosts"));
- // 使用Hadoop提供的IOUtils,将in的内容copy到out,设置buffSize大小,是否关闭流设置true
- IOUtils.copyBytes(in, out, 4096, true);
- }
- }
- import java.io.IOException;
- import java.net.URI;
- import java.net.URISyntaxException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- public class DeleteDemo {
- public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
- // 获得FileSystem对象
- FileSystem fileSystem = FileSystem.get(new URI("hdfs://Hadoop1:9000"), new Configuration(), "root");
- // 调用delete方法,删除指定的文件。参数:false:表示是否递归删除
- boolean flag = fileSystem.delete(new Path("/hadoop/hosts"), false);
- // 执行结果:true
- System.out.println(flag);
- }
- }
- import java.io.IOException;
- import java.net.URI;
- import java.net.URISyntaxException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- public class MkDirDemo {
- public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
- // 获得FileSystem对象
- FileSystem fileSystem = FileSystem.get(new URI("hdfs://Hadoop1:9000"), new Configuration(), "root");
- // 调用mkdirs方法,在HDFS文件服务器上创建文件夹。
- boolean flag = fileSystem.mkdirs(new Path("/hadoop/dir3"));
- // 执行结果:true
- System.out.println(flag);
- }
- }