一个大型mapreduce作业(连接14个输入目录,总计约14 TB的输入)失败。我们不仅不能执行我们的任务。当我们刚刚做map is cat/reduce is cat时,我们甚至不能完成这个。复制数据似乎停滞不前。
我们猜测hadoop正在饱和aws提供的emr容量。不确定是网络饱和,还是磁盘空间饱和,还是什么。我们会遇到这样的错误
“减少>复制(438094的436333,速度为0.10 mb/s)”
在hadoop控制面板上。它只是挂在那里,从来没有完成的副本。另一种理论是hadoop的离线排序和复制是同时发生的,不知何故这是一个瓶颈。我们尝试了各种各样的排列,包括更多的减缩器、更多的节点、不同大小的辅助框,但不知何故,我们还没有找到一个有效的组合。
由于我们迫切需要完成这项工作,我们正在做一个变通办法,就是将数据划分成更小的作业。也就是说,每14年的投入将被分割,然后我们将加入分区。
有没有人有过使用aws托管的hadoop处理如此大小或更大的作业的经验,如果有,你能给出一些建议让cat-map/cat-reduce获得成功吗?比如节点数量、节点大小和配置选项?
否则我想我们只是触及了电子病历的局限性。
2条答案
按热度按时间8i9zcol21#
我看不到集群中的reducer数量和插槽/主机总数,但看起来像是您的reducer dos mapper主机。为了解决这个问题,你可以做几件事:
增加块大小。这使得使用较少的Map数量和每个Map将做更多的工作。这里将是较少的部分,由减速器下载。
如果集群相对较大(100+),请检查http处理程序的数量(mapreduce.tasktracker.http.threads)
减速器的数量应在集群容量(减速器槽)的0.7-1.2之间。
希望这有帮助。
bz4sfanl2#
克里斯·史密斯回答了这个问题,说我可以把它贴到网上。他的回答是:
因此,输入数据的大小本身并不是emr的限制。还有很多其他因素。
也就是说,吸入10tb的数据是一项令人头痛的任务。仅仅是读取那么多数据是相当残酷的,然后你就有了排序。
第一个问题是:制约因素是什么?你看到网络带宽被耗尽了吗?你看到cpu耗尽了吗?磁盘i/o或iops?这些在数据节点上是什么样子的?jobtracker&namenodes呢(在集群其他部分正常的情况下最大化这些节点并不罕见)?如果以上都没有,那么可能有一个hadoop资源已经耗尽,需要进行不同的配置。
因为你没有提到争论的任何特定方面,超过了哪个阶段,这让我怀疑你没有太多关于下面发生的事情的标准。通常,在调整好一个大任务之前,需要多次迭代“测量,然后调整”。
作为一般的经验法则,长时间处于“减少/复制”阶段是“你做错了”的有力指标。通常问题是,在排序/溢出/合并过程中,节点以某种方式使磁盘io达到最大值。hadoop有许多调优参数,对于有大量Map器和还原器的作业来说,这些参数开始变得古怪,特别是当两者之间存在很大的不平衡时。同样,karmasphere和类似的工具在这里可以帮助你很多。需要调整的典型情况(我可能有一些名称错误):
登录中。尤其是像dfs.namenode.logging.level这样的东西,在作业之前进行调整非常重要。用冗长的日志记录自杀是完全可能的。虽然矛盾,但它也可以拯救你,所以。。。
Map输出大小通常是“减少/复制”问题的关键因素。如果可能的话,想办法减小Map输出的大小。它确实应该比Map输入的大小小得多。去掉reduce阶段不需要的所有数据。考虑使用紧凑的二进制序列化格式(java序列化会降低性能),如协议缓冲区或节俭(整数数据的大赢家)。考虑您的字符串在多大程度上可以用id/enum表示。你能用组合器来减少通过线路发送的数据量吗?如果你有多余的cpu,可以使用压缩(从lzo或snappy开始,但是如果你还有更多的cpu要消耗,可以考虑gzip或者更强大的东西)。如果在Map任务日志中仍然看到合并步骤花费了很长时间,则需要进行一些调整:
io.sort.factor:可能应该更高。你甚至可能因为太多的Map绘制者而痛苦,这取决于你在做什么。io.sort.mb:与io.sort.factor密切相关,但不同。如果您开始看到节点上有大量磁盘i/o压力,我会启动它。这会占用内存,因此在这个参数中涉及到一个真正的权衡。
mapred.job.reuse.jvm.num.tasks:只有当您的任务变得非常小的时候,但是如果它们变小了,这就值得提高mapred.reduce.parallel.copies:如果您没有cpu限制,那么您可能需要提高这个数字。你可能最终需要调整其他数字来平衡。
io.sort.record.percent:由于作业大小的原因,这个是最不可能完全偏离标准的。通常如果这是错误的,那是因为你有非常大或非常小的记录。你想要达到的黄金比率是“16/(16+每条记录的字节数)”。
很难强调早期溢出对节点性能的影响有多严重。如果溢出,则意味着数据将被写出,然后再次读取,然后再次写出。在每个节点上。因此,如果你弄错了,添加更多的节点是没有帮助的(实际上会让事情变得更糟)。您需要查看一个作业溢出了多少记录,以及输出了多少map记录。理想情况下,这些数字是相同的。现在,如果必须溢出,就必须溢出(尽管这通常表明您做错了什么),但是每个记录只溢出到磁盘一次的作业只会压垮其他作业。
减速器侧可能存在类似问题。查看合并阶段的计数器。理想情况下,您希望溢出的记录为0或至少<=输入记录数。如果更高。。。这就是为什么你有一个性能问题(说真的,这可能是绝对残酷的)。注意各种设置:mapred.job.shuffle.input.buffer.percent、mapred.job.shuffle.merge.percent、mapred.inmem.merge.threshold、io.sort.factor。对于大的工作来说,通常会得到支持的是mapred.inmem.merge.threshold。前两项也经常搞砸,但这更多地是工作性质的函数,而不是工作规模的函数。
count:如果您在hdfs中生成大量的小文件,那么您肯定希望将其推高
dfs.mapred.job.tracker.handler.count:看看你有多少任务要做,如果这个值应该更高。如果您要创建数千个在数百个节点上运行的小任务,那么您不会满足于10个
dfs.datanode.handler.count:这个与parallel.copies标志一起使用。这一次总是给我带来麻烦,因为我的第一React是把它拉得很高,然后我就在其他地方造成了木塞不管怎样,如果你考虑你有多少个Map器和多少个还原器,这可能是有意义的,提高这一点。
tasktracker.http.threads:如果您陷入reduce copy,那么这个问题就不太可能出现。反正离它应该在的地方更近了。mapred.local.dir:这是一个我经常不得不在非emr集群上对具有大量map输出的作业进行调整的集群。你真的可以成为磁盘绑定和磁盘空间绑定,所以我发现它有助于改变路径为逗号分隔的目录列表,每个驱动器一个。当然,使用emr是没有意义的,但是它指出了如何快速耗尽磁盘空间。
mapred.local.dir.minspacestart:您可能没有意识到,但是您的Map输出空间可能已经用完了。调整此值以确保在开始作业之前每个任务在系统上都有足够的剩余空间,这样可以真正节省时间。
请记住,hadoop实际上是为每个主轴有2个内核的系统而设计的(这是摩尔定律之前的几次迭代),所有的输入和输出都在hdfs中(允许大量的输入和输出捷径),每8个内核有1GGE端口,交换结构中几乎没有瓶颈。电子病历没有给你这样的东西。亚马逊试图给出一些合理的默认值来进行调整,但很难普遍地为每个人解决这个问题。emr的一个优点是,每个节点往往有大量的ram,因此您应该花一些时间确保以最佳方式使用ram,以最小化磁盘i/o。hadoop也确实适用于Map程序消耗大量原始数据,但吐出的数据相对较少的工作。对每个作业中生成的所有数据都进行了大规模的分布式排序,默认情况下,hadoop会尝试这样做,同时为您的任务保留大量的ram和磁盘空间。让您的数据已经被压缩/分类,可以将大量的工作从reducer中推到mapper中,从而避免大量的开销。很可能,这就是你的问题所在。