Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统
前言
我们知道HDFS集群中,所有的文件都是存放在DN的数据块中的。那我们该怎么去查看数据块的相关属性的呢?这就是我今天分享的内容了
一、HDFS中数据块概述
1.1、HDFS集群中数据块存放位置
我们知道hadoop集群遵循的是主/从的架构,namenode很多时候都不作为文件的读写操作,只负责任务的调度和掌握数据块在哪些datanode的分布,
保存的是一些数据结构,是namespace或者类似索引之类的东西,真正的数据存储和对数据的读写是发生在datanode里的。
找到${HADOOP_HOME}/ect/hadoop/hdfs-site.xml文件,里面有你自己定义的dfs.datanode.data.dir一项就是你数据存放的位置。
此外我们还可以通过Web控制页面(http://master:50070)的hdfs查看你所存放的所有数据文件,而且更加的清晰简洁,包括文件的名称,用了多少个数据块存储,数据块的id,每个数据块写入数据的大小。
1.2、数据块(data block)简介
每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位,构建于单个磁盘之上的文件系统通过磁盘块来管理该文件系统中的块,该文件系统块的大小可以是磁盘块的整数倍。
HDFS同样也有块的概念,但是大得多,默认为128MB(2.0以前是64MB)。与单一磁盘上的文件系统相似,HDFS上的文件也被划分为多个分块,作为独立的存储单元。
与其他文件系统不同的是,HDFS中小于一个块大小的文件不会占据整个块的空间。
1.3、对分布式文件系统中的块进行抽象会带来很多好处
1)第一个明显的好处是,一个文件的大小可以大于网络中任意一个磁盘的容量。文件的所有块并不需要存储在同一个磁盘上,因此他们可以利用集群上的任意一个磁盘进行存储。 2)第二个好处是,使用块抽象而非整个文件做为存储单元,大大简化了存储子系统的设计。简化是所有系统的目标,但是这对于故障种类繁多的分布式系统来说尤为重要。
将存储子系统控制单元设置为块,可简化存储管理(由于块的大小是固定的,因此计算单个磁盘能够存储多少个块相对容易)。同时也消除了对元数据的顾虑(块只是存储数据的一部分---而文件的元数据,
如权限信息,并不需要与块一同存储,这样一来,其他的系统就可以单独管理这些元数据)。 3)块非常适合用于数据备份进而提供数据容错能力和可用性。将每个块复制到少数几个独立的机器上(默认为3个),可以确保在发生块、磁盘或机器故障后数据不会丢失。
如果发现一个块不可用,系统会从其他地方读取另一个复本,而这个过程对用户是透明的。
注意:HDFS中的文件都是一次性写入的,并且严格要求在任何时候只能有一个写入者。
二、Java访问HDFS中的数据块
2.1、相关类和方法介绍
Hadoop关于HDFS中的数据块相关类 org.apache.hadoop.hdfs.protocol包下。(不知道为什么在2.8的api中查询不到,所以我只能通过IDEA去看源码)
1)ExtendedBlock类(通过LocatedBlock的getBlock()方法获取)
public String getBlockName() {}
这里主要是得到数据块的名字和id。
2)DatanodeInfo类
这里列举部分属性
public String getIpAddr() {}
public String getHostName() {}
3)LocatedBlock
public ExtendedBlock getBlock(){}
public long getBlockSize() {}
2.2、编写程序访问
1)使用方法
在 HdfsDataInputStream中:获取所有数据块信息
2)ListBlocks_0010
import java.net.URI;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.HdfsDataInputStream;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class ListBlocks_0010
extends Configured
implements Tool{
@Override
public int run(String[] args) throws Exception{
Configuration conf=getConf();
String input=conf.get("input");
FileSystem fs=
FileSystem.get(
URI.create(input),conf);
HdfsDataInputStream hdis=
(HdfsDataInputStream)
fs.open(new Path(input));
List<LocatedBlock> allBlocks=
hdis.getAllBlocks();
for(LocatedBlock block:allBlocks){
ExtendedBlock eBlock=
block.getBlock();
System.out.println("------------------------");
System.out.println(
eBlock.getBlockId());
System.out.println(
eBlock.getBlockName());
System.out.println(
block.getBlockSize());
System.out.println(
block.getStartOffset());
// 获取当前的数据块所在的DataNode的信息
DatanodeInfo[] locations=
block.getLocations();
for(DatanodeInfo info:locations){
System.out.println(
info.getIpAddr());
System.out.println(
info.getHostName());
}
}
return 0;
}
public static void main(String[] args) throws Exception{
System.exit(
ToolRunner.run(
new ListBlocks_0010(),args));
}
}
3)测试
在安装了Hadoop客户端的服务器中执行:
结果:
这里解释一下偏移量:
数据块的偏移量是指一个数据块距离一个文件开始的偏移位置(从上图中可以分析出来)
二、Java查看HDFS集群文件系统
我们怎么去查看HDFS文件系统呢?我们可以通过FileSystem类中
1.1、相关类和方法
1)FileStatus类
FileStatus类封装文件和目录的文件系统元数据,包括文件长度,块大小,复制,修改时间,所有权和许可信息。 FileSystem上的getFileStatus()方法提供了一种获取FileStatus的方法对象为单个文件或目录。
getAccessTime() //上次访问的时间
getOwner() //文件的所有者
getGroup() //文件的所属者
getPath() //得到文件的路径
getPermission() //文件的权限
getReplication() //文件的备份数
2)FileSystem中的类
public FileStatus[] listStatus(Path f)throws IOException;
public FileStatus[] listStatus(Path f, PathFilter filter)throws IOException;
public FileStatus[] listStatus(Path[] files)throws IOException;
public FileStatus[] listStatus(Path[] files, PathFilter filter)throws IOException;
2.2、编写程序访问
1)核心代码
import java.io.IOException;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class ListFileStatus_0010
extends Configured
implements Tool{
FileSystem fs;
@Override
public int run(String[] args) throws Exception{
Configuration conf=getConf();
String input=conf.get("input");
fs=FileSystem.get(
URI.create(input),conf);
FileStatus[] fileStatuses=
fs.listStatus(new Path(input));
for(FileStatus status:fileStatuses){
process(status);
}
return 0;
}
public void process(
FileStatus fileStatus) throws IOException{
if(fileStatus.isFile()){
System.out.println("--------------");
System.out.println(
fileStatus.getAccessTime()); //上次访问的时间
System.out.println(
fileStatus.getOwner()); //文件的所有者
System.out.println(
fileStatus.getGroup()); //文件的所属者
System.out.println(
fileStatus.getPath()); //得到文件的路径
System.out.println(
fileStatus.getPermission()); //文件的权限
System.out.println(
fileStatus.getReplication()); //文件的备份数
}else if(fileStatus.isDirectory()){
// 和Java的File不一样的地方:
// 当File对象所代表的是目录的时候,
// 可以通过listFiles方法来获取该目录下的所有文件(有可能还包含目录)
// 在HDFS中,当FileStatus对象代表一个目录的时候
// 没有相应的方法来获取该目录下的所有文件
// 要通过FileSystem类来获取该目录下的文件
// path=fileStatus.getPath();
// FileStatus[] fileStstuses=
// fs.listStatus(path);
FileStatus[] fileStatuses=
fs.listStatus(fileStatus.getPath());
for(FileStatus status:fileStatuses){
process(status);
}
}
}
public static void main(String[] args) throws Exception{
System.exit(ToolRunner.run(new ListFileStatus_0010(),args));
}
}
2)测试
我们先运行一个文件:
我们运行一个目录:有n多的文件,并且做了递归调用
喜欢就点个“推荐”哦!
- Docker容器学习梳理--容器登陆方法梳理(attach、exec、nsenter)
- java学习:调用 java web service
- java学习:数据增删改查、存储过程调用及事务处理
- 极客手工:自制51四驱无线遥控小车
- flash:二次贝塞尔曲线应用-生成飞机路径示意图
- 微信小程序重磅功能上线!一键连Wi-Fi/手机变门禁卡
- MySQL下载安装、基本配置、问题处理
- windows下命令行模式中cd命令无效的原因
- 分布式和集群区别?什么是云计算平台?分布式的应用场景?
- 中国移动也要搞自动驾驶,没了SIM卡怎么耍花样?
- python并发编程之多进程理论部分
- 使用concurrent.futures模块并发,实现进程池、线程池
- 人工智能与医疗
- 每周论文清单:知识图谱,文本匹配,图像翻译,视频对象分割
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ggstatsplot绘图|统计+可视化,学术科研神器
- 用python下载哔哩哔哩视频?
- 数据处理|数据查重怎么办?去重,就这么办!
- FFmpeg合并MP4文件
- Broom |tidy up a bit,模型,检验结果一键输出!
- 今日算法题-动态规划法
- 3分钟短文 | PHP获取函数的代码片段,唯有反射最高效!
- ggforce|绘制区域轮廓-区域放大-寻找你的“onepiece”
- 基因矩阵转置文件格式(* .gmt)
- gganimate|创建可视化动图,让你的表会说话
- ggplot2|玩转Manhattan图-你有被要求这么画吗?
- deconstructSigs|探寻cosmic的独特“气质”-mutation signature !
- barplot3d|圣诞节送你一个mutation signature搭建的“乐高”
- R读取gmt文件
- 一个画双层pie图的函数