hadoop(一HDFS)
介绍
狭义上来说:
hadoop指的是以下的三大系统:
- HDFS :分布式文件系统(高吞吐,没有延时要求,容错性,扩展能力)
- MapReduce : 分布式计算系统
- Yarn:分布式样集群资源管理
但是hadoop可不止这三个系统
广义上来说:
hadoop指的是大数据的一个生态圈
架构模型
1.X版本的架构
NameNode:集群的主节点,主要是管理集群中的各种元数据()
secondaryNameNode:主节点的辅助管理,主节点宕机后无法代替它(SecondaryNameNode 定期合并 fsimage 和 edits, 把 edits 控制在一个范围内 )
DataNode:从节点,主要用于存储集群中的各种数据
JobTracker:主节点,接收用户的计算请求,并分配给从节点
TaskTracker:负责执行主节点JobTracker分配的任务
2.x的版本架构模型
数据计算核心模块:
ResourceManager:接收用户的计算请求任务,并负责集群的资源分配
NodeManager:负责执行主节点APPmaster分配的任务
高可用的实现
文件管理系统多了JournalNode,目的是为了实现NameNode里面元数据的同步,当其中一个宕机,另外一个能完美代替它
多了一个备份节点,让Zookeeper来管理实现高可用
配置的作用
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://node01:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.7.5/hadoopDatas/tempDatas</value>
</property>
<!-- 缓冲区大小,实际工作中根据服务器性能动态调整 -->
<property>
<name>io.file.buffer.size</name>
<value>4096</value>
</property>
<!-- 开启hdfs的垃圾桶机制,删除掉的数据可以从垃圾桶中回收,单位分钟 -->
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
</configuration>
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim hdfs-site.xml
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node01:50090</value>
</property>
<property>
<name>dfs.namenode.http-address</name>
<value>node01:50070</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/namenodeDatas,file:///export/servers/hadoop-
2.7.5/hadoopDatas/namenodeDatas2</value>
</property>
<!-- 定义dataNode数据存储的节点位置,实际工作中,一般先确定磁盘的挂载目录,然后
多个目录用,进行分割 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///export/servers/hadoop-
2.7.5/hadoopDatas/datanodeDatas,file:///export/servers/hadoop-
2.7.5/hadoopDatas/datanodeDatas2</value>
</property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-
2.7.5/hadoopDatas/nn/edits</value>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///export/servers/hadoop-
2.7.5/hadoopDatas/snn/name</value>
</property>
<property>
<name>dfs.namenode.checkpoint.edits.dir</name>
<value>file:///export/servers/hadoop-
2.7.5/hadoopDatas/dfs/snn/edits</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
</configuration>
HDFS 的架构
HDFS由四部分组成,HDFS Client、NameNod e、DataNode和Secondary NameNode
1、Client:就是客户端。
文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储。
与 NameNode 交互,获取文件的位置信息。
与 DataNode 交互,读取或者写入数据。
Client 提供一些命令来管理 和访问HDFS,比如启动或者关闭HDFS。
2、NameNode:就是 master,它是一个主管、管理者。
管理 HDFS 的名称空间
管理数据块(Block)映射信息
配置副本策略
处理客户端读写请求。
3、DataNode:就是Slave。NameNode 下达命令,DataNode 执行实际的操作。
存储实际的数据块。
执行数据块的读/写操作。
4、Secondary NameNode:并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。
辅助 NameNode,分担其工作量。
定期合并 fsimage和fsedits,并推送给NameNode。
在紧急情况下,可辅助恢复 NameNode。
NameNode作用 :
1、NameNode元数据信息 文件名,文件目录结构,文件属性(生成时间,副本数,权限)每个
文件的块列表。 以及列表中的块与块所在的DataNode之间的地址映射关系 在内存中加载文件
系统中每个文件和每个数据块的引用关系(文件、block、datanode之间的映射信息) 数据会定
期保存到本地磁盘(fsImage文件和edits文件)
2、NameNode文件操作 NameNode负责文件元数据的操作 DataNode负责处理文件内容的读写
请求,数据流不经过NameNode,会询问它跟那个DataNode联系
3、NameNode副本 文件数据块到底存放到哪些DataNode上,是由NameNode决定的,NN根
据全局情况做出放置副本的决定
4、NameNode心跳机制 全权管理数据块的复制,周期性的接受心跳和块的状态报告信息(包
含该DataNode上所有数据块的列表) 若接受到心跳信息,NameNode认为DataNode工作正
常,如果在10分钟后还接受到不到DN的心跳,那么NameNode认为DataNode已经宕机 ,这时候
NN准备要把DN上的数据块进行重新的复制。 块的状态报告包含了一个DN上所有数据块的列
表,blocks report 每个1小时发送一次.
DataNode作用
提供真实文件数据的存储服务。
1、Data Node以数据块的形式存储HDFS文件
2、Data Node 响应HDFS 客户端读写请求
3、Data Node 周期性向NameNode汇报心跳信息
4、Data Node 周期性向NameNode汇报数据块信息
5、Data Node 周期性向NameNode汇报缓存数据块信息
HDFS 文件副本机制
所有的文件都是以 block 块的方式存放在 HDFS 文件系统当中,作用如下
- 一个文件有可能大于集群中任意一个磁盘,引入块机制,可以很好的解决这个问题
- 使用块作为文件存储的逻辑单位可以简化存储子系统
- 块非常适合用于数据备份进而提供数据容错能力
机架感知
HDFS分布式文件系统的内部有一个副本存放策略:以默认的副本数=3为例:
1、第一个副本块存本机
2、第二个副本块存跟本机同机架内的其他服务器节点
3、第三个副本块存不同机架的一个服务器节点上
HDFS 的元数据辅助管理
当 Hadoop 的集群当中, NameNode的所有元数据信息都保存在了 FsImage 与 Eidts 文件当中,这两个文件就记录了所有的数据的元数据信息, 元数据信息的保存目录配置在了 hdfssite.xml 当中
<property>
<name>dfs.namenode.name.dir</name>
<value>
file:///export/servers/hadoop2.7.5/hadoopDatas/namenodeDatas,
file:///export/servers/hadoop-
2.7.5/hadoopDatas/namenodeDatas2
</value>
</property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-
2.7.5/hadoopDatas/nn/edits</value
</property>>
11.1 FsImage 和 Edits 详解
edits
- edits 存放了客户端最近一段时间的操作日志
- 客户端对 HDFS 进行写文件时会首先被记录在 edits 文件中
- edits 修改时元数据也会更新
fsimage
- NameNode 中关于元数据的镜像, 一般称为检查点, fsimage 存放了一份比较完整的元数据信息
- 因为 fsimage 是 NameNode 的完整的镜像, 如果每次都加载到内存生成树状拓扑结构,这是非常耗内存和CPU, 所以一般开始时对 NameNode 的操作都放在 edits 中
- fsimage 内容包含了 NameNode 管理下的所有 DataNode 文件及文件 block 及 block所在的 DataNode 的元数据信息
- .随着 edits 内容增大, 就需要在一定时间点和 fsimage 合并
11.4 SecondaryNameNode 如何辅助管理 fsimage 与 edits 文件?
SecondaryNameNode 定期合并 fsimage 和 edits, 把 edits 控制在一个范围内
配置 SecondaryNameNode
SecondaryNameNode 在 conf/masters 中指定
在 masters 指定的机器上, 修改 hdfs-site.xml
<property>
<name>dfs.http.address</name>
<value>host:50070</value>
</property>
修改 core-site.xml , 这一步不做配置保持默认也可以
<!-- 多久记录一次 HDFS 镜像, 默认 1小时 -->
<property>
<name>fs.checkpoint.period</name>
<value>3600</value>
</property>
<!-- 一次记录多大, 默认 64M -->
<property>
<name>fs.checkpoint.size</name>
<value>67108864</value>
</property>
- SecondaryNameNode 通知 NameNode 切换 editlog
- SecondaryNameNode 从 NameNode 中获得 fsimage 和 editlog(通过http方式)
- SecondaryNameNode 将 fsimage 载入内存, 然后开始合并 editlog, 合并之后成为新的fsimage
- SecondaryNameNode 将新的 fsimage 发回给 NameNode
- NameNode 用新的 fsimage 替换旧的 fsimage
HDFS---API常规操作
常用Maven依赖
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<!-- <verbal>true</verbal>-->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
获取 FileSystem
@Test
public void getFileSystem2() throws URISyntaxException, IOException {
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
System.out.println(fileSystem);
}
hdfs文件的遍历
/*
hdfs文件的遍历
*/
@Test
public void listFiles() throws URISyntaxException, IOException {
//1:获取FileSystem实例
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
//2:调用方法listFiles 获取 /目录下所有的文件信息
RemoteIterator<LocatedFileStatus> iterator = fileSystem.listFiles(new Path("/"), true);
//3:遍历迭代器
while (iterator.hasNext()){
LocatedFileStatus fileStatus = iterator.next();
//获取文件的绝对路径 : hdfs://node01:8020/xxx
System.out.println(fileStatus.getPath() + "----" +fileStatus.getPath().getName());
//文件的block信息
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
System.out.println("block数:"+blockLocations.length);
}
}
hdfs创建文件夹
/*
hdfs创建文件夹
*/
@Test
public void mkdirsTest() throws URISyntaxException, IOException {
//1:获取FileSystem实例
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
//2:创建文件夹
//boolean bl = fileSystem.mkdirs(new Path("/aaa/bbb/ccc"));
fileSystem.create(new Path("/aaa/bbb/ccc/a.txt"));
fileSystem.create(new Path("/aaa2/bbb/ccc/a.txt"));
//System.out.println(bl);
//3: 关闭FileSystem
//fileSystem.close();
}
实现文件的下载
/*
实现文件的下载
*/
@Test
public void downloadFile2() throws URISyntaxException, IOException, InterruptedException {
//1:获取FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root");
//2:调用方法,实现文件的下载
fileSystem.copyToLocalFile(new Path("/a.txt"), new Path("D://a4.txt"));
//3:关闭FileSystem
fileSystem.close();
}
文件的上传
/*
文件的上传
*/
@Test
public void uploadFile() throws URISyntaxException, IOException {
//1:获取FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration());
//2:调用方法,实现上传
fileSystem.copyFromLocalFile(new Path("D://set.xml"), new Path("/"));
//3:关闭FileSystem
fileSystem.close();
}
小文件的合并
/*
小文件的合并
*/
@Test
public void mergeFile() throws URISyntaxException, IOException, InterruptedException {
//1:获取FileSystem(分布式文件系统)
FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:8020"), new Configuration(),"root");
//2:获取hdfs大文件的输出流
FSDataOutputStream outputStream = fileSystem.create(new Path("/big_txt.txt"));
//3:获取一个本地文件系统
LocalFileSystem localFileSystem = FileSystem.getLocal(new Configuration());
//4:获取本地文件夹下所有文件的详情
FileStatus[] fileStatuses = localFileSystem.listStatus(new Path("D:\\input"));
//5:遍历每个文件,获取每个文件的输入流
for (FileStatus fileStatus : fileStatuses) {
FSDataInputStream inputStream = localFileSystem.open(fileStatus.getPath());
//6:将小文件的数据复制到大文件
IOUtils.copy(inputStream, outputStream);
IOUtils.closeQuietly(inputStream);
}
//7:关闭流
IOUtils.closeQuietly(outputStream);
localFileSystem.close();
fileSystem.close();
}
漫步在广阔无垠的草原上的感觉是如此的美妙,一个少年的成长故事还在继续.....