A. HDFS 系统架构
HDFS Architecture
Hadoop Distributed File System (HDFS) 是设计可以运行于普通商业硬件上的分布式文件系统。它跟现有的分布式文件系统有很多相通的地方,但是区别也是显著的。HDFS具有高度容错性能,被设计运行于低成本硬件上。HDFS可以向应用提供高吞吐带宽,适合于大数据应用。HDFS 放宽了一些 POSIX 的要求,以开启对文件系统数据的流式访问。HDFS 最初是作为Apache Nutch web 搜索引擎项目的基础设施开发的。HDFS 现在是 Apache Hadoop 核心项目的一部分。
HDFS是主从架构。一个HDFS集群包含一个NameNode,一个管理文件系统命名空间和控制客户端访问文件的master server。以及,若干的 DataNodes,通常集群的每个node一个,管理运行DataNode的节点上的存储。HDFS 发布一个文件系统命名空间,并允许用户数据已文件的形式存储在上面。内部,一个文件被分成一个或多个块,存储在一组DataNodes上。NameNode 执行文件系统命名空间操作,比如:打开、关闭、重命名文件或目录。它还确定块到DataNodes的映射。DataNodes 负责向文件系统客户端提供读写服务。DataNodes 根据 NameNode 的指令执行块的创建、删除以及复制。
NameNode 和 DataNode 是设计运行于普通商业机器的软件。这些机器通常运行 GNU/Linux 操作系统。HDFS 是java 语言编写的;任何支持Java的机器都可以运行NameNode or DataNode 软件。使用高移植性Java语言,意味着HDFS可以部署在很大范围的机器上。一个典型的部署就是一台特定的机器只运行NameNode 软件,而集群内的其他机器运行DataNode 软件的一个实例。这种架构不排除一台机器上运行多个DataNodes ,但是在实际部署中很少见。
单 NameNode 节点的存在大大简化了架构。NameNode 是所有HDFS 元数据的仲裁和仓库。系统设计上,用户数据永远不经过NameNode。
HDFS 支持传统的文件分级组织。用户或应用可以创建目录,并在目录内存储文件。 文件系统命名空间的层次结构跟其他文件系统类似;可以创建、删除、移动、重命名文件。HDFS 支持 user quotas 和 access permissions 。 HDFS 不支持软、硬链接。但是,HDFS 架构不排除实现这些功能。
虽然HDFS遵守 文件系统命名约定 ,一些路径和名称 (比如/.reserved 和.snapshot ) 保留了。比如功能 transparent encryption 和 snapshot 就使用的保留路径。
NameNode 维护文件系统命名空间。任何文件系统命名空间或属性的变化,都会被NameNode记录。 应用可以指定HDFS应维护的文件副本数量。文件副本的数量被称为该文件的复制因子 replication factor 。该信息存储于NameNode。
HDFS 被设计用于在一个大规模集群上跨机器可靠地存储巨大的文件。它以一序列的块的方式存储文件。每个文件都可以配置块尺寸和复制因子。
一个文件除了最后一个块外,其他的块一样大。在 append 和 hsync 添加了可变长度块的支持后,用户可以启动一个新的块,而不用填充最后一个块到配置的块大小。
应用可以指定一个文件的副本数量。复制因子可以在创建的时候指定,也可以以后更改。HDFS的文件只写一次(除了 appends 和 truncates) ,并在任何时候只允许一个 writer 。
NameNode 指定块复制的所有决策。它周期性的从集群的每个DataNodes 接受 Heartbeat 和 Blockreport。Heartbeat 的接受代表 DataNode 工作正常。Blockreport 包含了DataNode上所有块的清单。
副本的位置对HDFS的可靠性和性能至关重要。副本位置的优化是HDFS和其他大多数分布式文件系统的区别。这是一个需要大量调优和经验的特性。Rack-aware 复制策略的目的就是提高数据可靠性,可用性和网络带宽利用率。当前副本位置策略的实现是这个方向的第一步。实施该策略的短期目标是在生产环境验证它,了解其更多的行为,为测试和研究更复杂的策略打下基础。
大型HDFS实例运行在跨多个Rack的集群服务器上。不同rack的两个node通信需要通过交换机。大多数情况下,同一rack内的带宽大于rack之间的带宽。
NameNode 通过在 Hadoop Rack Awareness 内的进程描述 判断DataNode 属于哪个rack id。一个简单但是并非最佳的策略是将副本分布于不同的racks。这可以防止整个机架发生故障时丢失数据,并允许在读取数据时使用多个机架的带宽。该策略在群集中均匀地分布副本,使得组件故障时很容易平衡负载。 但是,该策略会增加写入成本,因为写入操作需要将块传输到多个机架。
一般,复制因子设置为3, HDFS 的分布策略是:如果writer在datanode上则将一个副本放到本地机器, 如果writer不在datanode上则将一个副本放到writer所在机柜的随机datanode 上;另一个副本位于不同机架的node上;最后一个副本位于同一远程机架的不同node上。 该策略减少了机架间的写流量,提升了写性能。机架故障的概率远小于节点故障的概率;此策略不会影响数据可靠性和可用性承诺。但是,在读取数据时,它确实减少了聚合带宽,因为块存储于两个机柜而不是三个机柜内。使用此策略,副本不会均匀的分布于机架上。1/3 副本 位于同一节点, 2/3 副本位于同一机架, 另1/3副本位于其他机架。该策略提升了写性能而不影响数据可靠性和读性能。
如果复制因子大于3,那么第4个及以后的副本则随机放置,只要满足每个机架的副本在(replicas - 1) / racks + 2)之下。
因为 NameNode 不允许 DataNodes 拥有同一个块的多个副本,所以副本的最大数就是DataNodes的数量。
在把对 存储类型和存储策略 的支持添加到 HDFS 后,除了上面介绍的rack awareness外, NameNode 会考虑其他副本排布的策略。NameNode 先基于rack awareness 选择节点,然后检查候选节点有文件关联的策略需要的存储空间。 如果候选节点没有该存储类型, NameNode 会查找其他节点。如果在第一条路径中找不到足够的节点来放置副本,NameNode会在第二条路径中查找具有回滚存储类型的节点。 、
当前,这里描述的默认副本排布策略正在使用中。
为了最小化全局带宽消耗和读取延迟, HDFS 会尝试从最靠近reader的副本响应读取请求。如果在reader节点的同一机架上上存在副本,则该副本有限响应读请求。如果HDFS集群跨多个数据中心,则本地数据中心优先。
启动时,NameNode 会进入一个称为 Safemode 的特殊状态。当NameNode处于Safemode状态时,不会复制数据块。NameNode从DataNodes接收Heartbeat和Blockreport消息。Blockreport包含DataNode托管的数据块列表。每个块都指定了最小副本数。当数据块的最小副本数已与NameNode签入时,该块被认为是安全复制的。在NameNode签入安全复制数据块的已配置百分比(加上额外的30秒)后,NameNode退出Safemode状态。然后,它判断列表内的数据块清单是否少于副本指定的数量。NameNode 然后复制这些块给其他 DataNodes。
HDFS 命名空间由 NameNode 存储。NameNode 使用事务日志 EditLog 来持久化的保存系统元数据的每次变更。比如,在HDFS创建一个新文件,NameNode会在 EditLog 插入一条记录来指示该变更。类似的,变更文件的复制因子也会在 EditLog 插入一条新记录。NameNode 以文件的形式,将 EditLog 保存在本地OS文件系统上。整个文件系统命名空间,包括块到文件的映射、文件系统属性,都存储于名字为 FsImage 的文件内。 FsImage 也以文件的形式,存储在NameNode的本地文件系统上。
NameNode 将包含整个文件系统和块映射的image保存在内存中。当NameNode启动时,或检查点被预先定义的阈值触发时,它会从磁盘读取 FsImage 和 EditLog ,把 EditLog 内的事物应用到内存中的FsImage,再将新版本刷新回磁盘的新 FsImage 。然后会截断旧的 EditLog ,因为它的事物已经应用到了持久化的 FsImage 上。 这个过程称为检查点 checkpoint 。检查点的目的是通过对文件系统元数据进行快照并保存到FsImage,来确保HDFS拥有文件系统元数据的一致性视图。尽管读取 FsImage 是高效的,但是对 FsImage 直接增量修改是不高效的。不是对每次编辑修改 FsImage ,而是将每次编辑保存到 Editlog 。在检查点期间,将 Editlog 的变更应用到 FsImage 。一个检查点可以在固定周期(dfs.namenode.checkpoint.period)(以秒为单位)触发,也可以文件系统事物数量达到某个值(dfs.namenode.checkpoint.txns)的时候触发。
DataNode 在本地文件系统上以文件的形式存储 HDFS data 。DataNode 不知道 HDFS 文件。它将HDFS data 的每个块以独立的文件存储于本地文件系统上。DataNode 不在同一目录创建所有的文件。而是,使用heuristic来确定每个目录的最佳文件数量,并适当的创建子目录。在一个目录创建所有的本地文件是不好的,因为本地文件系统可能不支持单目录的海量文件数量。当DataNode启动的时候,它扫描本地文件系统,生成与本地文件系统一一对应的HDFS数据块列表,然后报告给NameNode。这个报告称为 Blockreport。
所有的HDFS通信协议都在TCP/IP协议栈上。客户端与NameNode指定的端口建立连接。与NameNode以ClientProtocol 通信。DataNodes与NameNode以DataNode Protocol进行通信。远程过程调用(RPC)封装了Client Protocol 和 DataNode Protocol。设计上,NameNode从不启动任何RPCs。相反,它只应答DataNodes or clients发出的RPC请求。
HDFS的主要目标是可靠的存储数据,即使是在故障的情况下。常见故障类型有三种: NameNode failures , DataNode failures 和 network partitions 。
每个DataNode都周期性的向NameNode发送心跳信息。 一个 network partition 可能导致DataNodes子集丢失与NameNode的连接。NameNode会基于心跳信息的缺失来侦测这种情况。NameNode将没有心跳信息的DataNodes标记为 dead ,并不再转发任何IO请求给它们。任何注册到dead DataNode的数据对HDFS将不再可用。DataNode death会导致某些块的复制因子低于它们指定的值。NameNode不断跟踪需要复制的块,并在必要时启动复制。很多因素会导致重新复制:DataNode不可用,副本损坏,DataNode上硬盘故障,复制因子增加。
标记 DataNodes dead 的超时时间保守地设置了较长时间 (默认超过10分钟) 以避免DataNodes状态抖动引起的复制风暴。对于性能敏感的应用,用户可以设置较短的周期来标记DataNodes为过期,读写时避免过期节点。
HDFS 架构支持数据再平衡schemes。如果一个DataNode的空余磁盘空间低于阈值,sheme就会将数据从一个DataNode 移动到另外一个。在某些文件需求突然增长的情况下,sheme可能会在集群内动态的创建额外的副本,并再平衡其他数据。这些类型的数据再平衡schemes还没有实现。
有可能从DataNode获取的数据块,到达的时候损坏了。这种损坏可能是由于存储设备故障、网络故障、软件bug。HDFS客户端软件会HDFS的内容进行校验。当客户端创建HDFS文件的时候,它计算文件每个块的校验值,并以独立的隐藏文件存储在同一HDFS命名空间内。当客户端检索文件时候,它会校验从每个DataNode获取的数据,是否与关联校验文件内的校验值匹配。 如果不匹配,客户端可以从另外拥有副本块的DataNode检索。
FsImage 和 EditLog 是HDFS的核心数据结构。这些文件的损坏将导致HDFS实例异常。 因此,NameNode可以配置为支持多 FsImage 和 EditLog 副本模式。任何对 FsImage or EditLog 的更新都会导致每个 FsImages 和 EditLogs 的同步更新。 FsImage 和 EditLog 的同步更新会导致降低命名空间每秒的事物效率。但是,这种降级是可以接受的,因为HDFS应用是数据密集型,而不是元数据密集型。当NameNode重启的时候,它会选择最新的一致的 FsImage 和 EditLog 。
另外一种提供故障恢复能力的办法是多NameNodes 开启HA,以 shared storage on NFS or distributed edit log (called Journal)的方式。推荐后者。
Snapshots - 快照,支持在特定时刻存储数据的副本。快照功能的一个用法,可以回滚一个故障的HDFS实例到已知工作良好的时候。
HDFS被设计与支持超大的文件。与HDFS适配的软件都是处理大数据的。这些应用都只写一次,但是它们会读取一或多次,并且需要满足流式读速度。HDFS支持文件的 一次写入-多次读取 语义。 HDFS典型的块大小是128 MB.。因此,HDFS文件被分割为128 MB的块,可能的话每个块都位于不同的DataNode上。
当客户端以复制因子3写入HDFS文件时,NameNode以 复制目标选择算法 replication target choosing algorithm 检索DataNodes 列表。该列表包含了承载该数据块副本的DataNodes清单。然后客户端写入到第一个DataNode。第一DataNode逐步接受数据的一部分,将每一部分内容写入到本地仓库,并将该部分数据传输给清单上的第二DataNode。第二DataNode,按顺序接受数据块的每个部分,写入到仓库,然后将该部分数据刷新到第三DataNode。最终,第三DataNode将数据写入到其本地仓库。
因此,DataNode从管道的前一个DataNode获取数据,同时转发到管道的后一个DataNode。因此,数据是以管道的方式从一个DataNode传输到下一个的。
应用访问HDFS有很多方式。原生的,HDFS 提供了 FileSystem Java API 来给应用调用。还提供了 C language wrapper for this Java API 和 REST API 。另外,还支持HTTP浏览器查看HDFS实例的文件。 通过使用 NFS gateway ,HDFS还可以挂载到客户端作为本地文件系统的一部分。
HDFS的用户数据是以文件和目录的形式组织的。它提供了一个命令行接口 FS shell 来提供用户交互。命令的语法类似于其他shell (比如:bash, csh)。如下是一些范例:
FS shell 的目标是向依赖于脚本语言的应用提供与存储数据的交互。
DFSAdmin 命令用于管理HDFS集群。这些命令仅给HDFS管理员使用。如下范例:
如果启用了回收站配置,那么文件被 FS Shell 移除时并不会立即从HDFS删除。HDFS会将其移动到回收站目录(每个用户都有回收站,位于 /user/<username>/.Trash )。只要文件还在回收站内,就可以快速恢复。
最近删除的文件大多数被移动到 current 回收站目录 ( /user/<username>/.Trash/Current ),在配置周期内,HDFS给 current目录内的文件创建检查点 checkpoints (位于 /user/<username>/.Trash/<date> ) ,并删除旧的检查点。参考 expunge command of FS shell 获取更多关于回收站检查点的信息。
在回收站过期后,NameNode从HDFS命名空间删除文件。删除文件会将文件关联的块释放。注意,在用户删除文件和HDFS增加free空间之间,会有一个明显的延迟。
如下范例展示了FS Shell如何删除文件。我们在delete目录下创建两个文件(test1 & test2)
我们删除文件 test1。如下命令显示文件被移动到回收站。
现在我们尝试以skipTrash参数删除文件,该参数将不将文件发送到回收站。文件将会从HDFS完全删除。
我们检查回收站,只有文件test1。
如上,文件test1进了回收站,文件test2被永久删除了。
当缩减文件的复制因子时,NameNode选择可以被删除的多余副本。下一个Heartbeat会通报此信息给DataNode。DataNode然后会删除响应的块,相应的剩余空间会显示在集群内。同样,在setReplication API调用完成和剩余空间在集群显示之间会有一个时间延迟。
Hadoop JavaDoc API .
HDFS source code: http://hadoop.apache.org/version_control.html
B. 如何使用Java API访问HDFS为目录设置配额
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。
HDFS有着高容错性(fault-tolerant)的特点,并且设计用来部署在低廉的(low-cost)硬件上。而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求(requirements)这样可以实现流的形式访问(streaming access)文件系统中的数据。
C. java web怎么读取hdfs文件大小
用org.apache.hadoop.fs.DF public String toString() { return "df -k " + mount +"\n" + filesystem + "\t" + getCapacity() / 1024 + "\t" + getUsed() / 1024 + "\t" + getAvailable() / 1024 + "\t" + getPercentUsed() + "%\t" + mount; }
D. Hadoop如何处理如何增强Hadoop 安全
Hadoop是由Apache开源软件基金会开发的,运行于大规模普通服务器上的分布式系统基础架构,用于大规模数据的存储、计算、分析等。通过使用Hadoop平台用户可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力进行高速运算和存储。2007年雅虎发布了第一个Apache Hadoop版本0.14.1;2008年雅虎用Hadoop做到全网尺度的搜索;2009年雅虎把内部版本全部开源,于是IBM也加入Hadoop的开发阵营;2010年Facebook宣布正式运行世界最大的Hadoop集群;2011年Apache Hadoop1.0版本发布;2012年Apache Hadoop2.0版本发布。下面具体介绍一下Hadoop系统的架构。
Hadoop由许多元素构成,如下图图所示,包括HBase、Hive、Pig、Chukwa、Oozie和ZooKeeper等,但是其核心组件为HDFS和MapRece。
JobTraker和NameNode运行在同一个服务器上,我们称为Hadoop集群的主节点,负责接收客户端提交的作业,并将任务分配到不同的计算节点TaskTracker上,同时监控作业的运行情况,完成作业的更新和容错处理;Tasktracker通常和DataNode装在一起,称为Hadoop集群的从节点,它调用Map和Rece执行JobTracker指派的任务,并发送心跳消息给JobTracker,向JobTracker汇报可运行任务的数量。
Hadoop 一直缺乏安全机制,主要表现在以下几个方面。
为了增强Hadoop的安全机制, 从2009年起Apache专门抽出一个团队为Hadoop增加安全认证和授权机制,Apache Hadoop 1.0.0版本之后的版本添加了安全机制,但是升级到该版本后可能会导致Hadoop的一些应用不可用。
E. Hadoop生态系统-新手快速入门(含HDFS、HBase系统架构)
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。
Hadoop的框架最核心的设计就是:HDFS和MapRece。HDFS为海量的数据提供了存储,而MapRece则为海量的数据提供了计算。
广义的Hadoop,一般称为Hadoop生态系统,如下所示。
Hadoop生态系统中这些软件的作用:
HDFS 采用了主从(Master/Slave)结构模型,一个HDFS集群包括一个名称节点(NameNode)和若干个数据节点(DataNode)。
HDFS采用Java语言开发,因此任何支持JVM的机器都可以部署名称节点和数据节点。
在配置好Hadoop 集群之后,可以通过浏览器访问 http://[NameNodeIP]:9870,查询HDFS文件系统。通过该Web界面,可以查看当前文件系统中各个节点的分布信息。
HBase系统架构如下所示,包括客户端、Zookeeper服务器、Master主服务器、Region服务器。一般而言,HBase会采用HDFS作为底层数据存储。
在HBase服务器集群中,包含了一个Master和多个Region服务器,Master是HBase集群的“总管”,它必须知道Region服务器的状态。
HBase中可以启动多个Master,但是Zookeeper 可以帮助选举出一个Master 作为集群的总管,并保证在任何时刻总有唯一一个Master在运行,这样可以避免Master单点失效的问题。
Region服务器是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。
Store是Region服务器的核心。每个Store对应了表中的一个列族的存储。每一个Store包含了一个MemStore缓存和若干个StoreFile文件。
HBase采用HLog来保证系统发生故障时,能够恢复到正确的状态。HLog是磁盘上面的记录文件,它记录着所有的更新操作。
HBase系统为每个Region服务器配置了一个HLog文件,它是一种预写式日志(Write Ahead Log),也就是说,用户更新数据必须首先被记入日志后,才能写入MemStore缓存。
此外,Pig和Hive还为HBase提供了高层语言支持,使得在HBase上进行数据统计处理变的非常简单。 Sqoop则为HBase提供了方便的RDBMS数据导入功能,使得传统数据库数据向HBase中迁移变的非常方便。
注意:Hadoop 安装完成之后,只包含HDFS和MapRece,并不含HBase,因此需要在Hadoop 之上继续安装HBase。
F. 如何使用Java API读写HDFS
HDFS是Hadoop生态系统的根基,也是Hadoop生态系统中的重要一员,大部分时候,我们都会使用Linuxshell命令来管理HDFS,包括一些文件的创建,删除,修改,上传等等,因为使用shell命令操作HDFS的方式,相对比较简单,方便,但是有时候,我们也需要通过编程的方式来实现对文件系统的管理。比如有如下的一个小需求,要求我们实现读取HDFS某个文件夹下所有日志,经过加工处理后在写入到HDFS上,或者存进Hbase里,或者存进其他一些存储系统。这时候使用shell的方式就有点麻烦了,所以这时候我们就可以使用编程的方式来完成这件事了,当然散仙在这里使用的是原生的Java语言的方式,其他的一些语言例如C++,PHP,Python都可以实现,散仙在这里不给出演示了,(其实散仙也不会那些语言,除了刚入门的Python)。下面,散仙给出代码,以供参考:viewsourceprint?packagecom.java.api.hdfs;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReaderimportorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FileStatus;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;/***@author三劫散仙*JavaAPI操作HDFS*工具类****/publicclassOperaHDFS{publicstaticvoidmain(String[]args)throwsException{//System.out.println("aaa");//uploadFile();//createFileOnHDFS();//deleteFileOnHDFS();//createDirectoryOnHDFS();//deleteDirectoryOnHDFS();//renameFileOrDirectoryOnHDFS();readHDFSListAll();}/****加载配置文件***/staticConfigurationconf=newConfiguration();/***重名名一个文件夹或者文件()throwsException{FileSystemfs=FileSystem.get(conf);Pathp1=newPath("hdfs://10.2.143.5:9090/root/myfile/my.txt");fs.rename(p1,p2);System.out.println("重命名文件夹或文件成功..");}/*****读取HDFS某个文件夹的所有*文件,并打印****/()throwsException{//流读入和写入InputStreamin=null;//获取HDFS的conf//读取HDFS上的文件系统FileSystemhdfs=FileSystem.get(conf);//使用缓冲流,进行按行读取的功能BufferedReaderbuff=null;//获取日志文件的根目录Pathlistf=newPath("hdfs://10.2.143.5:9090/root/myfile/");//获取根目录下的所有2级子文件目录FileStatusstats[]=hdfs.listStatus(listf);//自定义j,方便查看插入信息intj=0;for(inti=0;i
G. HDFS文件
Hadoop支持的文件系统由很多(见下图),HDFS只是其中一种实现。Java抽象类 org.apache.hadoop.fs.FileSystem 定义了Hadoop中一个文件系统的客户端接口,并且该抽象类有几个具体实现。Hadoop一般使用URI(下图)方案来选取合适的文件系统实例进行交互。
特别的,HDFS文件系统的操作可以使用 FsSystem shell 、客户端(http rest api、Java api、C api等)。
FsSystem shell 的用法基本同本地shell类似,命令可参考 FsSystem shell
Hadoop是用Java写的,通过Java Api( FileSystem 类)可以调用大部分Hadoop文件系统的交互操作。更详细的介绍可参考 hadoop Filesystem 。
非Java开发的应用可以使用由WebHDFS协议提供的HTTP REST API,但是HTTP比原生的Java客户端要慢,所以不到万不得已尽量不要使用HTTP传输特大数据。通过HTTP来访问HDFS有两种方法:
两种如图
在第一种情况中,namenode和datanode内嵌的web服务作为WebHDFS的端节点运行(是否启用WebHDFS可通过dfs.webhdfs.enabled设置,默认为true)。文件元数据在namenode上,文件读写操作首先被发往namenode,有namenode发送一个HTTP重定向至某个客户端,指示以流的方式传输文件数据的目的或源datanode。
第二种方法依靠一个或多个独立代理服务器通过HTTP访问HDFS。所有集群的网络通信都需要通过代理,因此客户端从来不直接访问namenode或datanode。使用代理后可以使用更严格的防火墙策略和带宽策略。
HttpFs代理提供和WebHDFS相同的HTTP接口,这样客户端能够通过webhdfs URI访问接口。HttpFS代理启动独立于namenode和datanode的守护进程,使用httpfs.sh 脚本,默认在一个不同的端口上监听(14000)。
下图描述了
读文件时客户端与 HDFS 中的 namenode, datanode 之间的数据流动。
对上图的解释如下:
在读取过程中, 如果 FSDataInputStream 在和一个 datanode 进行交流时出现了一个错误,他就去试一试下一个最接近的块,他当然也会记住刚才发生错误的 datanode 以至于之后不会再在这个 datanode 上进行没必要的尝试。 DFSInputStream 也会在 datanode 上传输出的数据上核查检查数(checknums).如果损坏的块被发现了, DFSInputStream 就试图从另一个拥有备份的 datanode 中去读取备份块中的数据。
在这个设计中一个重要的方面就是客户端直接从 datanode 上检索数据,并通过 namenode 指导来得到每一个块的最佳 datanode。这种设计允许 HDFS 扩展大量的并发客户端,因为数据传输只是集群上的所有 datanode 展开的。期间,namenode 仅仅只需要服务于获取块位置的请求(块位置信息是存放在内存中,所以效率很高)。如果不这样设计,随着客户端数据量的增长,数据服务就会很快成为一个瓶颈。
我们知道,相对于客户端(之后就是 maprece task 了),块的位置有以下可能性:
我们认为他们对于客户端的带宽递减,距离递增(括号中表示距离)。示意图如下:
如果集群中的机器都在同一个机架上,我们无需其他配置,若集群比较复杂,由于hadoop无法自动发现网络拓扑,所以需要额外配置网络拓扑。
基本读取程序,将文件内容输出到console
FileSystemCat
随机读取
展开原码
下图描述了写文件时客户端与 HDFS 中的 namenode, datanode 之间的数据流动。
对上图的解释如下:
如果在任何一个 datanode 在写入数据的时候失败了,接下来所做的一切对客户端都是透明的:首先, pipeline 被关闭,在确认队列中的剩下的包会被添加进数据队列的起始位置上,以至于在失败的节点下游的任 何节点都不会丢失任何的包。然后与 namenode 联系后,当前在一个好的 datanode 会联系 namenode, 给失败节点上还未写完的块生成一个新的标识ID, 以至于如果这个失败的 datanode 不久后恢复了,这个不完整的块将会被删除。失败节点会从 pipeline 中移除,然后剩下两个好的 datanode 会组成一个的新的 pipeline ,剩下的 这些块的包(也就是刚才放在数据队列队首的包)会继续写进 pipeline 中好的 datanode 中。最后,namenode 注意到块备份数小于规定的备份数,他就安排在另一个节点上创建完成备份,直接从已有的块中复制就可以。然后一直到满足了备份数( dfs.replication )。如果有多个节点的写入失败了,如果满足了最小备份数的设置( dfs.namenode.repliction.min ),写入也将会成功,然后剩下的备份会被集群异步的执行备份,直到满足了备份数( dfs.replication )。
创建目录
文件压缩有两大好处:
Hadoop 对于压缩格式的是自动识别。如果我们压缩的文件有相应压缩格式的扩展名(比如 lzo,gz,bzip2 等)。Hadoop 会根据压缩格式的扩展名自动选择相对应的解码器来解压数据,此过程完全是 Hadoop 自动处理,我们只需要确保输入的压缩文件有扩展名。
Hadoop中有多种压缩格式、算法和工具,下图列出了常用的压缩方法。
表中的“是否可切分”表示对应的压缩算法是否支持切分,也就是说是否可以搜索数据流的任意位置并进一步往下读取数据,可切分的压缩格式尤其适合MapRece。
所有的压缩算法都需要权衡空间/时间:压缩和解压缩速度更快,其代价通常是只能节省少量的空间。不同的压缩工具有不同的特性:
更详细的比较如下
1.压缩性能比较
2.优缺点
另外使用hadoop原生(native)类库比其他java实现有更快的压缩和解压缩速度。特征比较如下:
使用容器文件格式结合压缩算法也能更好的提高效率。顺序文件、Arvo文件、ORCFiles、Parqurt文件同时支持压缩和切分。
压缩举例(Java)
压缩
解压缩
六、文件序列化
序列化是指将结构化数据转换为字节流以便在网络上传输或写到磁盘进行永久存储。反序列化狮子将字节流转换回结构化对象的逆过程。
序列化用于分布式数据处理的两大领域:进程间通信和永久存储。
对序列化的要求时是格式紧凑(高效使用存储空间)、快速(读写效率高)、可扩展(可以透明地读取老格式数据)且可以互操作(可以使用不同的语言读写数据)。
Hadoop使用的是自己的序列化格式 Writable ,它绝对紧凑、速度快,但不太容易用java以外的语言进行扩展或使用。
当然,用户也可以使用其他序列化框架或者自定义序列化方式,如 Avro 框架。
Hadoop内部还使用了 Apache Thrift 和 Protocal Buffers 来实现RPC和数据交换。