CCCCCold丶大数据之禅-HDFS篇
HDFS简介
HDFS:分布式文件存储系统(Hadoop Distributed Filesystem),管理网络中跨多台计算机存储文件的系统。
HDFS设计理念
硬件错误:硬件错误是常态而不是异常。HDFS可能由成百上千的服务器所构成,每个服务器上存储着文件系统的部分数据。我们面对的现实是构成系统的组件数目是巨大的,而且任一组件都有可能失效,这意味着总是有一部分HDFS的组件是不工作的。因此错误检测和快速、自动的恢复是HDFS最核心的架构目标
流式数据访问:运行在HDFS上的应用和普通的应用不同,需要流式访问它们的数据集。HDFS的设计中更多的考虑到了数据批处理,而不是用户交互处理。比之数据访问的低延迟问题,更关键的在于数据访问的高吞吐量。每次对HDFS上数据进行分析都会涉及到该数据集大部分,甚至全部,因此读取整个数据集的时间延迟比读取第一条纪录的时间延迟更重要。
大规模数据集 :运行在HDFS上的应用具有很大的数据集。HDFS上的一个典型文件大小一般都在G字节至T字节。因此,HDFS被调节以支持大文件存储。它应该能提供整体上高的数据传输带宽,能在一个集群里扩展到数百个节点。一个单一的HDFS实例应该能支撑数以千万计的文件。
简单的一致性模型 :只支持单个写入者,一次写入多次读写,而且写操作总是以“只添加”方式在文件末尾写数据。
移动计算比移动数据更划算 :一个应用请求的计算,离它操作的数据越近就越高效,在数据达到海量级别的时候更是如此。因为这样就能降低网络阻塞的影响,提高系统数据的吞吐量。将计算移动到数据附近,比之将数据移动到应用所在显然更好。HDFS为应用提供了将它们自己移动到数据附近的接口。
异构软硬件平台间的可移植性 :HDFS在设计的时候就考虑到平台的可移植性。这种特性方便了HDFS作为大规模数据应用平台的推广。
Namenode和Datanode :HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成。Namenode是一个中心服务器,负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。集群中的Datanode一般是一个节点一个,负责管理它所在节点上的存储。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。
小文件 :由于Namenode将文件系统的元数据(Datanode中数据块的关系)存储在内存中,因此该文件系统所能存储的文件总数受限于Namenode的内存总量。根据经验,每个文件、目录和数据块存储信息大约占150字节,举例来说,如果有一百万个文件,每个文件占一个数据块,至少需要300MB的内存,尽管存储上百万文件是可行的,但是存储数十亿文件就超出硬件能力(内存受限)
文件系统的名字空间(namespace) :HDFS支持传统的层次型文件组织结构。用户或者应用程序可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。当前,HDFS不支持用户磁盘配额和访问权限控制,也不支持硬链接和软链接。但是HDFS架构并不妨碍实现这些特性。
Namenode负责维护文件系统的名字空间,任何对文件系统名字空间或属性的修改都将被Namenode记录下来。应用程序可以设置HDFS保存的文件的副本数目。文件副本的数目称为文件的副本系数,这个信息也是由Namenode保存的。
举例:
hdfs://ns1/user/mart_meituan/tmp.db/
hdfs://ns2/user/mart_didi/app.db/
hdfs://ns3/user/mart_mart_cmo/dev.db/
数据复制 :HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的。为了容错,文件的所有数据块都会有副本。每个文件的数据块大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。HDFS中的文件都是一次性写入的,并且严格要求在任何时候只能有一个写入者。
Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表
副本存放 :副本的存放是HDFS可靠性和性能的关键。优化的副本存放策略是HDFS区分于其他大部分分布式文件系统的重要特性。这种特性需要做大量的调优,并需要经验的积累。HDFS采用一种称为机架感知(rack-aware)的策略来改进数据的可靠性、可用性和网络带宽的利用率。目前实现的副本存放策略只是在这个方向上的第一步。实现这个策略的短期目标是验证它在生产环境下的有效性,观察它的行为,为实现更先进的策略打下测试和研究的基础。
大型HDFS实例一般运行在跨越多个机架的计算机组成的集群上,不同机架上的两台机器之间的通讯需要经过交换机。在大数情况下,同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。
通过一个机架感知的过程,Namenode可以确定每个Datanode所属的机架id。一个简单但没有优化的策略就是将副本存放在不同的机架上。这样可以有效防止当整个机架失效时数据的丢失,并且允许读数据的时候充分利用多个机架的带宽。这种策略设置可以将副本均匀分布在集群中,有利于当组件失效情况下的负载均衡。但是,因为这种策略的一个写操作需要传输数据块到多个机架,这增加了写的代价。
在大多数情况下,副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。这种策略减少了机架间的数据传输,这就提高了写操作的效率。机架的错误远远比节点的错误少,所以这个策略不会影响到数据的可靠性和可用性。于此同时,因为数据块只放在两个(不是三个)不同的机架上,所以此策略减少了读取数据时需要的网络传输总带宽。在这种策略下,副本并不是均匀分布在不同的机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。
副本选择 :为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本。如果在读取程序的同一个机架上有一个副本,那么就读取该副本。如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本。
集群均衡 :HDFS的架构支持数据均衡策略。如果某个Datanode节点上的空闲空间低于特定的临界点,按照均衡策略系统就会自动地将数据从这个Datanode移动到其他空闲的Datanode。当对某个文件的请求突然增加,那么也可能启动一个计划创建该文件新的副本,并且同时重新平衡集群中的其他数据。这些均衡策略目前还没有实现。
数据完整性 :从某个Datanode获取的数据块有可能是损坏的,损坏可能是由Datanode的存储设备错误、网络错误或者软件bug造成的。HDFS客户端软件实现了对HDFS文件内容的校验和(checksum)检查。当客户端创建一个新的HDFS文件,会计算这个文件每个数据块的校验和,并将校验和作为一个单独的隐藏文件保存在同一个HDFS名字空间下。当客户端获取文件内容后,它会检验从Datanode获取的数据跟相应的校验和文件中的校验和是否匹配,如果不匹配,客户端可以选择从其他Datanode获取该数据块的副本。
文件的删除和恢复 :当用户或应用程序删除某个文件时,这个文件并没有立刻从HDFS中删除。实际上,HDFS会将这个文件重命名转移到/.trash目录。只要文件还在/.trash目录中,该文件就可以被迅速地恢复。文件在/.trash中保存的时间是可配置的,当超过这个时间时,Namenode就会将该文件从名字空间中删除。删除文件会使得该文件相关的数据块被释放。注意,从用户删除文件到HDFS空闲空间的增加之间会有一定时间的延迟。
只要被删除的文件还在/.trash目录中,用户就可以恢复这个文件。如果用户想恢复被删除的文件,他/她可以浏览/.trash目录找回该文件。/.trash目录仅仅保存被删除文件的最后副本。/.trash目录与其他的目录没有什么区别,除了一点:在该目录上HDFS会应用一个特殊策略来自动删除文件。目前的默认策略是删除/.trash中保留时间超过6小时的文件。
HDFS-quota :Hadoop分布式文件系统(HDFS)允许管理员为每个目录设置配额。新建立的目录没有配额。最大的配额是Long.Max_Value。配额为1可以强制目录保持为空。
目录配额是对目录树上该目录下的名字数量做硬性限制。如果创建文件或目录时超过了配额,该操作会失败。重命名不会改变该目录的配额;如果重命名操作会导致违反配额限制,该操作将会失败。如果尝试设置一个配额而现有文件数量已经超出了这个新配额,则设置失败。
如果有线上生产作业往此目录写入数据,超出限额会导致作业失败
HDFS-权限管控 :Hadoop分布式文件系统实现了一个和POSIX系统类似的文件和目录的权限模型。每个文件和目录有一个所有者(owner)和一个组(group)。文件或目录对其所有者、同组的其他用户以及所有其他用户分别有着不同的权限。对文件而言,当读取这个文件时需要有r权限,当写入或者追加到文件时需要有w权限。对目录而言,当列出目录内容时需要具有r权限,当新建或删除子文件或子目录时需要有w权限,当访问目录的子节点时需要有x权限。不同于POSIX模型,HDFS权限模型中的文件没有sticky,setuid或setgid位,因为这里没有可执行文件的概念。为了简单起见,这里也没有目录的sticky,setuid或setgid位。总的来说,文件或目录的权限就是它的模式(mode)。HDFS采用了Unix表示和显示模式的习惯,包括使用八进制数来表示权限。当新建一个文件或目录,它的所有者即客户进程的用户,它的所属组是父目录的组(BSD的规定)。
如果线上生产作业没有某个目录权限,会直接导致作业失败
HDFS-shell 常用操作:
put : hadoop dfs -put ./meta_data.sql hdfs//ns1/user/mart_test/ 上传本地文件至指定hdfs路径
get :hadoop dfs -get hdfs://ns1/user/mart_test/meta_data.sql ./ 下载hdfs文件至本地指定路径
rm :hadoop dfs -rm hdfs://ns1/user/mart_test/ 删除指定路径文件或目录
count :hadoop dfs -count hdfs://ns1/user/mart_test/ 统计指定路径下文件数及大小(默认单位字节)
du :hadoop dfs -du hdfs://ns1/user/mart_test/ 显示目录中所有文件的大小,或者当只指定一个文件时,显示此文件的大小 -h 自动转换单位为MB或者GB
mkdir :hadoop dfs -mkdir hdfs://ns1/user/mart_test/ 在指定路径创建目录 -p 创建各父级文件
mv :hadoop dfs -mkdir hdfs://ns1/user/mart_test/ 移动文件或重命名 同Linux
cp :hadoop dfs -cp hdfs://ns1/user/mart_test/ hdfs://ns1/user/mart_test/ 移动文件或重命名 同Linux
chmod :hadoop dfs -chmod 777 hdfs://ns1/user/mart_test/
chown :hadoop dfs -chown mart_tha:mart_tha hdfs://ns1/user/mart_test/
copyFromLocal :hadoop dfs -copyFromLocal ./meta_data.sql hdfs//ns1/user/mart_test/ 上传本地文件至指定hdfs路径 与put命令相似
copyToLocal:hadoop dfs -copyToLocal hdfs//ns1/user/mart_test/meta_data.sql ./ 上传本地文件至指定hdfs路径 与get命令相似
expunge:hadoop dfs -expunge 清空回收站
lsr:hadoop dfs -ls hdfs://ns1/user/mart_test/ ls递归版本
rmr:hadoop dfs -rmr hdfs://ns1/user/mart_test/ rm递归版本
setrep:hadoop dfs -setrep -w 3 -R hdfs://ns1/user/mart_test/meta_data.sql
tail:hadoop dfs -tail hdfs://ns1/user/mart_test/meta_data.sql
test:
-e 检查文件是否存在。如果存在则返回0
-z 检查文件是否是0字节。如果是则返回0
-d 如果路径是个目录,则返回1,否则返回0
hadoop dfs -test -e hdfs://ns1/user/mart_test/meta_data.sql
text:hadoop fs -text hdfs://ns1/user/mart_test/meta_data.sql 将源文件输出为文本格式。允许的格式是zip和TextRecordInputStream
touchz:hadoop dfs -touchz hdfs://ns1/user/mart_test/meta_data.sql 创建0字节空
一般hdfs-shell命令有三种:
hadoop fs
hadoop dfs
hdfs dfs
fs是文件系统, dfs是分布式文件系统
fs > dfs
分布式环境情况下,fs与dfs无区别
本地环境中,fs就是本地文件,dfs就不能用了
Hadoop fs:使用面最广,可以操作任何文件系统。
hadoop dfs与hdfs dfs:只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者。