作者:张建

第一章 小文件过多带来的三个影响

Hive是一个建设在Apache Hadoop之上建设的一个数仓零碎,Hive应用Hadoop中的HDFS组件存储数据文件。在应用hive时通常会遇到小文件问题,即存储在HDFS上的数据文件是显著小于HDFS文件块大小的。小文件问题通常会带来以下影响。

1.1 HDFS内存资源耗费过大,并限度了数据存储规模

在HDFS中,具体的文件保留在datanode节点中,在namenode节点中会有一个内存对象与之对应,用于存储文件的元信息,如地位、大小、分块等,每个对象大概占用150个字节。因而,过多的碎片文件会使得namenode耗费大量的内存资源用于管理文件元数据,性能也会因而受到影响,这样namenode的内存容量重大制约了集群的倒退。

1.2 数据的拜访更加耗时

解决小文件并非Hadoop的设计指标,HDFS的设计指标是流式拜访大数据集。在HDFS中,每次读写文件都须要先从namenode获取文件元数据信息,而后与datanode建设连贯。而拜访大量的小文件会常常会须要大量的定位寻址操作,一直地在datanode间跳跃去检索小文件。这种拜访形式重大影响性能。

1.3 数据运算的工夫老本以及计算资源老本更高

在计算层面,小文件越多,意味着MapReduce执行工作时须要创立的map也会越多,这样,工作的启动与开释将消耗大量工夫。同时,每一个map都会开启一个JVM虚拟机用于执行工作,带来的调度以及计算成本也更高了。

第二章 我的项目中的2个理论案例

前文形容了在以Hive为数仓的大数据系统中普遍存在大量小文件的景象以及该景象为大数据处理过程中带来的3个挑战。本章将介绍笔者近几年生涯中在我的项目上遇到的2个实在案例,更进一步向读者阐明小文件的危害。

2.1 某医药行业客户我的项目内存压力问题

在某医药行业我的项目上,每天须要将数据从业务零碎同步到数仓中。小数据量的表每天进行离线全量同步,大数据量表进行每天离线增量同步以及实时同步到kudu临时缓存,而后再定时同步到hive中。但增量写入kudu经常出现工作失败的状况。

经排查,在CDH集群中,Kudu与HDFS namenode部署在同一台服务器上,并且写入hive的小文件过多,造成HDFS namenode占用了50%以上的物理内存用于存储文件元数据,导致有时候kudu写入数据时缓存区有余出现异常,从而导致工作失败。

针对这种状况,现场减少了一个spark工作定时调度执行,用于合并小文件,加重了namenode对服务器造成的内存压力,从而解决了kudu工作异样的问题。

2.2 某批发行业客户我的项目数据查问变慢问题

在某批发行业客户我的项目中,发现有一个对增量hive表查问的工作速度执行越来越慢,测试发现,几千万数据统计耗时须要几分钟,排查发现因为每天定时从多个数据源增量同步数据到hive表,导致hive表中小文件沉积越来越多,SQL执行耗时越来越长。

第三章 小文件问题解决

后面讲到小文件过多景象以及危害,接下来将从问题产生的起因剖析,并提供业界解决该问题的思路与计划。

3.1 小文件问题产生的起因

3.1.1 数据源自身蕴含大量的小文件

很多时候在Hive工作中,数据源就是Hive自身,当Hive中的表自身就蕴含大量小文件时,通过计算输入到指标表时,也将导致指标表中存在大量小文件。

3.1.2 reduce数量多导致生成的小文件增多

mapreduce工作中,reduce的数量与输入文件个数是对应的。在一些场景中,Hive对数据进行操作时,为了晋升底层mapreduce程序的运算速度,也会减少reduce的数量,导致产生的后果文件数量减少。

3.1.3 应用动静分区导致小文件增多

很多场景须要将表依据数据内容进行动静分区,Hive在向分区表写入数据时,在mapreduce工作中每个map会为该map工作中的数据对应的动静分区生成文件,如果每个map中的数据对应的分区有10个,有4000个map,则这次写入会生成4000*10个文件。

3.2 小文件问题的2种解决思路

3.2.1 从源端限度小文件的产生

在源端管制小文件产生的个数,如应用能够追加写的存储格局,防止应用动静分区,执行mapreduce工作时缩小reduce的数量。

这一类计划对利用场景有较高要求,如数仓建表须要兼顾到压缩性能和读取性能,这一类存储格局个别无奈做到追加写入,而表是否须要动静分区和业务场景以及表数据量的大小有很大关系,缩小reduce数量会使得工作执行效率变低。

3.2.2 对已产生的小文件进行解决

应用工具对曾经生成的小文件进行归档打包,这样减小namenode内存压力的同时,依然答应对文件进行通明的拜访,但在须要笼罩写入时须要将文件解除归档。创立离线工作将小文件合并成大文件,这一类计划比拟通用,毛病是合并时须要占用大量的计算资源。

3.3 大数据畛域提供的解决方案

3.2节中介绍了大数据中解决该问题的2个思路,在大数据组件的倒退过程中,很多组件曾经使用上述思路对小文件问题进行了解决。

3.3.1 Hive的解决方案

Hive SQL提供了distribute by语法用于管制map端如何拆分数据给reduce,依据distribute by前面的列对应的reduce个数进行散发,默认采纳hash算法,在应用上如配合分区表的分区列 insert select到构造与源表一样的指标表,能够在指标表对数据按分区进行压缩。

Hive还提供归档操作用于将小文件打包归档,如将分区表中一个分区的数据文件打包成一个归档文件,须要留神的是归档操作并不会压缩文件,并且读取归档数据时查问可能会变慢。

3.3.2 Spark的解决方案

Spark生成的文件数量间接取决于RDD里partition的数量和表分区数量。生成的文件数量个别是RDD分区数和表分区数的乘积。当工作并行度过高或者分区数目很大时,很容易产生很多的小文件。同样,也能够通过缩小最初一个阶段RDD的分区数来达到缩小生成文件数目的目标。

3.3.3 Flink的解决方案

Flink提供了小文件主动合并的性能,在同一个checkpoint周期的文件会主动合并。通过设置正当的checkpoint周期长度,能够缩小文件生成的数量。

上述各大数据组件提供的计划都采纳了第二种解决思路--即对已产生的小文件问题进行解决。第二种思路实质上是一种补救措施,无奈从根本上限度小文件的产生,因而其成果会弱于第一种。如果文件合并速度比小文件的生产速度慢,将会对数据系统造成很大的影响。

第四章 DCT的小文件问题解决方案

上文提到了大数据组件中内置的一些解决小文件问题的计划,但受限于其自身的限度,这些大数据组件无奈或很难采纳第一种思路,这也导致在极其状况下其机制可能生效,因而咱们须要一个依照第一种思路解决问题的办法。

DCT是一个用于异构数据源的数据同步工具,兼具实时CDC和离线同步两种同步形式。因为基于离线数据同步场景数据量较为固定,计算逻辑简略的特点,DCT抉择了第一种解决思路--即缩小小文件产生的形式,其本质上是一种事先预防措施。

DCT Hive离线写入组件从Hive获取表元数据,而后在本地结构数据文件后提交到HDFS。和间接应用Hive JDBC相比拟,这种形式不依赖离线程序,写入速度不受Hive计算层的影响,而且单次工作内生成的数据文件大小及数量可控。这种形式能够从源端解决该问题。

本节形容了使用第一种思路的解决方案,但这类计划也有其局限性,只能解决单次离线数据同步带来的小文件问题,当遇到流式数据或者小批次数据同步工作时还是无奈防止该问题。因而倡议联合事先预防和预先补救两种思路一起实现计划,这样能够将小文件过多的影响尽量减小。