大数据面试 | 06 我看了10篇文章,总结出的Hadoop小文件最全学习攻略

1. 什么是小文件

小文件的定义和hadoop中定义的block大小有关,这里把所有远远小于hadoop block大小的文件称为小文件。hadoop block块大小通常设置为128MB、256MB,趋向于越来越大。这里假定如果文件大小是小于block size的75%,则定义为小文件。

但小文件不仅是指文件比较小,如果Hadoop集群中的大量文件略大于block size,同样也会存在小文件问题。比如,假设block size是128MB,但加载到Hadoop的所有文件都是136MB,就会存在大量8MB的block。处理这种“小块”问题你可以调大block size来解决,但解决小文件问题却要复杂的多。

2. 小文件产生的原因

一个Hadoop集群中存在小文件问题是很正常的,可能的原因如下:

  1. 现在我们越来越多的将Hadoop用于(准)实时计算,在做数据抽取时处理的频率可能是每小时,每天,每周等,每次可能就只生成一个不到10MB的文件。即公司对实时数据的渴望,获取数据的时间间隔的缩短,导致采集进入hadoop的数据文件偏小。

2.数据源有大量小文件,未做处理直接拷贝到Hadoop集群。

3.MapReduce作业的配置未设置合理的reducer或者未做限制,每个reduce都会生成一个独立的文件。另外如果数据倾斜,导致大量的数据都shuffle到一个reduce,然后其他的reduce都会处理较小的数据量并输出小文件。

3. Hadoop的小文件对NameNode内存管理造成影响

Hadoop中的每个目录、文件和block都会以对象的形式保存在NameNode的内存中。

根据经验每个对象在内存中大概占用150个字节。如果HDFS中保存2000万个文件,每个文件都在同一个文件夹中,而且每个文件都只有一个block,则NameNode需要6GB内存。随着数据量的增长集群的扩容,最终会达到单台NameNode可以处理的文件(block)数量的上限。基于同样的假设,如果HDFS中保存的数据文件增长到10亿个,则NameNode需要300GB内存。这会对NameNode有什么影响:

  1. NameNode重启时,它都需要从本地磁盘读取每个文件的元数据,意味着你要读取300GB数据到内存中,不可避免导致NameNode启动时间较长。

  2. 一般来说,NameNode会不断跟踪并检查每个数据块的存储位置。这是通过DataNode的定时心跳上报其数据块来实现的。数据节点需要上报的block越多,则也会消耗越多的网络带宽/时延。

  3. NameNode本身使用300G内存,相当于JVM你需要配置300GB的heap,对于JVM来说本来就存在稳定性的风险,比如GC时间较长。

所以如果可以减少集群上的小文件数,则可以减少NameNode的内存占用,启动时间以及网络影响。

4. Hadoop的小文件问题主要是会对MapReduce性能造成影响

如果集群中有大量小文件,会降低MapReduce的处理性能,无论是Hive,Pig还是Java MapReduce,当然其实其他计算引擎比如Spark,Impala也会受到影响。


  1. 第一个原因是大量小文件意味着大量的随机磁盘IO。磁盘IO通常是MapReduce性能的最大瓶颈之一,在HDFS中对于相同数量的数据,一次大的顺序读取往往优于几次随机读取的性能。

  2. 当MapReduce任务启动时,每个数据block会被分配为一个map任务。HDFS中的每个文件至少是一个block。如果你有10000个文件,而且每个文件10MB,那么这个MapReduce作业会被分配为10000个map任务。一般来说每个Hadoop的map任务会运行在自己的JVM中,所以会带来10000个JVM的启动和关闭的资源开销。
    集群的资源是有限的,为了方便计算,假设我们在YARN的配置中为每个NodeManager配置20个vcore,那么为了同时运行10000个mapper,你需要500台节点。大多数Hadoop集群都小于这个规模,所以一般情况下大量map任务可能只能排队等待ResourceManager来分配资源。如果你只有10台机器,那么总共只有200个vcore,这个排队的队列会较大,相应的处理时间也会变的较长。
    如果10000个10MB文件换成800个128MB的文件,那么你就只需要800个map任务。相当于减少了一个数量级的JVM维护时间,同时也优化了磁盘IO。

5.解决NameNode的内存问题

上面的内容提到过每个block的元数据都需要加载到NameNode的内存中,这导致一个Hadoop集群在NameNode中存储的对象是有上限的,并且对象太多会带来启动时间较长以及网络延迟的问题。常见的有两种解决方案,减少集群的NameNode中的对象数量,或者以某种方式让NameNode使用更多的“内存”但不会导致较长的启动时间,这就是Hadoop Archive(HAR)文件和NameNode联邦。

1. Hadoop Archive Files

Hadoop archive files通过将许多小文件打包到更大的HAR文件中来缓解NameNode内存问题,类似于Linux上的TAR文件。这样可以让NameNode只处理单个HAR文件,而不是数十个或数百个小文件。可以使用har://前缀而不是hdfs://来访问HAR文件中的文件。HAR文件是基于HDFS中已有的文件创建的。因此,HAR文件不仅可以合并从数据源抽取到HDFS中的数据,也可以合并通过正常的MapReduce处理创建的数据。HAR文件可以独立的用于解决小文件问题,除了HDFS,没有其他的依赖。

虽然HAR文件减少了NameNode中小文件对内存的占用,但访问HAR文件内容性能可能会更低。HAR文件仍然随机存储在磁盘上,并且读取HAR内的文件需要访问两个索引 - 一个用于NameNode找到HAR文件本身,一个用于在HAR文件内找到小文件的位置。在HAR中读取文件实际上可能比读取存储在HDFS上的相同文件慢。MapReduce作业的性能同样会受到影响,因为它仍旧会为每个HAR文件中的每个文件启动一个map任务。

所以这里我们需要有一个权衡(trade-off),HAR文件可以解决NameNode内存问题,但同时会降低读取性能。如果你的小文件主要用于存档,并且不经常访问,那么HAR文件是一个很好的解决方案。如果小文件经常要被读取或者处理,那么可能需要重新考虑解决方案。

2. NameNode联邦

NameNode联邦允许你在一个集群中拥有多个NameNode,每个NameNode都存储元数据对象的子集。这样可以让所有的元数据对象都不止存储在单个机器上,也消除了单个节点的内存限制,因为你可以扩容。这听上去是一个很美丽的方案,但其实它也有局限性。


NameNode联邦隔离了元数据对象 - 仅仅只有某一个NameNode知道某一个特定的元数据对象在哪里,意思就是说如果你想找到某个文件,你必须知道它是保存在哪个NameNode上的。如果你的集群中有多个租户和或隔离的应用程序,那使用NameNode联邦是挺不错的,你可以通过租户或者应用程序来隔离元数据对象。但是,如果要在所有的应用程序之间共享数据,则该方法其实也并不是完美的。

6.解决MR的性能问题

根据之前讨论的内容,MapReduce性能问题主要是由随机磁盘IO和启动/管理太多的map任务组合引起的。解决方案似乎很明显 - 合并小文件,以下讨论一下几种解决方案:
注:虽然本章名为解决MapReduce的性能问题,但其实同样也是为了解决NameNode的压力,以及解决其他计算引擎比如Impala/Spark的性能问题。

1. 修改数据抽取方法/间隔

解决小文件问题的最简单方法就是在生成阶段就进行杜绝(在源头拒绝小文件的产生)。
如果是由数据源产生大量小文件并直接拷贝到Hadoop,可以调研了解数据源是否能生成一些大文件,或者从数据源到HDFS的数据抽取过程中进行数据处理合并小文件。如果每小时只抽取10MB的数据,考虑是否改为每天一次,这样创建1个240MB的文件而不是24个10MB的文件。
但是,可能无法控制数据源的改动配合或业务对数据抽取间隔的需求,这样小文件问题无法避免,这时可能需要考虑其他的解决方案。
————————————————

2. 批量文件合并

当产生小文件是不可避免时,文件合并是常见的解决方案。使用这种方法,定期运行一个MapReduce任务,读取某一个文件夹中的所有小文件,并将它们重写为较少数量的大文件。
比如一个文件夹中有1000个文件,你可以在一个MapReduce任务中指定reduce的数量为5,这样1000个输入文件会被合并为5个文件。随后进行一些简单的HDFS文件/文件夹操作(将新文件覆盖回原目录),则可以将NameNode的内存使用减少到200分之1,并且可以提高以后MapReduce或其他计算引擎对同一数据处理的性能。

在Hive或Java MapReduce中实现比较容易。这些MapReduce作业运行同样需要集群资源,所以建议调度在生产系统非繁忙时间段执行。但是,应该定期执行这种合并的MapReduce作业,因为小文件随时或者几乎每天都可能产生。

但这个合并程序需要有额外的逻辑来判断存在大量小文件的目录,或者你自己是知道哪些目录是存在大量小文件的。因为假如某个目录只有3个文件,运行合并作业远不如合并一个500个文件的文件夹的性能优势提升明显。

批量合并文件的方法无法保留原始文件名,如果原始文件名对于你了解数据来源非常重要,则批量合并文件的方法也不适用。
————————————————

3. 使用CombineFileInputFormat

CombineFileInputFormat是Hadoop提供的抽象类,它在MapReduce读取时合并小文件。合并的文件不会持久化到磁盘,它是在一个map任务中合并读取到的这些小文件。

好处是MapReduce可以不用为每个小文件启动一个map任务,而且因为是自带的实现类,你用额外将小文件先提前合并。这解决了MapReduce作业启动太多map任务的问题,但是因为作业仍然在读取多个小文件,随机磁盘IO依旧是一个问题

因为合并的文件并不会持久化保存到磁盘,因此CombineFileInputFormat方式并不会缓解NameNode内存管理问题。只是提高MapReduce或者Hive作业的性能。
————————————————

4. HBase列式存储

解决小文件问题,除了HDFS存储外,当然还可以考虑HBase列式存储。使用HBase可以将数据抽取过程从生成大量小HDFS文件更改为以逐条记录写入到HBase表。如果你对数据访问的需求主要是随机查找或者叫点查,则HBase是最好的选择。HBase在架构上就是为快速插入,存储大量数据,单个记录的快速查找以及流式数据处理而设计的。但如果你对数据访问的需求主要是全表扫描,则HBase不是最适合的。

使用HBase,可以较好的应对实时数据写入以及实时查询的场景。但是如何分配和平衡HBase与集群上其他的组件的资源使用,以及HBase本身运维都会带来额外的运维管理成本。另外,HBase的性能主要取决于你的数据访问方式,所以在选择HBase解决小文件问题之前,应该进行仔细调研和设计。

推荐阅读:

https://www.cnblogs.com/ballwql/p/8944025.html
https://blog.csdn.net/u010010664/article/details/83105174

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351