草庐IT

为啥集群小文件治理那么重要,你真的懂吗?

涤生大数据 2023-03-28 原文
小文件是 Hadoop 集群运维中的常见挑战,尤其对于大规模运行的集群来说可谓至关重要。如果处理不好,可能会导致许多并发症。Hadoop集群本质是为了TB,PB规模的数据存储和计算应运而生的。为啥大数据开发都说小文件的治理重要,说HDFS 存储小文件效率低下,比如增加namenode负载等,降低访问效率等?究竟本质上为什么重要?以及如何从本质上剖析小文件,治理小文件呢?今天就带你走进小文件的世界。

1.什么是小文件?

日常生产中HDFS上小文件产生是一个很正常的事情,有些甚至是不可避免,比如jar,xml配置文件,tmp临时文件,流式任务等都是小文件的组成部分。当然更多的是因为集群设置不合理,造成一些意料之外的小文件产生。实际公司生产中对于小文件的大小没有一个统一的定义。一般公司集群的blocksize的大小在128/256两者居多。首先小文件大小肯定是要远小于blocksize的文件。一般公司小文件的大小定义如1Mb,8Mb,甚至16Mb,32Mb更大。根据公司实际集群状态定义,因为有些情况合并小文件需要消耗额外的资源。

既然剖析小文件,那么不可避免的要先剖析hdfs的存储原理。众多周知了,HDFS上文件的数据存储分为namenode元数据管理和实际数据文件。hdfs上的数据文件被拆分成块block,这些块block在整个集群中的datanode的本地文件系统上存储和复制,每个块也维护者自己的blockmeta信息。namenode主要维护这些文件的元数据信息,具体namenode的解析参考我的其他博客。

如下一个某个文件的某个block在data上存储的情况。


2.小文件的产生

1.流式数据,如flume,kafak,sparkstreaming,storm,flink等,流式增量文件,小窗口文件,如几分钟一次等。

2.MapReduce引擎任务:如果纯map任务,大量的map;如果mapreduce任务,大量的reduce;两者都会造成大量的文件。出现这种情况的原因很多,果分布表的过度分区,输入大量的小文件,参数设置的不合理等,输出没有文件合并等。

3.spark任务过度并行化,Spark 分区越多,写入的文件就越多。

4.文件的压缩与存储格式不合理;一般生产公司很少使用textfile这种低效的文件格式了。

使用压缩,降低文件的大小,同时也会降低文件的总块数。注意文件存储格式和压缩不合理只是加剧小文件问题,不是产生小文件的本质。

3.小文件的危害

3.1小文件对namenod的影响

如下图1,一个文件192Mb,默认blocksize=128Mb,副本个数为3,存储为2个block。

图1


如下图2,同样一个文件192Mb,默认blocksize=128Mb,副本个数为3,存储为192个block

图2

namenode的namespace中主要占存储对象是文件的目录个数,文件(文件名长度)以及文件block数。根据namenode实际使用经验来看,一个存储对象大概占用150字节的空间。HDFS上存储文件占用的namenode内存计算公式如下:

Memory=150bytes*(1个文件inode+(文件的块数*副本个数))

如上图1 ,一个文件192Mb,默认blocksize=128Mb,副本个数为3,存储为2个block,需要namenode内存=150*(1+2*3)=1050 Bytes

同理,图2 一个文件192Mb,默认blocksize=128Mb,副本个数为3,存储为192个block,需要namenode内存=150 x (192 + (192 x 3)) = 115200 Bytes

尖叫总结:

1 .从上面可以看出,同样的一个文件,大小不同形态的存储占用namenode的内存之比相差了109倍之多。所以如果对于单namenode的集群来说,大量的小文件的会占用大量的namenode堆内存空间,给集群的存储造成瓶颈。有些人可能会说我们联邦,多组namenode不就没有这个问题了,其实不然,且往下看

2.当 NameNode 重新启动时(虽然生产上这种情况很少),它必须将文件系统元数据fsimage从本地磁盘加载到内存中。这意味着如果 namenode 元数据很大,重启会更慢(以我们公司3亿block,5万多个文件对象来说,重启一次1.5小时,期间应用不可用)其次,datanode 还通过网络向 NameNode 报告块更改;更多的块意味着要通过网络报告更多的变化,等待时间更长。

3.更多的文件,更多的block,意味着更多的读取请求需要由 NameNode 提供服务,这将增加 RPC 队列和处理延迟,进而导致namenode性能和响应能力下降。官方介绍说接近 40K~50K RPCs/s 人为是极高的负载。实际使用来看比这低时对于namenode来说性能都会打很大的折扣。

3.2 小文件对datanode影响

文件的block存储是存储在datanode本地系统上,底层的磁盘上,甚至不同的挂载目录,不同的磁盘上。大量的小文件,意味着数据着寻址需要花费很多时间,尤其对于高负载的集群来说,磁盘使用率50%以上的集群,花费在寻址的时间比文件读取写入的时间更多。这种就违背了blocksize大小设计的初衷(实践显示最佳效果是:寻址时间仅占传输时间的1%)。这样会造成磁盘的读写会很慢,拥有大量小文件会导致更多的磁盘搜索。如下磁盘延迟:

3.3小文件对计算的影响

基于HDFS文件系统的计算,blokc块是最小粒度的数据处理单元。块的多少往往影响应用程序的吞吐量。更多的文件,意味着更多的块,以及更多的节点分布。

比如以MapReduce任务为例(hive等),在 MapReduce 中,会为每个读取的块生成一个单独的 Map 任务,如果大量小文件,大量的块,意味着着更多任务调度,任务创建开销,以及更多的任务管理开销(MapReduce 作业的 application master 是一个 Java 应用,它的主类是 MRAppMaster。它通过创建一定数量的bookkeeping object跟踪作业进度来初始化作业,该对象接受任务报告的进度和完成情况)。虽然可以开启map前文件合并,但是这也需要不停地从不同节点建立连接,数据读取,网络传输,然后进行合并,同样会增加消耗资源和增加计算时间,成本也很高。

同样,如果是spark计算引擎,executor的一次读取和处理一个分区,默认情况下,每个分区是一个 HDFS 块,如果大量的小文件,每个文件都在不同的分区中读取,这将导致大量的任务调度开销,同时每个 CPU 内核的吞吐量降低。

简单总结一下:小文件对于计算的影响就是需要大量节点之间频繁建立联系,数据传输等,浪费资源,消耗时间长。其次小文件相关大量的任务初始化时间甚至比计算时间还长,造成计算资源的使用浪费,降低集群的吞吐量。

本文转载自微信公众号「涤生大数据」,作者「涤生大数据」,可以通过以下二维码关注。

转载本文请联系「涤生大数据」公众号。

有关为啥集群小文件治理那么重要,你真的懂吗?的更多相关文章

  1. ruby - 使 faSTLane 不那么冗长 - 2

    有没有办法配置(例如,可以使用Fastfile)或以更简洁的方式执行FaSTLane?它目前打印出很多信息,这些信息通常会使开发人员对警告和错误视而不见。主要问题是需要花费一些时间在大量无用消息中滚动和搜索黄色/红色文本,直到您了解发生了什么。默认设置会打印所有内容,令人惊讶的是甚至还有--verbosemode对于CLI,但我找不到任何相反的东西,例如--quiet模式。编辑:下面是一些我希望能够抑制的输出示例。考虑到我使用了来自gitrepo的Fastfile,gym、match、cocoapods、get_version_number、increment_version_numb

  2. ruby-on-rails - 我真的需要在 Rails 中使用 csv gem 吗? - 2

    我的问题很简单:我是否必须在使用RubyonRails的类上require'csv'?如果我打开一个railsconsole并尝试使用CSVgem它可以工作,但我必须在文件中这样做吗? 最佳答案 CSVlibrary是ruby​​标准库的一部分;它不是gem(即第三方库)。与所有标准库(与核心库不同)一样,csv不会由ruby​​解释器自动加载。所以是的,在您的应用程序中某处您确实需要要求它:irb(main):001:0>CSVNameError:uninitializedconstantCSVfrom(irb):1from/Us

  3. ruby-on-rails - ruby 真的是一种完全面向对象的语言吗? - 2

    Ruby是完全面向对象的语言。在ruby​​中,一切都是对象,因此属于某个类。例如5属于Objectclass1.9.3p194:001>5.class=>Fixnum1.9.3p194:002>5.class.superclass=>Integer1.9.3p194:003>5.class.superclass.superclass=>Numeric1.9.3p194:005>5.class.superclass.superclass.superclass=>Object1.9.3p194:006>5.class.superclass.superclass.superclass.su

  4. ruby - Camping 和 Sinatra 之间有什么重要区别吗? - 2

    我的感觉是Camping和Sinatra之间的差异不是很大,您可以安全地选择其中任何一个并且没问题。但我想问问Ruby专家,这是不是真的。Sinatra和Camping微框架之间实际上有什么重要区别吗?您将如何决定使用哪一个? 最佳答案 我知道的唯一显着区别是Camping像Rails一样基于MVC模式,并且与ActiveRecord耦合。Sinatra更加不可知。Camping也不再维护,而Sinatra正在积极开发中。仅这一点就足以让我们先看看Sinatra。编辑:感谢Philippe的更正,很高兴听到Camping的开发正在进

  5. ruby-on-rails - Rails 3 Cli 执行命令真的很慢吗? - 2

    有人知道为什么我的rails3.0.7cli这么慢吗?当我运行railss或railsg时,他大约需要5秒才能真正执行命令...有什么建议吗?谢谢 最佳答案 更新:我正在将我的建议从rrails切换到rails-sh,因为前者支持REPL,而rrails不是用例。此外,当与ruby​​环境结合使用时,修补似乎确实可以提高性能变量,现在反射(reflect)在答案中。一个可能的原因可能是这个performancebuginruby每当在ruby​​代码中使用“require”时,它就会调用一些代码(更多详细信息here)。在使用Rai

  6. ruby - =~ 运算符的顺序重要吗? - 2

    下面两个语句除了编码风格有区别吗?/regex/=~"some_string_with_regex""some_string_with_regex"=~/regex/ 最佳答案 是的,有区别。正如在http://www.ruby-doc.org/core/classes/Regexp.html#M001232中提到的If=~isusedwitharegexpliteralwithnamedcaptures,capturedstrings(ornil)isassignedtolocalvariablesnamedbythecaptur

  7. 最近火热的“数字藏品”,你真的了解吗? - 2

    最近火热的“数字藏品”,你真正了解吗?其实有很多人会把数字藏品跟NFT混为一谈,但其实这两者还是有差别的。数字藏品并不等同于NFT数字藏品是什么?直观来看,它可能就是一张数字化照片或视频,甚至就只是一串数字。但它却是一件对应特定作品、艺术品生成的包含着大量数字信息且拥有唯一加密信息的可以买卖交易的收藏品。NFT则是指一种基于以太坊区块链的“非同质化代币”。它在百度百科里的释义是“用于表示数字资产(包括jpg和视频剪辑形式)的唯一加密货币令牌,可以买卖”。比如已被很多人认识的比特币就是NFT的一种。NFT在元宇宙中发挥的作用是巨大的,目前正是它在支撑着元宇宙中的经济体系。数字藏品其实也是NFT的

  8. 【详解】Docker安装Elasticsearch7.16.1集群 - 2

    开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建

  9. ruby-on-rails - Rails 5 - config.assets.compile 应该是真的 - 为什么? - 2

    我正在开发Rails5应用程序并使用Assets管道。它在开发模式下运行良好,但如果我尝试在生产模式下运行它,它无法正确加载图像和样式。我查了一下,发现是因为config.assets.compile=false在config/environments/production.rb中除非我将其设置为真,否则它根本不起作用。我知道实时编译不适合生产,有什么解决方案? 最佳答案 有两个与在Rails服务器中提供Assets相关的选项:Assets编译config.assets.compile=true指Assets编译。也就是说,当Rai

  10. ruby-on-rails - 为什么初始化变量如此重要? - 2

    有人可以向我解释一下,为什么不初始化first_idx和last_idx会导致代码无法运行??当我运行它时,出现此错误“未定义的局部变量或方法last_idx”。我知道建议总是初始化变量,但我不明白为什么。毕竟first_idx和last_idx总是会在循环中得到一个值,因为参数letter总是出现在字符串中(在这个特定问题中)。我真的很感激一些(简单的)见解。谢谢!P.S,我也知道在Ruby中使用#index和#rindex很容易解决这个问题,但我不允许使用直接的方法来解决它。deffind_for_letter(string,letter)first_idx=nil0.upto(s

随机推荐