作者:张建
第一章 小文件过多带来的三个影响
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 计算层的影响,而且单次工作内生成的数据文件大小及数量可控。这种形式能够从源端解决该问题。
本节形容了使用第一种思路的解决方案,但这类计划也有其局限性,只能解决单次离线数据同步带来的小文件问题,当遇到流式数据或者小批次数据同步工作时还是无奈防止该问题。因而倡议联合事先预防和预先补救两种思路一起实现计划,这样能够将小文件过多的影响尽量减小。