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

[经验分享] Hadoop学习笔记(3) Hadoop文件系统一

[复制链接]

尚未签到

发表于 2017-12-16 20:30:44 | 显示全部楼层 |阅读模式
  1. 分布式文件系统,即为管理网络中跨多台计算机存储的文件系统。HDFS以流式数据访问模式来存储超大文件,运行于商用硬件集群上。HDFS的构建思路为:一次写入、多次读取是最高效的访问模式。数据集通常由数据源生成或从数据源赋值而来,接着长时间在此数据集上进行各类分析。每次分析都涉及该数据集的大部分数据甚至全部,因此读取整个数据集的时间延迟比第一条记录的时间延迟更重要。
  2. HDFS是为高数据吞吐量应用优化的,这可能会以高时间延迟为代价。目前,对于低延迟的访问需求,HBase是更好的选择。
  3. HDFS的块默认为64M,与单一磁盘上的文件系统相似,HDFS上 的文件也被划分为块大小的多个分块(chunk),作为独立的存储单元。不同的是HDFS中小于一个块大小的文件不会占据整个块的空间。HDFS的块比磁盘大,目的是为了最小化寻址开销。如果块设置得足够大,从磁盘传输数据的时间可以明显大于定位这个块开始位置所需的时间。这样,传输一个由多个块组成的文件的时间取决于磁盘的传输速率。
  4. 对分布式文件系统中的块进行抽象会带来很多好处。1) 一个文件的大小可以大于网络中任意一个磁盘的容量;2) 使用块抽象而非整个文件作为存储单元,大大简化了存储子系统的设计。3) 块非常适合用于数据备份进而提供数据容错能力和可用性。将每个块复制到少数几个独立的机器上(默认为3个),可以确保在发生块、磁盘或机器故障后数据不丢失。如果发现一个块不可用,系统会从其他地方读取另一个副本,而这个过程对用户是透明的。一个因损坏或机器故障而丢失的块可以从其他候选地点复制到另一台可以正常运行的机器上,以保证复本的数量回到正常水平。HDFS中的fsck指令可以显示块的信息。% hadoop fsck / -files -blocks将列出文件系统中各个文件由哪些块构成。
  5. HDFS集群有两类节点,并以管理者-工作者模式运行,即一个namenode(管理者)和多个datanode(工作者).
  (1) namonode管理文件系统的命名空间。它维护着文件系统树及整棵树内所有的文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件和编辑日志文件。namenode也记录着每个文件中各个块所在的数据节点信息,但它不会永久保存块的位置信息。因为这些信息会在系统启动时由数据节点重建。
  (2) 客户端代表用户通过与namenode和datanode交互来访问整个文件系统。
  (3) datanode是文件系统的工作节点。它们根据需要存储并检索数据块(受客户端或namenode调度),并且定期向namenode发送它们所存储的块的列表。
  6. 没有namenode,文件系统将无法使用,因此对namenode实现容错非常重要,Hadoop为此提供了两种机制:
  (1) 备份那些组成文件系统元数据持久状态的文件。Hadoop可通过配置使namenode在多个文件系统上保存元数据的持久状态,这些写操作是实时同步的,一般的配置是,将持久状态写入本地磁盘的同时,写入一个远程挂载的网络文件系统(NFS)。
  (2) 运行一个辅助namenode,但它不能被用作namenode。其作用是定期通过编辑日志并命名空间镜像,以防止编辑日志过大,且一般在另一台单独的物理计算机上运行。它会保存合并后的命名空间镜像的副本,并在namenode发生故障时启用。但,辅助namenode保存的状态总是滞后于主节点,所以在主节点全部失效时,难免会丢失部分数据。在这种情况下,一般把存储在NFS上的namenode元数据复制到辅助namenode并作为新的主namenode运行。
  7. 基本文件系统操作
  可以通过hadoop fs -help命令获取所有命令的详细帮助文件。
  (1) 从本地文件系统将一个文件复制到HDFS。
  %hadoop fs -copyFromLocal input/docs/quangle.txt hdfs://localhost/user/tom/quangle.txt
  该命令调用Hadoop文件系统的shell命令fs,本地文件quangle.txt被复制到运行在localhost上的HDFS实例中,路径为/user/tom/quangle.txt。事实上,可以简化命令格式以省略主机的URI并使用默认设置,即省略hdfs://localhost,因为该项已在core-site.xml中指定。
  %hadoop fs -copyFromLocal input/docs/quangle.txt /user/tom/quangle.txt
  也可以使用相对路径,并将文件复制到HDFS的home目录中,本例中为/usr/tom
  %hadoop fs -copyFromLocal input/docs/quangle.txt quangle.txt
  我们将文件复制回本地文件系统,并检查是否一致:
  % hadoop fs -copyToLocal quangle.txt quangle.copy.txt
  % md5 input/docs/quangle.txt quangle.copy.txt
  由于MD5键值相同,表明这个文件在HDFS之旅中得以幸存并保存完整。
  (2) 创建一个目录看它zai列表中是如何显示的:
  % hadoop fs -mkdir books
  % hadoop fs -ls .
  返回的结果与Linux的ls -l的输出结果很相似,不同之处在于第2列是这个文件的备份数。由于在整个文件系统范围内设置的默认复本数为1,所以这里显示的也都是1,。新建的目录为空,因为本例中没有使用复本的概念-目录作为元数据保存在namenode中,而非datanode中。
  8. Hadoop文件系统
  HDFS只是Hadoop的一个实现。Java抽象类org.apache.hadoop.fs.FileSystem定义了Hadoop中的一个文件系统接口。

文件系统
URI方案
Java实现
描述
Local
file
fs.LocalFileSystem
使用了客户端检验和的本地磁盘文件系统。没有使用校验和的本地磁盘文件系统RawLocalFileSystem
HDFS
hdfs
hdfs.DistributedFileSystem
Hadoop的分布式文件系统,将HDFS设计成与MapReduce结合使用,可以实现高性能
HFTP
Hftp
hdfs.hftpFileSystem
一个在HTTP上提供对HDFS只读访问的文件系统,通常与distcp结合使用,以实现并运行不同版本的HDFS的集群之间复制数据
HSFTP
hsftp
hdfs.HsftpFileSystem
在HTTPS上提供对HDFS只读访问的文件系统
HAR
har
fs.HarFileSystem
一个构建在其他文件系统之上用于文件存档的文件系统。Hadoop存档文件系统通常用于需要将HDFS中的文件进行存档时,以减少namenode内存的使用
hfs(云存储)
kfs
fs.kgs.kosmosFileSystem
CloudStore是类似于HDFS或是谷歌的GFS文件系统
FTP
ftp
fs.ftp.FTPFileSystem
由FTP服务器支持的文件系统
s3(原生)
s3n
fs.s3native.NativeS3FileSystem
由Amazon S3支持的文件系统
s3(基于块)
s3
fs.sa.S3FileSystem
由Amazon S3支持的文件系统,以块格式存储文件以解决S3的5GB文件大小限制  Hadoop对文件系统提供了很多接口,一般使用URI方案来选取合适的文件系统实例进行交互。例:要想列出本地文件系统根目录下的文件,输入命令:
  %hadoop fs file:///
  9 Hadoop文件系统的接口是通过Java API提供的,所以其他非Java应用程序访问Hadoop文件系统会比较麻烦。thriftfs定制功能模块中的Thrift API通过把Hadoop文件系统包装一个Apache Thrift服务来弥补这个不足,从而使任何具有Thrift绑定的语言都能轻松地与Hadoop文件系统进行交互。
  10 Hadoop提供了一个名为libhdfs的C语言库,该语言库是Java FileSystem接口类的一个镜像。它可以使用Java原生接口(JNI)调用Java文件系统客户端。
  11 用户空间文件系统(Filesystem in Userspace,FUSE)允许把按照用户空间实现的文件系统整合成一个Unix文件系统,通过使用Hadoop的Fuse-DFS功能模块,任意一个Hadoop文件系统均可以作为一个标准文件系统进行挂载。
  12 Java接口:与Hadoop的某一文件系统进行交互的API。
  (1) 从Hadoop URL中读取数据
  最简单的方法是使用java.net.URL对象打开数据流,进而从中读取数据。
  例:通过URLStreamHandler实例以标准输出方式显示Hadoop文件系统的文件
  

public>
static {  

// JVM只能调用一次该方法,因此第三方组件如已声明一个URLStreamHandlerFactory实例  

// 将无法再使用该方法从Hadoop中读取数据  
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
  
}
  

  
public static void main(String[] args) throws Exception{
  
InputStream in = null;
  
try{
  
in = new URL(args[0]).openStream();
  
// 输入流和输出流之间复制数据
  
// 4096-设置复制的缓冲区大小,flase-设置复制结束后是否关闭数据流
  
IOUtils.copyBytes(in,System.out,4096,false);
  
}finally{
  
IOUtils.closeStream(in);
  
}
  
}
  
}
  

  下面是一个运行示例:
  % hadoop URLCat hdfs://localhost/user/tom/quangle.txt
  (2) 通过FileSystem API读取数据
  Hadoop文件系统中通过Hadoop Path对象来代表文件,你可以将一条路径视为一个Hadoop文件系统URI。
  获取FileSystem实例有两种方法:
  

public static FileSystem get(Configuration conf) throws IOException  

public static FileSystem get(URI uri,Configuration conf) throws IOException  

  Configuration对象封装了客户端或服务器的配置,通过设置配置文件读取类路径来实现(如conf/core-site.xml)。第一个方法返回的是默认文件系统,第二个方法通过给定的URI方案和权限来确定要使用的文件系统。
  有了FileSystem实例后,可调用open函数来读取文件的输入流:
  

public FSDataInputStream open(Path f) throws IOException  

public abstract FSDataInputStream open(Path f, int bufferSize) throws IOException  

  例:直接使用FileSystem以标准格式显示Hadoop文件系统中的文件
  

public>
public static void main(String[] args) throws IOExcption{  
String uri
= args[0];  
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);
  
}
  
}
  
}
  

  运行示例:
  % hadoop FileSystemCat hdfs://localhost/user/tom/quangle.txt
  FileSystem对象中的open()方法返回的是FSDataInputStream对象,该类继承了java.io.DataInputStream接口,并支持随机访问,由此可从流的任意位置读取数据。
  

package org.apache.hadoop.fs;  

public>
implements Seekable,PositionedReadable{  

  
}
  

  Seekable接口支持在文件中找到指定位置,并提供一个查询当前位置相对于文件起始位置偏移量的查询方法getPos()。
  

public interface Seekable{  

void seek(long pos) throws IOException;  

long getPos() throws IOException;  

boolean seekToNewSource(long targetPos) throws IOException;  
}
  

  调用seek()定位大于文件长度的位置会导致IOException异常,与java.io.InputStream中的skip()不停,seek()可以移到文件中任意一个绝对位置,skip()则只能相对于当前位置定位到另一个新位置。
  例:将一个文件写入标准输出两次:在第一次写完之后,定位到文件的起始位置再次以流方式读取该文件。
  

public>
String uri = args[0];  
Configuration conf
= new Configuration();  
FileSystem fs
= FileSystem.get(URI.create(uri),conf);  
FSDataInputStream in
= null;  

try{  
in
= fs.open(new Path(uri));  
IOUtils.copyBytes(in,System.out,
4096,false);  
in.seek(
0);  
IOUtils.copyBytes(in,System.out,
4096,false);  
}
finally{  
IOUtils.closeStream(in);
  
}
  
}
  

  运行示例:
  % hadoop FileSystemDoubleCat hdfs://local/user/tom/quangle.txt
  FSDataInputStream也继承了PositionedReadble接口,从一个指定偏移量处读取文件的一部分:
  

public interface PositionedReadable{  

public int read(long position, byte[] buffer, int offset, int length) throws IOException;  

public void readFully(long position, byte[] buffer, int offset, int length) throws IOException;  

public void readFully(long position, byte[] bufer) throws IOException;  
}
  

  read()方法从文件的指定position处读取至多为length字节的数据并存入缓冲区buffer指定的偏移量offset处。返回的是实际读到的字节数。
  所有这些方法会保留当前偏移量,因此它们提供了在读取文件-可能是元数据-的主体时访问文件的其他部分的便利方法。
  13 写入数据
  最简单的方法是给准备创建的文件指定一个Path对象,然后返回一个用于写入数据的输出流。
  

public FSDataOutputStream create(Path f) throws IOException;  

  还有一个重载方法Progressable,用于传递回调接口,如此一来,可以把数据写入数据节点的进度通知到你的应用:
  

package org.apache.hadoop.util;  

public interface Progressable{  

public void progress();  
}
  

  另一个新建文件的方法是使用append()方法在一个已有文件末尾追加数据:
  

public FSDataOutputStream append(Path f) throws IOException  

  该追加操作允许一个writter打开文件后在访问文件的最后偏移量处追加数据。该API可以时某些应用创建无边界文件。
  例:显示如何将本地文件复制到Hadoop文件系统,每次Hadoop调用progress()方法时,打印一个时间点来显示整个运行过程。
  

public>
public static void main(String[] args) throws IOException{  
String localSrc
= args[0];  
String dst
= args[1];  

  
InputStream in
= new BufferedInputStream(new FileInputStream(localSrc));  

  
Configuration conf
= new Configuration();  
FileSystem fs
= FileSystem.get(URI.create(dst),conf);  

  
OutputStream out
= fs.create(new Path(dst),new Progressable(){  

public void progress(){  
System.out.print(
".");  
}
  
});
  

  
IOUtils.copyBytes(in,out,
4096,true);  
}
  
}
  

  运行示例:
  % hadoop FileCopyWithProgress input/docs/1400-8.txt hdfs://localhost/user/tom/1400-8.txt
  FSDataOutputStream也有一个查询文件当前位置的方法:
  

package org.apache.hadoop.fs;  

public>
implements Syncable{  

public long getPos() throws IOException{  

  
}
  
}
  

  FSDataOutputStream类不允许在文件中定位,因为HDFS只允许对一个已打开的文件顺序写入或在现有文件的末尾追加数据。
  14 FileSystem实例提供了创建目录的方法:
  

boolean mkdirs(Path f) throws IOException  

  该方法可以一次性新建所有必要但还没有的父目录,如果目录都已创建成功,则返回true。

运维网声明 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-424822-1-1.html 上篇帖子: Hadoop-hdfs安装与配置 下篇帖子: 介绍hadoop中的hadoop和hdfs命令
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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