设为首页 收藏本站
查看: 1227|回复: 0

[经验分享] Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统

[复制链接]

尚未签到

发表于 2017-12-18 13:44:53 | 显示全部楼层 |阅读模式
  前言
  我们知道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,每个数据块写入数据的大小。
DSC0000.png


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() {}  

public long getBlockId() {}  

  这里主要是得到数据块的名字和id。
  2)DatanodeInfo类
  这里列举部分属性
DSC0001.png

  

  public String getIpAddr() {}  

public String getHostName() {}    

  3)LocatedBlock
  

public ExtendedBlock getBlock(){}  public
long getBlockSize() {}  

public long getStartOffset() {}  //这个数据块距离这个文件的偏移量  

public DatanodeInfo[] getLocations() {}  // 获取当前的数据块所在的DataNode的信息       


2.2、编写程序访问
  1)使用方法
  在 HdfsDataInputStream中:获取所有数据块信息
DSC0002.png

  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>
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客户端的服务器中执行:
DSC0003.png

  结果:
DSC0004.png DSC0005.png

  这里解释一下偏移量:
  数据块的偏移量是指一个数据块距离一个文件开始的偏移位置(从上图中可以分析出来)
DSC0006.png   


二、Java查看HDFS集群文件系统
  我们怎么去查看HDFS文件系统呢?我们可以通过FileSystem类中

1.1、相关类和方法
  1)FileStatus类
DSC0007.png

  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>
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)测试
  我们先运行一个文件:
DSC0008.png

  我们运行一个目录:有n多的文件,并且做了递归调用
DSC0009.png

DSC00010.png

  喜欢就点个“推荐”哦!    

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-425393-1-1.html 上篇帖子: Windows平台开发Mapreduce程序远程调用运行在Hadoop集群 下篇帖子: Hadoop 新生报道(二) hadoop2.6.0 集群系统版本安装和启动配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表