Hadoop入门篇02---HDFS学习与简单使用
- 存储系统概念
- 认识硬盘,RAID
- 小结
- 存储架构
- DAS,NAS,SAN对比
- 文件系统
- 大数据存储
- 大数据存储面临的问题
- 如何解决
- 小结
- HDFS
- HDFS的起源和发展
- HDFS的设计目标
- HDFS的应用场景
- HDFS的特性
- 命令行实践
- 常用命令
- Java客户端API使用
- 环境准备
- 踩坑实录
- 第一个坑: 无法通过外网访问nameNode节点监听的8020端口
- 第二个坑: dfs.client.use.datanode.hostname配置的作用到底是什么
- 第三个坑: 客户端没有权限
- CRUD实践
存储系统概念
认识硬盘,RAID
硬盘:
- 硬盘(Hard Disk Drive,缩写为HDD)是一种用于存储计算机数据的永久性储存设备。硬盘通常由一组旋转的磁盘(也称为盘片)组成,每个磁盘上都有一个读写头,可以在磁盘表面上读取和写入数据。
- 当计算机需要访问硬盘上的数据时,读写头会移动到磁盘表面上的指定位置,并读取或写入数据。硬盘的存储容量通常以GB(千兆字节)或TB(万亿字节)为单位,可以存储大量的数据,包括操作系统、应用程序、文档、照片、视频和音频文件等。
- 尽管现在固态硬盘(Solid State Drive,SSD)已经逐渐取代了传统硬盘,但是硬盘仍然是一种可靠、高容量、低成本的存储设备,被广泛应用于个人电脑、服务器、数据中心等场合。
机械硬盘:
- 机械硬盘(Mechanical Hard Disk Drive,缩写为HDD)是一种传统的硬盘类型,它是计算机存储设备中最常见和最古老的类型之一。它由一个或多个磁盘和一个机械臂组成,机械臂上带有读写头,可以在磁盘表面上读写数据。
- 磁盘是由金属或玻璃等材料制成的圆盘,其表面涂有磁性材料。读写头通过机械臂在磁盘表面上移动,读取和写入磁性材料中存储的数据。硬盘的转速通常是5400rpm、7200rpm或10000rpm,转速越高,读写速度越快。
- 机械硬盘是一种可靠的存储设备,容量较大,价格相对较低,但是由于其内部机械部件的运作,存在寿命限制和故障率高的问题。与现代的固态硬盘相比,机械硬盘的读写速度较慢,能耗较高,并且在移动设备等场景下不太适用。
固态硬盘:
- 固态硬盘(Solid State Drive,缩写为SSD)是一种新型的硬盘类型,它采用了固态存储器来存储数据,相对于传统的机械硬盘具有更快的读写速度、更低的能耗和更长的使用寿命。
- 固态硬盘的存储介质是闪存芯片,它可以通过电子信号来读取和写入数据,而不需要像机械硬盘一样依靠旋转的磁盘和机械臂。由于没有机械部件,固态硬盘具有更高的抗震性和更低的噪音。此外,固态硬盘在随机读写操作(如启动操作系统、打开应用程序等)方面比机械硬盘快得多。
- 固态硬盘的容量通常以GB或TB为单位,目前最大的固态硬盘容量已经超过20TB。尽管固态硬盘的价格相对较高,但随着技术的进步和生产规模的扩大,价格正在逐步降低。固态硬盘已经广泛应用于笔记本电脑、平板电脑、智能手机、服务器和数据中心等领域。
混合硬盘:
- 混合硬盘(Hybrid Hard Disk Drive,缩写为HHD)是一种介于机械硬盘和固态硬盘之间的硬盘类型。它的设计思想是在机械硬盘的基础上加入了一个小型的固态存储器,用于存储频繁访问的数据。
- 混合硬盘的工作原理是将频繁访问的数据缓存在固态存储器中,以便快速读取。一旦频繁访问的数据被缓存到固态存储器中,就可以更快地访问和处理这些数据,从而提高硬盘的读写速度。
- 混合硬盘的固态存储器容量通常在8GB到64GB之间,价格相对于固态硬盘要低廉。混合硬盘的读写速度相对于机械硬盘有一定的提升,但与真正的固态硬盘相比仍有一定差距。混合硬盘通常被用于需要大容量存储同时又需要一定读写速度的场合,如一些游戏、多媒体、服务器等应用场景。
RAID:
- RAID(Redundant Array of Independent Disks)是一种数据存储技术,通过将多个磁盘组合起来,提供更高的数据可靠性、容错能力和性能。
- RAID可以将多个磁盘组合成一个逻辑磁盘,称为RAID组。RAID组可以采用多种不同的方式来存储和保护数据,其中最常见的有以下几种:
- RAID 0:将多个磁盘组合成一个大的逻辑磁盘,提高数据传输速度。RAID 0将数据块分割成较小的块,然后交替写入各个磁盘中,以实现并行访问,提高读写速度。但是,RAID 0没有冗余数据,任何一个磁盘出现故障都会导致整个RAID组的数据丢失。
- RAID 1:将多个磁盘进行镜像备份,即数据同时写入两个或多个磁盘中,提高数据可靠性和容错能力。RAID 1对数据进行完全复制,可以在任何一个磁盘出现故障时继续工作,但需要更多的磁盘空间,且写入速度较慢。
- RAID 5:将多个磁盘组合成一个逻辑磁盘,其中一部分空间用于存储校验数据,提高数据可靠性和容错能力。RAID 5采用奇偶校验方式,将每个数据块分割成多个子块,每个子块存储在不同的磁盘中,同时计算一个校验块,存储在其他磁盘中。如果其中一个磁盘出现故障,RAID 5可以通过校验块来恢复数据。RAID 5可以提供较高的性能和容错能力,但在重建磁盘时会影响读写性能。
- RAID 6:类似于RAID 5,但提供更高的容错能力。RAID 6采用双重奇偶校验方式,可以在两个磁盘故障的情况下继续工作,但需要更多的磁盘空间。
- RAID 10:将多个磁盘组合成多个RAID 1阵列,然后组合成一个RAID 0阵列。RAID 10提供了较高的读写性能和容错能力,但需要更多的磁盘空间。
- RAID 50:将多个RAID 5阵列组合成一个RAID 0阵列。RAID 50提供了较高的性能和容错能力,但需要更多的磁盘空间。
RAID技术可以应用于各种数据存储场景,如服务器、网络存储设备、工作站等。RAID技术通过提供更高的数据可靠性和容错能力,保障了数据的安全性和可靠性,提高了数据访问速度和处理能力,提高了数据存储系统的整体性能。
此处推荐大家阅读操作系统导论第38章进行学习:
小结
- 磁盘是计算机主要的存储介质,可以存储大量的二进制数据,并且断电后也能保持数据不丢失。
- 早期计算机使用的磁盘是软磁盘(Floppy Disk,简称软盘),如今常用的磁盘是硬磁盘(Hard disk,简称硬盘)
- 硬盘分为HDD、SSD、SSHD
- 磁盘阵列(RAID):多块磁盘的组合体,实现不同存储功能
存储架构
- DAS存储架构
- Direct-Attached Storage(DAS)是指直接连接到服务器或工作站的存储设备,例如硬盘、固态硬盘、磁带机等。与网络存储(如NAS和SAN)不同,DAS直接连接到主机上,可以提供更快的数据传输速度和更低的延迟。
- DAS通常通过SATA、SAS或USB等接口连接到主机上,这些接口支持高速数据传输,并且可以使用硬件RAID或软件RAID等技术提供数据冗余和可靠性保护。DAS设备通常被用作本地数据存储,例如用于存储操作系统、应用程序和用户数据等。
- DAS的主要优点是易于安装和管理,成本相对较低,不需要额外的网络设备或复杂的管理软件。此外,DAS可以提供非常高的性能,适用于需要快速读写大量数据的应用场景,例如视频编辑、数据备份和高性能计算等。
- DAS的主要缺点是存储容量和扩展性受限于主机本身的限制。此外,DAS设备通常只能被单个主机访问,无法在多个主机之间共享数据,这在某些应用场景下可能会导致数据共享和管理上的问题。
- NAS网络接入存储
- Network-Attached Storage(NAS)是指通过网络连接到计算机或服务器的存储设备,可以在网络上提供文件存储和共享服务。NAS设备通常包括一个或多个硬盘驱动器、固态硬盘或磁带机,它们通过网络连接到本地网络或互联网上的计算机、服务器或其他网络设备。
- NAS设备提供了许多优点,例如:
- 简单易用:NAS设备易于安装、配置和管理,用户只需连接到网络并配置适当的网络设置即可开始使用。
- 高可靠性:NAS设备通常采用RAID(独立磁盘冗余阵列)技术,提高数据的可靠性和安全性。
- 资源共享:多个用户可以同时访问NAS设备上的数据和文件,实现资源共享和协作。
- 可扩展性:通过添加额外的硬盘驱动器或扩展单元,可以轻松扩展存储容量和性能。
- 远程访问:NAS设备可以通过互联网进行远程访问,用户可以随时随地访问其存储的文件和数据。
- 尽管NAS设备提供了许多优点,但也存在一些限制。例如,NAS的性能受网络带宽的限制,因此在处理大量数据和高并发访问时可能会出现性能瓶颈。此外,由于NAS设备直接暴露在网络上,安全性也是一个关键问题,因此必须采取适当的安全措施来保护存储设备和数据。
- SAN 存储区域网络存储
- Storage Area Network(SAN)是一种高性能、高可靠性的存储解决方案,它通过专用的网络连接存储设备和服务器,提供高速数据传输和资源共享服务。SAN通常由多个存储设备、交换机、主机适配器等组成。
- SAN的主要特点包括:
- 高性能:SAN使用高速网络连接,可提供非常高的数据传输速率和I/O性能。
- 高可靠性:SAN采用冗余设计,包括双路电源、双控制器、RAID等技术,提高数据的可靠性和安全性。
- 资源共享:SAN可以让多个服务器共享存储设备上的数据,实现资源共享和协作。
- 可扩展性:SAN可以轻松扩展存储容量和性能,支持在线添加存储设备和扩展存储容量。
- 高灵活性:SAN支持多种不同的协议和拓扑结构,可以根据不同的应用需求进行定制。
- SAN主要适用于大规模数据中心和企业级应用场景,如数据库、虚拟化、云计算等,对于对性能、可靠性和可扩展性要求较高的应用非常适合。然而,SAN的价格相对较高,安装和管理也相对复杂,需要专业的技术支持和管理。
DAS,NAS,SAN对比
这里重点讲解一下NAS和SAN的区别:
- SAN和NAS都是用于存储和共享数据的解决方案,但它们的架构和应用场景有所不同。
- 架构不同
- SAN采用专用网络连接存储设备和服务器,通常使用高速光纤通道(FC)协议进行数据传输。数据存储和管理是在SAN存储设备上完成的,因此SAN可以提供高性能、高可靠性和灵活性。
- NAS则是基于普通网络(如以太网)连接存储设备和服务器,使用网络文件系统(NFS)或Server Message Block(SMB)等协议进行数据传输。数据存储和管理是在NAS设备上完成的,因此NAS具有易用性和低成本等优点。
- 应用场景不同
- SAN主要适用于对性能和可靠性要求非常高的应用场景,如数据库、虚拟化和云计算等,可以为多个服务器提供高速数据传输和存储共享。
- NAS则更适合用于小型和中型企业、分布式环境和远程办公场景等,因为它易于管理、可扩展、价格相对较低,而且可以提供文件级别的共享服务。
- 管理和部署不同
- SAN通常需要专业的技术支持和管理,需要经验丰富的IT团队进行部署和维护。而NAS则较为易于部署和管理,用户可以自行完成基本的安装和配置。
总的来说,SAN和NAS是两种不同的存储方案,它们各有优缺点和适用场景。选择合适的存储方案应该根据企业的实际需求和预算来决定。
文件系统
文件系统:
- 是一种存储和组织数据的方法,它使得对文件访问和查找变得容易
- 使用文件和树形目录的抽象逻辑概念代替了硬盘等物理设备使用数据块的概念,用户使用文件系统来保存数据,不必关心数据底层存在硬盘哪里,只需要记住这个文件的所属目录和文件名。
- 文件系统通常使用硬盘和光盘这样的存储设备,并维护文件在设备中的物理位置。
- 文件系统是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型(Abstract data type)。
文件名:
- DOS操作系统中文件名由文件主名和扩展名组成,之间以一个小圆点隔开
- 文件名可用于用于定位存储位置、区分不同文件,计算机实行按名存取的操作方式
- 某些符号因有其特殊含义,一般不允许出现在文件名中
元数据:
- 元数据(metadata)又称之为解释性数据,记录数据的数据
- 文件系统元数据一般指文件大小、最后修改时间、底层存储位置、属性、所属用户、权限等信息
文件系统分类:
- 基于磁盘的文件系统
- 是在非易失介质上(磁盘、光盘)存储文档的经典方式。用以在多次会话之间保持文件的内容。包括Ext2/3/4、XFS、NTFS、FAT和iso9660等众所周知的文件系统。Linux中可以使用df -Th查看。
- 虚拟文件系统
- 在内核中生成的文件系统,比如proc。
- proc文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。
- 网络文件系统
- 网络文件系统(NFS,Network File System)是一种将远程主机上的分区(目录)经网络挂载到本地系统的一种机制。
允许本地计算机访问另一台计算机上的数据,对此类文件系统中文件的操作都通过网络连接进行。
大数据存储
大数据存储面临的问题
- 成本高
- 传统存储硬件通用性差,设备投资加上后期维护、升级扩容的成本非常高。
- 性能低
- 单节点I/O性能瓶颈无法逾越,难以支撑海量数据的高并发高吞吐场景。
- 可扩展性差
- 无法实现快速部署和弹性扩展,动态扩容、缩容成本高,技术实现难度大。
- 如何支撑高效率的计算分析
- 传统存储方式意味着数据存储是存储,计算是计算,当需要处理数据的时候把数据移动过来。
- 程序和数据存储是属于不同的技术厂商实现,无法有机统一整合在一起。
如何解决
- 如何解决海量数据下存储问题 ?
- 传统做法是在单机存储。但是随着数据变多,会遇到存储瓶颈。
- 单机纵向扩展:内存不够加内存,磁盘不够加磁盘。有上限限制,不能无限制加下去。
- 多机横向扩展:采用多台机器存储,一台不够就加机器。理论上可以无限。多台机器存储也就意味着迈入了分布式存储。
- 如何解决海量数据文件查询便捷问题 ?
- 当文件被分布式存储在多台机器之后,后续获取文件的时候如何能快速找到文件位于哪台机器上呢。
- 一台一台查询过来也不靠谱。因此可以借助于元数据记录来解决这个问题。
- 把文件和其存储的机器的位置信息记录下来,类似于图书馆查阅图书系统,这样就可以快速定位文件存储在哪一台机器上了。
- 如何解决大文件传输效率慢的问题 ?
- 大数据使用场景下,GB、TP级别的大文件是常见的。当单个文件过大的时候,如何提高传输效率?
- 通常的做法是分块存储:把大文件拆分成若干个小块(block 简写blk),分别存储在不同机器上,并行操作提高效率。
- 此外分块存储还可以解决数据存储负载均衡问题。此时元数据记录信息也应该更加详细:文件分了几块,分别位于哪些机器上。
- 如何解决硬件故障数据丢失问题 ?
- 机器、磁盘等硬件出现故障是难以避免的事情,如何保证数据存储的安全性。
- 如果某台机器故障,数据块丢失,对于文件来说整体就是不完整的。
- 冗余存储是个不错的选择。采用副本机制。副本越多,数据越安全,当然冗余也会越多。
- 通过“不要把鸡蛋放在一个篮子里”的思想,可以把数据丢失的风险分散到各个机器上。
- 如何解决用户查询视角统一规整问题 ?
- 随着存储的进行,数据文件越来越多,与之对应元数据信息也越来越多,如何让用户视觉层面感觉不到元数据的凌乱,同时也与传统的文件系统操作体验保持一致?
- 传统的文件系统拥有所谓的目录树结构,带有层次感的namespace(命名空间),因此可以把分布式文件系统的元数据记录这一块也抽象成统一的目录树结构。
小结
- 如何解决海量数据存的下的存储问题–分布式存储
- 如何解决海量数据文件查询便捷的问题—-元数据记录
- 如何解决大文件传输效率慢的问题—-分块存储
- 如何解决硬件故障数据丢失的问题–副本机制
- 如何解决用户查询视角统一规整的问题–抽象目录树结构
HDFS
- HDFS( Hadoop Distributed File System ),意为:Hadoop分布式文件系统。是Apache Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。
- 分布式文件系统解决大数据如何存储问题。分布式意味着是横跨在多台计算机上的存储系统。
- HDFS是一种能够在普通硬件上运行的分布式文件系统,它是高度容错的,适应于具有大数据集的应用程序,它非常适于存储大型数据 (比如 TB 和 PB)。
- HDFS使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统。
HDFS的起源和发展
- Doug Cutting领导Nutch项目研发,Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取、索引、查询等功能。
- 随着爬虫抓取网页数量的增加,遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索引问题。
- 2003年的时候, Google 发表的论文为该问题提供了可行的解决方案 —>《分布式文件系统(GFS),可用于处理海量网页的存储》
- Nutch的开发人员完成了相应的开源实现HDFS,并从Nutch中剥离和MapReduce成为独立项目HADOOP。
- HDFS相关论文—>The Hadoop Distributed File System
HDFS的设计目标
- 硬件故障(Hardware Failure)是常态, HDFS可能有成百上千的服务器组成,每一个组件都有可能出现故障。因此故障检测和自动快速恢复是HDFS的核心架构目标。
- HDFS上的应用主要是以流式读取数据(Streaming Data Access)。HDFS被设计成用于批处理,而不是用户交互式的。相较于数据访问的反应时间,更注重数据访问的高吞吐量。
- 典型的HDFS文件大小是GB到TB的级别。所以,HDFS被调整成支持大文件(Large Data Sets)。它应该提供很高的聚合数据带宽,一个集群中支持数百个节点,一个集群中还应该支持千万级别的文件。
- 大部分HDFS应用对文件要求的是write-one-read-many访问模型。一个文件一旦创建、写入、关闭之后就不需要修改了。这一假设简化了数据一致性问题,使高吞吐量的数据访问成为可能。
- 移动计算的代价比之移动数据的代价低。一个应用请求的计算,离它操作的数据越近就越高效。将计算移动到数据附近,比之将数据移动到应用所在显然更好。
- HDFS被设计为可从一个平台轻松移植到另一个平台。这有助于将HDFS广泛用作大量应用程序的首选平台。
HDFS的应用场景
HDFS的特性
主从架构:
- HDFS采用master/slave架构。一般一个HDFS集群是有一个Namenode和一定数目的Datanode组成。Namenode是HDFS主节点,Datanode是HDFS从节点,两种角色各司其职,共同协调完成分布式的文件存储服务。
分块存储:
- HDFS中的文件在物理上是分块存储(block)的,块的大小可以通过配置参数来规定,参数位于hdfs-default.xml中:dfs.blocksize。默认大小是128M(134217728)
副本机制:
- 文件的所有block都会有副本。每个文件的block大小(dfs.blocksize)和副本系数(dfs.replication)都是可配置的。副本系数可以在文件创建的时候指定,也可以在之后通过命令改变。
- 默认dfs.replication的值是3,也就是会额外再复制2份,连同本身总共3份副本。
namespace:
- HDFS支持传统的层次型文件组织结构。用户可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。
- Namenode负责维护文件系统的namespace名称空间,任何对文件系统名称空间或属性的修改都将被Namenode记录下来。
- HDFS会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data。
元数据管理:
- 在HDFS中,Namenode管理的元数据具有两种类型:
- 文件自身属性信息
- 文件名称、权限,修改时间,文件大小,复制因子,数据块大小。
- 文件块位置映射信息
- 记录文件块和DataNode之间的映射信息,即哪个块位于哪个节点上
数据块存储:
- 文件的各个block的具体存储管理由DataNode节点承担。每一个block都可以在多个DataNode上存储。
命令行实践
HDFS Shell CLI客户端:
- 命令行界面(英语:command-line interface,缩写:CLI)是指用户通过键盘输入指令,计算机接收到指令后,予以执行一种人际交互方式。
- Hadoop提供了文件系统的shell命令行客户端,使用方法如下:
hdfs [OPTIONS] SUBCOMMAND [SUBCOMMAND OPTIONS] SUBCOMMAND:Admin Commands、Client Commands、Daemon Commands。
跟文件系统读写使用相关的命令是 hdfs dfs [generic options]
HDFS Shell CLI客户端–说明:
- HDFS Shell CLI支持操作多种文件系统,包括本地文件系统(file:///)、分布式文件系统(hdfs://nn:8020)等
- 操作的是什么文件系统取决于URL中的前缀协议。
- 如果没有指定前缀,则将会读取环境变量中的fs.defaultFS属性,以该属性值作为默认文件系统
hdfs dfs -ls file:/// #操作本地文件系统
hdfs dfs -ls hdfs://node1:8020/ #操作HDFS分布式文件系统
hdfs dfs -ls / #直接根目录,没有指定协议 将加载读取fs.defaultFS值
- hadoop dfs、hdfs dfs、 hadoop fs 三者区别
- hadoop dfs 只能操作HDFS文件系统(包括与Local FS间的操作),不过已经Deprecated
- hdfs dfs 只能操作HDFS文件系统相关(包括与Local FS间的操作),常用
- hadoop fs 可操作任意文件系统,不仅仅是hdfs文件系统,使用范围更广
- 目前版本来看,官方最终推荐使用的是hadoop fs。当然hdfs dfs在市面上的使用也比较多。
- HDFS文件系统的操作命令很多和Linux类似,因此学习成本相对较低。
- 可以通过hadoop fs -help命令来查看每个命令的详细用法。
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
……
-appendToFile <localsrc> ... <dst> :
Appends the contents of all the given local files to the given dst file. The dst
file will be created if it does not exist. If <localSrc> is -, then the input is
read from stdin.
-cat [-ignoreCrc] <src> ... :
Fetch all files that match the file pattern <src> and display their content on
stdout.
常用命令
- 创建目录
hadoop fs -mkdir [-p] <path> ...
path为待创建的目录
-p选项的行为与Unix mkdir -p非常相似,它会沿着路径创建父目录
hadoop fs -mkdir -p /xpy/dhy/test
- 查看指定目录下的内容
hadoop fs -ls [-h] [-R] [<path> ...]
path 指定目录路径
-h 人性化显示文件size
-R 递归查看指定目录及其子目录
hadoop fs -ls -h -R /xpy
- 上传文件
hadoop fs -put [-f] [-p] <localsrc> ... <dst>
-f 覆盖目标文件(已存在下)
-p 保留访问和修改时间,所有权和权限。
localsrc 本地文件系统(客户端所在机器)
dst 目标文件系统(HDFS)
hadoop fs -put hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log /xpy/dhy/test
hadoop fs -moveFromLocal <localsrc> ... <dst>
和-put功能意义,只不过上传结束,源数据会被删除
hadoop fs -moveFromLocal test.txt /xpy/dhy/test
- 查看文件内容
hadoop fs -cat <src> ...
读取指定文件全部内容,显示在标准输出控制台。
注意:对于大文件内容读取,慎重。
hadoop fs -cat /xpy/dhy/test/test.txt
- 查看文件前1KB的内容
hadoop fs -head <file>
hadoop fs -head /xpy/dhy/test/hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log
- 查看文件最后1KB的内容
hadoop fs -tail [-f] <file>
-f选择可以动态显示文件中追加的内容
hadoop fs -tail /xpy/dhy/test/hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log
- 下载文件
hadoop fs -get [-f] [-p] <src> ... <localdst>
下载文件到本地文件系统指定目录,localdst必须是目录
-f 覆盖目标文件(已存在下)
-p 保留访问和修改时间,所有权和权限。
hadoop fs -get /xpy/dhy/test/hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log ./
- 合并下载文件
hadoop fs -getmerge [-nl] [-skip-empty-file] <src> <localdst>
下载多个文件合并到本地文件系统的一个文件中。
-nl选项表示在每个文件末尾添加换行符
hadoop fs -getmerge -nl -skip-empty-file /xpy/dhy/test/hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log /xpy/dhy/test/test.txt ./merge.txt
- 拷贝文件
hadoop fs -cp [-f] <src> ... <dst>
-f 覆盖目标文件(已存在下)
本地文件复制到HDFS中 --> hadoop fs -cp file:///home/user/file.txt hdfs://namenode:9000/path/to/destination
在HDFS中复制文件 --> hadoop fs -cp hdfs://namenode:9000/path/to/source hdfs://namenode:9000/path/to/destination
(不加hdfs://,默认采用hdfs文件传输协议)
- 追加数据
hadoop fs -appendToFile <localsrc> ... <dst>
将所有给定本地文件的内容追加到给定dst文件。
dst如果文件不存在,将创建该文件。
如果<localSrc>为-,则输入为从标准输入中读取。
hadoop fs -appendToFile - /xpy/dhy/test/test1.txt
- 查看HDFS磁盘空间
hadoop fs -df [-h] [<path> ...]
显示文件系统的容量,可用空间和已用空间
hadoop fs -df -h /
- 查看文件使用的空间量
hadoop fs -du [-s] [-h] <path> ...
-s:表示显示指定路径文件长度的汇总摘要,而不是单个文件的摘要。
-h:选项将以“人类可读”的方式格式化文件大小
hadoop fs -du -s -h -v /xpy/dhy/test/hadoop-root-datanode-iZ0jl31cusuwz95ltn0gzfZ.log
- 数据移动操作
hadoop fs -mv <src> ... <dst>
移动文件到指定文件夹下
可以使用该命令移动数据,重命名文件的名称
- 修改文件副本个数
hadoop fs -setrep [-R] [-w] <rep> <path> ...
修改指定文件的副本个数。
-R表示递归 修改文件夹下及其所有
-w 客户端是否等待副本修改完毕。
更多hdfs shell命令
Java客户端API使用
环境准备
HDFS在生产应用中主要是Java客户端的开发,其核心步骤是从HDFS提供的API中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件。
客户端核心类:
- Configuration 配置对象类,用于加载或设置参数属性
- FileSystem 文件系统对象基类。针对不同文件系统有不同具体实现。该类封装了文件系统的相关操作方法。
引入依赖:
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</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>
</configuration>
</plugin>
</plugins>
</build>
创建测试用例:
/**
* hdfs客户端测试类
*/
public class HDFSClientTest {
private Configuration conf = null;
private FileSystem fs = null;
@Before
public void connect2HDFS() throws IOException {
//创建配置对象实例
conf = new Configuration();
//设置操作的文件系统是HDFS
conf.set("fs.defaultFS", "hdfs://主机名或者外网ip地址:8020");
//创建FileSystem实例 此处通过conf设置 代表的是分布式文件系统
fs = FileSystem.get(conf);
}
@After
public void closeConnect() {
//如果文件系统连接没有关闭 关闭连接
if (fs != null) {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
踩坑实录
第一个坑: 无法通过外网访问nameNode节点监听的8020端口
我的HDFS集群部署在三台云服务器上,并且处于不同的局域网中,两台阿里云,一台华为云,此时我们的客户端如果按照上面配置的方式尝试通过外网访问nameNode节点监听的8020端口,可能会抛出Connection Refused异常。
解决这个问题的思路如下:
- 因为是nameNode节点监听的8020端口,所以这里使用jps命名,在服务器上查看nameNode节点是否启动
- 如果nameNode启动了,那么进入下一步排查,
netstat -nltp|grep 8020
命令查看8020端口是否处于监听状态,特别注意观察: 8020端口是只在127.0.0.1地址上进行监听,还是0.0.0.0监听全部ip地址。
- 我的问题出现在这里,由于NameNode只监听了本地地址(127.0.0.1),因此无法通过外网IP访问。
- 解决办法: 修改NameNode配置文件中的 dfs.namenode.rpc-bind-host 属性和 dfs.namenode.servicerpc-bind-host 属性,将其绑定到外网IP上。
- 在
hdfs-site.xml
中添加以下属性配置, 这样,NameNode 就会绑定到所有可用的IP地址上,包括外网IP,从而可以通过外网IP访问了。记得重启 NameNode 服务使配置生效。
<property>
<name>dfs.namenode.rpc-bind-host</name>
<value>0.0.0.0</value>
</property>
<property>
<name>dfs.namenode.servicerpc-bind-host</name>
<value>0.0.0.0</value>
</property>
再次使用netstat命令验证是否在8020端口上监听所有ip地址:
如果想要验证此时能否通过外网访问nameNode的8020端口,可以在外网的一台主机上使用telnet nameNode的ip地址 8020
命令验证验证能否正常访问:
如果还是不行,记得检查防火墙是否开放了8020端口哦!
第二个坑: dfs.client.use.datanode.hostname配置的作用到底是什么
dfs.client.use.datanode.hostname
是Hadoop
配置文件中的一个属性,配置该参数为true
后,客户端向NameNode
请求数据块的时候,NameNode
会将DataNode
的主机名(hostname
)信息返回给客户端,而不是返回DataNode
的IP
地址。这样可以确保客户端始终能够正确地访问到DataNode
,避免了由于IP
地址变更导致的连接错误。
该参数默认值为false
我们可以在服务端的hdfs-site.xml
配置文件中配置该参数:
<property>
<name>dfs.client.use.datanode.hostname</name>
<value>true</value>
</property>
也可以在客户端中通过代码指定:
@Before
public void connect2HDFS() throws IOException {
conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://node1:8020");
fs = FileSystem.get(conf);
}
那么大家思考这两种方式有什么区别呢?
- 服务端配置该参数,是将默认值由false改为true, 但是客户端可以通过显示指定,让每次rpc通信时,显示告诉NameNode,
dfs.client.use.datanode.hostname
参数值取true,忽略默认值
第三个坑: 客户端没有权限
原因:以Windows登录用户访问HDFS,而该用户不具备在HDFS操作权限
解决:
- 修改HDFS文件系统权限
- 或者设置客户端身份,该身份具备在HDFS操作权限
展示第二种方法对应的代码:
@Before
public void connect2HDFS() throws IOException {
conf = new Configuration();
//设置客户端身份
System.setProperty("HADOOP_USER_NAME","root");
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://node1:8020");
fs = FileSystem.get(conf);
}
CRUD实践
- 创建目录
@Test
public void mkdir() throws IOException {
if (!fs.exists(new Path("/hdfsClientTest"))) {
fs.mkdirs(new Path("/hdfsClientTest"));
}
}
- 上传文件
@Test
public void putFile2HDFS() throws IOException {
//本地文件路径
Path src = new Path("a.txt");
//hdfs目标路径
Path dst = new Path("/hdfsClientTest");
//上传文件
fs.copyFromLocalFile(src, dst);
}
相对路径运行时完整路径是什么,取决于当前程序的工作目录在哪里,大家可以查看一下:
如果出现:
java.io.IOException: java.nio.channels.UnresolvedAddressException
异常,说明nameNode返回给客户端的dataNode的ip地址或者主机名不正确。
使用下面这段代码可以查看nameNode返回给客户端的dataNode列表,可以打印出来,查看dataNode的ip地址和hostName是不是期望值:
DistributedFileSystem dfs = (DistributedFileSystem) fs;
DatanodeInfo[] datanodes = dfs.getDataNodeStats();
for (DatanodeInfo datanode : datanodes) {
System.out.println("DataNode Hostname: " + datanode.getHostName());
System.out.println("DataNode IP Address: " + datanode.getIpAddr());
}
如果是主机名不正确,确认一下是否已经配置好相关映射,如果配置了,查看/etc/hosts文件中是否存在多个本地127.0.0.1地址的映射,如果存在,将多余的去掉。
- 下载文件
@Test
public void getFile2Local() throws IOException {
//hdfs文件路径
Path src = new Path("/hdfsClientTest/a.txt");
//本地文件路径
Path dst = new Path("abc.txt");
//下载文件
fs.copyToLocalFile(src, dst);
}
这里可能会抛出找不到winutils.exe、HADOOP_HOME没有设置的异常。
- 错误提示:
- 找不到winutils.exe、HADOOP_HOME没有设置
- 原因:
- Hadoop访问windows本地文件系统,要求Windows上的本地库能正常工作。
- 其中Hadoop使用某些Windows API来实现类似posix的文件访问权限。
- 上述功能需要在hadoop.dll和winutils.exe来实现。
- 解决:
- 下载Hadoop源码在windows平台编译,编译出windows本地库。然后配置Hadoop环境变量。
hadoop报错:ExitCodeException exitCode=-1073741515