Hdfs文件多少行|hdfs为什么不适合处理大量的小文件

A. HDFS 架构

HDFS 涉及两个重要进程:NameNode、DataNode。 他们一般都部署单独部署在不同服务器上,运行 NameNode 的服务器是主服务器,运行 DataNode 的服务器是从服务器。主服务器只有一个,从服务器有多个。 这种一主多从的架构基本适用于所有分布式系统或框架。可重复使用的架构方案叫作架构模式,一主多从可谓是大数据领域的最主要的架构模式。主服务器只有一台,掌控全局。从服务器有很多台,负责具体的事情。这样很多台服务器可以有效组织起来,对外表现出一个统一又强大的存储计算能力。 DataNode 负责文件数据的存储和读写操作,HDFS 将文件数据分割成若干数据块(Block),每个 DataNode 存储一部分数据块,这样文件就分布存储在整个 HDFS 服务器集群中。应用程序客户端(Client)可以并行对这些数据块进行访问,从而使得 HDFS 可以在服务器集群规模上实现数据并行访问,极大地提高了访问速度。 在实践中,HDFS 集群的 DataNode 服务器会有很多台,一般在几百台到几千台这样的规模,每台服务器配有数块磁盘,整个集群的存储容量大概在几 PB 到数百 PB。 NameNode 负责整个分布式文件系统的元数据(MetaData)管理,也就是文件路径名、数据块的 ID 以及存储位置等信息,相当于操作系统中文件分配表(FAT)的角色。HDFS 为了保证数据的高可用,会将一个数据块复制为多份(默认3份),并将多份相同的数据块存储在不同的机架的服务器上。这样当有磁盘损坏,或者某个 DataNode 服务器宕机,甚至某个交换机宕机时,系统能通过其备份的数据块进行查找。 处理客户端的请求。 客户端向 HDFS 上传文件。 客户端向 HDFS 读取文件。 像 NameNode 这样主从服务器管理同一份数据的场景,如果从服务器错误地以为主服务器宕机而接管集群管理,会出现主从服务器一起对 DataNode 发送指令,进而导致集群混乱,也就是所谓的“脑裂”。这也是这类场景选举主服务器时,引入 ZooKeeper 的原因。

B. hdfs详解之块、小文件和副本数

1、block:block是物理切块,在文件上传到HDFS文件系统后,对大文件将以每128MB的大小切分若干,存放在不同的DataNode上。例如一个文件130M,那么他会存被切分成2个块,一个块128M,另一个块2M.

1、HDFS 适应场景: 大文件存储,小文件是致命的 2、如果小文件很多的,则有可能将NN(4G=42亿字节)撑爆。例如:1个小文件(阈值<=30M),那么NN节点维护的字节大约250字节。一亿个小文件则是250b * 1亿=250亿.将会把NN节点撑爆。如果一亿个小文件合并成100万个大文件:250b * 1百万=2亿字节。 3、在生产上一般会: 1)调整小文件阈值 2)合并小文件: a.数据未落地到hdfs之前合并 b.数据已经落到hdfs,调用spark service服务 。每天调度去合并 (-15天 业务周期) 3)小文件的危害: a.撑爆NN。 b.影响hive、spark的计算。占用集群计算资源

1、如果是伪分布式,那么副本数只能为一。 2、生成上副本数一般也是官方默认参数: 3份

如果一个文件130M,副本数为3。那么第一个block128M,有三份。另外一个block2M,也有三份。 题目: blockSize128M,副本数3份,那么一个文件260M,请问多少块,多少实际存储? 260%128=2….4M 3个块 3个副本=9块 260M 3=780M

C. HDFS架构

HDFS中的文件是以数据块(Block)的形式存储的,默认最基本的存储单位是128 MB(Hadoop 1.x为64 MB)的数据块。也就是说,存储在HDFS中的文件都会被分割成128 MB一块的数据块进行存储,如果文件本身小于一个数据块的大小,则按实际大小存储,并不占用整个数据块空间。HDFS的数据块之所以会设置这么大,其目的是减少寻址开销。数据块数量越多,寻址数据块所耗的时间就越多。当然也不会设置过大,MapRece中的Map任务通常一次只处理一个块中的数据,如果任务数太少,作业的运行速度就会比较慢。HDFS的每一个数据块默认都有三个副本,分别存储在不同的DataNode上,以实现容错功能。因此,若数据块的某个副本丢失并不会影响对数据块的访问。数据块大小和副本数量可在配置文件中更改 NameNode是HDFS中存储元数据(文件名称、大小和位置等信息)的地方,它将所有文件和文件夹的元数据保存在一个文件系统目录树中,任何元数据信息的改变,NameNode都会记录。HDFS中的每个文件都被拆分为多个数据块存放,这种文件与数据块的对应关系也存储在文件系统目录树中,由NameNode维护。NameNode还存储数据块到DataNode的映射信息,这种映射信息包括:数据块存放在哪些DataNode上、每个DataNode上保存了哪些数据块。NameNode也会周期性地接收来自集群中DataNode的“心跳”和“块报告”。通过“心跳”与DataNode保持通信,监控DataNode的状态(活着还是宕机),若长时间接收不到“心跳”信息,NameNode会认为DataNode已经宕机,从而做出相应的调整策略。“块报告”包含了DataNode上所有数据块的列表信息。 DataNode是HDFS中真正存储数据的地方。客户端可以向DataNode请求写入或读取数据块,DataNode还在来自NameNode的指令下执行块的创建、删除和复制,并且周期性地向NameNode汇报数据块信息。 NodeSecondaryNameNode用于帮助NameNode管理元数据,从而使NameNode能够快速、高效地工作。它并不是第二个NameNode,仅是NameNode的一个辅助工具。HDFS的元数据信息主要存储于两个文件中:fsimage和edits。fsimage是文件系统映射文件,主要存储文件元数据信息,其中包含文件系统所有目录、文件信息以及数据块的索引;edits是HDFS操作日志文件,HDFS对文件系统的修改日志会存储到该文件中。当NameNode启动时,会从文件fsimage中读取HDFS的状态,也会对文件fsimage和edits进行合并,得到完整的元数据信息,随后会将新HDFS状态写入fsimage。但是在繁忙的集群中,edits文件会随着时间的推移变得非常大,这就导致NameNode下一次启动的时间会非常长。为了解决这个问题,则产生了SecondaryNameNode,SecondaryNameNode会定期协助NameNode合并fsimage和edits文件,并使edits文件的大小保持在一定的限制内。SecondaryNameNode通常与NameNode在不同的计算机上运行,因为它的内存需求与NameNode相同,这样可以减轻NameNode所在计算机的压力。

D. 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

E. hdfs适合存储多大的单个文件

首先hdfs是建立在多个机器文件系统上的一个逻辑上的文件系统。它的底层数据以数据块方式存储,块大小可进行调整。假如你设置一个数据块大小为256M,上传一个1G的文件,它底层会将这个文件分成4块存储,每个块256M。你在hdfs上看到的是一个完整的文件,随时可对这个文件进行操作,无需关注它的存储。就像你在操作系统上操作文件一样,无需关注它存在那个磁盘哪个扇区

F. hdfs为什么不适合处理大量的小文件

在HDFS中,namenode将文件系统中的元数据存储在内存中,因此,HDFS所能存储的文件数量会受到namenode内存的专限制。一般属来说,每个文件、目录、数据块的存储信息大约占150个字节,根据当前namenode的内存空间的配置,就可以计算出大约能容纳多少个文件了。 有一种误解就是,之所以HDFS不适合大量小文件,是因为即使很小的文件也会占用一个块的存储空间。这是错误的,HDFS与其它文件系统不同,小于一个块大小的文件,不会占用一个块的空间。

G. HDFS 上每个数据节点最多能存多少,多大的数据

HDFS 上每个数据节点最多能存储多少数据取决于节点的硬盘大小。对于单个节点来说,其存储的容量为磁盘容量减去hdfs-site.xml配置文件中dfs.datanode..reserved参数值。对于集群来说,取决于集群中所有DataNode节点的硬盘大小之和。但是需要注意考虑集群的备份数量,假设备份数量为3,集群总容量为3TB,则实际可以存储1TB的文件。

H. parquet和orc

Parquet文件是自解析的,文件中包括该文件的数据和元数据。在HDFS文件系统和Parquet文件中存在如下几个概念: 1)HDFS块(Block):它是HDFS上的最小的副本单位,HDFS会把一个Block存储在本地的一个文件并且维护分散在不同的机器上的多个副本,通常情况下一个Block的大小为256M、512M等。 2)HDFS文件(File):一个HDFS的文件,包括数据和元数据,数据分散存储在多个Block中。 3)行组(Row Group):按照行将数据物理上划分为多个单元,每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,Parquet读写的时候会将整个行组缓存在内存中,所以如果每一个行组的大小是由内存大的小决定的。 4)列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。不同的列块可能使用不同的算法进行压缩。 5)页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。 Parquet文件的格式如下图所示: 可以看出,存储格式中元数据索引信息是被存储在最后的,所以当读取某一行的数据的时候,就需要去定位最后的索引信息,最后才能去读取对应的行数据。元数据包括 Parquet 原始类型定义、Page类型、编码类型、压缩类型等等。 Parquet 支持嵌套结构的数据模型,而非扁平式的数据模型,这是 Parquet 相对其他列存比如 ORC 的一大特点或优势。支持嵌套式结构,意味着 Parquet 能够很好的将诸如 Protobuf,thrift,json 等对象模型进行列式存储。 Parquet 的数据模型也是 schema 表达方式,用关键字 message 表示。每个字段包含三个属性,repetition属性(required/repeated/optional)、数据类型(primitive基本类型/group复杂类型)及字段名。如: 和Parquet类似,ORC文件也是以二进制方式存储的,所以是不可以直接读取,ORC文件也是自解析的,它包含许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。ORC的文件结构如下图,其中涉及到如下的概念: ORC文件:保存在文件系统上的普通二进制文件,一个ORC文件中可以包含多个stripe,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。 文件级元数据:包括文件的描述信息PostScript、文件meta信息(包括整个文件的统计信息)、所有stripe的信息和文件schema信息。 stripe:一组行形成一个stripe,每次读取文件是以行组为单位的,一般为HDFS的块大小,保存了每一列的索引和数据。 stripe元数据:保存stripe的位置、每一个列的在该stripe的统计信息以及所有的stream类型和位置。 row group:索引的最小单位,一个stripe中包含多个row group,默认为10000个值组成。 stream:一个stream表示文件中一段有效的数据,包括索引和数据两类。索引stream保存每一个row group的位置和统计信息,数据stream包括多种类型的数据,具体需要哪几种是由该列类型和编码方式决定。 在ORC文件中保存了三个层级的统计信息,分别为文件级别、stripe级别和row group级别的,他们都可以用来根据Search ARGuments(谓词下推条件)判断是否可以跳过某些数据,在统计信息中都包含成员数和是否有null值,并且对于不同类型的数据设置一些特定的统计信息。 读取ORC文件是从尾部开始的,第一次读取16KB的大小,尽可能的将Postscript和Footer数据都读入内存。文件的最后一个字节保存着PostScript的长度,它的长度不会超过256字节,PostScript中保存着整个文件的元数据信息,它包括文件的压缩格式、文件内部每一个压缩块的最大长度(每次分配内存的大小)、Footer长度,以及一些版本信息。在Postscript和Footer之间存储着整个文件的统计信息(上图中未画出),这部分的统计信息包括每一个stripe中每一列的信息,主要统计成员数、最大值、最小值、是否有空值等。 接下来读取文件的Footer信息,它包含了每一个stripe的长度和偏移量,该文件的schema信息(将schema树按照schema中的编号保存在数组中)、整个文件的统计信息以及每一个row group的行数。 处理stripe时首先从Footer中获取每一个stripe的其实位置和长度、每一个stripe的Footer数据(元数据,记录了index和data的的长度),整个striper被分为index和data两部分,stripe内部是按照row group进行分块的(每一个row group中多少条记录在文件的Footer中存储),row group内部按列存储。每一个row group由多个stream保存数据和索引信息。每一个stream的数据会根据该列的类型使用特定的压缩算法保存。在ORC中存在如下几种stream类型: PRESENT:每一个成员值在这个stream中保持一位(bit)用于标示该值是否为NULL,通过它可以只记录部位NULL的值 DATA:该列的中属于当前stripe的成员值。 LENGTH:每一个成员的长度,这个是针对string类型的列才有的。 DICTIONARY_DATA:对string类型数据编码之后字典的内容。 SECONDARY:存储Decimal、timestamp类型的小数或者纳秒数等。 ROW_INDEX:保存stripe中每一个row group的统计信息和每一个row group起始位置信息。 在初始化阶段获取全部的元数据之后,可以通过includes数组指定需要读取的列编号,它是一个boolean数组,如果不指定则读取全部的列,还可以通过传递SearchArgument参数指定过滤条件,根据元数据首先读取每一个stripe中的index信息,然后根据index中统计信息以及SearchArgument参数确定需要读取的row group编号,再根据includes数据决定需要从这些row group中读取的列,通过这两层的过滤需要读取的数据只是整个stripe多个小段的区间,然后ORC会尽可能合并多个离散的区间尽可能的减少I/O次数。然后再根据index中保存的下一个row group的位置信息调至该stripe中第一个需要读取的row group中。 ORC文件格式只支持读取指定字段,还不支持只读取特殊字段类型中的指定部分。 使用ORC文件格式时,用户可以使用HDFS的每一个block存储ORC文件的一个stripe。对于一个ORC文件来说,stripe的大小一般需要设置得比HDFS的block小,如果不这样的话,一个stripe就会分别在HDFS的多个block上,当读取这种数据时就会发生远程读数据的行为。如果设置stripe的只保存在一个block上的话,如果当前block上的剩余空间不足以存储下一个strpie,ORC的writer接下来会将数据打散保存在block剩余的空间上,直到这个block存满为止。这样,下一个stripe又会从下一个block开始存储。 由于ORC中使用了更加精确的索引信息,使得在读取数据时可以指定从任意一行开始读取,更细粒度的统计信息使得读取ORC文件跳过整个row group,ORC默认会对任何一块数据和索引信息使用ZLIB压缩,因此ORC文件占用的存储空间也更小,这点在后面的测试对比中也有所印证。

I. hdfs的特点有哪些

hdfs的特点一、hdfs的优点1.支持海量数据的存储:一般来说,HDFS存储的文件可以支持TB和PB级别的数据。2.检测和快速应对硬件故障:在集群环境中,硬件故障是常见性问题。因为有上千台服务器连在一起,故障率很高,因此故障检测和自动恢复hdfs文件系统的一个设计目标。假设某一个datanode挂掉之后,因为数据是有备份的,还可以从其他节点里找到。namenode通过心跳机制来检测datanode是否还存活。3.流式数据访问:(HDFS不能做到低延迟的数据访问,但是HDFS的吞吐量大)=》Hadoop适用于处理离线数据,不适合处理实时数据。HDFS的数据处理规模比较大,应用一次需要大量的数据,同时这些应用一般都是批量处理,而不是用户交互式处理。应用程序能以流的形式访问数据库。主要的是数据的吞吐量,而不是访问速度。访问速度最终是要受制于网络和磁盘的速度,机器节点再多,也不能突破物理的局限。4.简化的一致性模型:对于外部使用用户,不需要了解hadoop底层细节,比如文件的切块,文件的存储,节点的管理。一个文件存储在HDFS上后,适合一次写入,多次读取的场景。因为存储在HDFS上的文件都是超大文件,当上传完这个文件到hadoop集群后,会进行文件切块,分发,复制等操作。如果文件被修改,会导致重新触发这个过程,而这个过程耗时是最长的。所以在hadoop里,2.0版本允许数据的追加,单不允许数据的修改。5.高容错性:数据自动保存多个副本,副本丢失后自动恢复。可构建在廉价的机器上,实现线性扩展。当集群增加新节点之后,namenode也可以感知,将数据分发和备份到相应的节点上。6.商用硬件:Hadoop并不需要运行在昂贵且高可靠的硬件上。它是设计运行在商用硬件(在各种零售店都能买到的普通硬件)的集群上的,因此至少对于庞大的集群来说,节点故障的几率还是非常高的。HDFS遇到上述故障时,被设计成能够继续运行且不让用户察觉到明显的中断。二、HDFS缺点(局限性)1、不能做到低延迟数据访问:由于hadoop针对高数据吞吐量做了优化,牺牲了获取数据的延迟,所以对于低延迟数据访问,不适合hadoop。对于低延迟的访问需求,HBase是更好的选择。2、不适合大量的小文件存储 :由于namenode将文件系统的元数据存储在内存中,因此该文件系统所能存储的文件总数受限于namenode的内存容量。根据经验,每个文件、目录和数据块的存储信息大约占150字节。因此,如果有一百万个小文件,每个小文件都会占一个数据块,那至少需要300MB内存。如果是上亿级别的,就会超出当前硬件的能力。3、修改文件:对于上传到HDFS上的文件,不支持修改文件。Hadoop2.0虽然支持了文件的追加功能,但是还是不建议对HDFS上的文件进行修改。因为效率低下。HDFS适合一次写入,然后多次读取的场景。4、不支持用户的并行写:同一时间内,只能有一个用户执行写操作。

J. 大数据之HDFS

在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在集群上的文件系统称为 分布式文件系统 。

HDFS (Hadoop Distributed File System)是 Hadoop 的核心组件之一, 非常适于存储大型数据 (比如 TB 和 PB), HDFS 使用多台计算机存储文件,并且提供统一的访问接口,像是访问一个普通文件系统一样使用分布式文件系统。

HDFS是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上。它所具有的 高容错、高可靠性、高可扩展性、高获得性、高吞吐率 等特征为海量数据提供了不怕故障的存储,为超大数据集的应用处理带来了很多便利。

HDFS 具有以下 优点 :

当然 HDFS 也有它的 劣势 ,并不适合以下场合:

HDFS 采用Master/Slave的架构来存储数据,这种架构主要由四个部分组成,分别为HDFS Client、NameNode、DataNode和Secondary NameNode。

Namenode是整个文件系统的管理节点,负责接收用户的操作请求。它维护着整个文件系统的目录树,文件的元数据信息以及文件到块的对应关系和块到节点的对应关系。

Namenode保存了两个核心的数据结构:

在NameNode启动的时候,先将fsimage中的文件系统元数据信息加载到内存,然后根据edits中的记录将内存中的元数据同步到最新状态;所以,这两个文件一旦损坏或丢失,将导致整个HDFS文件系统不可用。

为了避免edits文件过大, SecondaryNameNode会按照时间阈值或者大小阈值,周期性的将fsimage和edits合并 ,然后将最新的fsimage推送给NameNode。

并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。其主要任务是辅助 NameNode,定期合并 fsimage和fsedits。

Datanode是实际存储数据块的地方,负责执行数据块的读/写操作。

一个数据块在DataNode以文件存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据,包括数据块的长度,块数据的校验和,以及时间戳。

文件划分成块,默认大小128M,以快为单位,每个块有多个副本(默认3个)存储不同的机器上。

Hadoop2.X默认128M, 小于一个块的文件,并不会占据整个块的空间 。Block数据块大小设置较大的原因:

文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储。

Client 还提供一些命令来管理 HDFS,比如启动或者关闭HDFS。

Namenode始终在内存中保存metedata,用于处理“读请求”,到有“写请求”到来时,namenode会首 先写editlog到磁盘,即向edits文件中写日志,成功返回后,才会修改内存 ,并且向客户端返回,Hadoop会维护一个fsimage文件,也就是namenode中metedata的镜像,但是fsimage不会随时与namenode内存中的metedata保持一致,而是每隔一段时间通过合并edits文件来更新内容。

HDFS HA(High Availability)是为了解决单点故障问题。

HA集群设置两个名称节点,“活跃( Active )”和“待命( Standby )”,两种名称节点的状态同步,可以借助于一个共享存储系统来实现,一旦活跃名称节点出现故障,就可以立即切换到待命名称节点。

为了保证读写数据一致性,HDFS集群设计为只能有一个状态为Active的NameNode,但这种设计存在单点故障问题,官方提供了两种解决方案:

通过增加一个Secondary NameNode节点,处于Standby的状态,与Active的NameNode同时运行。当Active的节点出现故障时,切换到Secondary节点。

为了保证Secondary节点能够随时顶替上去,Standby节点需要定时同步Active节点的事务日志来更新本地的文件系统目录树信息,同时DataNode需要配置所有NameNode的位置,并向所有状态的NameNode发送块列表信息和心跳。

同步事务日志来更新目录树由JournalNode的守护进程来完成,简称为QJM,一个NameNode对应一个QJM进程,当Active节点执行任何命名空间文件目录树修改时,它会将修改记录持久化到大多数QJM中,Standby节点从QJM中监听并读取编辑事务日志内容,并将编辑日志应用到自己的命名空间。发生故障转移时,Standby节点将确保在将自身提升为Active状态之前,从QJM读取所有编辑内容。

注意,QJM只是实现了数据的备份,当Active节点发送故障时,需要手工提升Standby节点为Active节点。如果要实现NameNode故障自动转移,则需要配套ZKFC组件来实现,ZKFC也是独立运行的一个守护进程,基于zookeeper来实现选举和自动故障转移。

虽然HDFS HA解决了“单点故障”问题,但是在系统扩展性、整体性能和隔离性方面仍然存在问题:

HDFS HA本质上还是单名称节点。HDFS联邦可以解决以上三个方面问题。

在HDFS联邦中,设计了多个相互独立的NN,使得HDFS的命名服务能够水平扩展,这些NN分别进行各自命名空间和块的管理,不需要彼此协调。每个DN要向集群中所有的NN注册,并周期性的发送心跳信息和块信息,报告自己的状态。

HDFS联邦拥有多个独立的命名空间,其中,每一个命名空间管理属于自己的一组块,这些属于同一个命名空间的块组成一个“块池”。每个DN会为多个块池提供块的存储,块池中的各个块实际上是存储在不同DN中的。


赞 (0)