(转)TaskTracker由于运行过多task导致内存不足而挂掉的处理办法

link:http://blog.csdn.net/ae86_fc/article/details/5284252

最近集群里出现了这样的情况:

  • tasktracker机器,由于运行 了过多的task (map/reduce),导致该机器上的内存 严重 overload,产生大量swap,最终导致任何命令 都无法得到相应,机器挂掉。连ssh都无法得到相应,只能通知机房的同事重启机器。

究其原因,其实很简单:

  • 就是因为集群中机器配置的可并行的map和reduce数加起来,超过了机器的cpu数,导致在极限的情况下,会有 6个map,6个reduce的task java 进程运行在这台slave上
  • 有些job作业,对内存资源的占用本来就很大,有的reduce甚至一个就可能要占据2G或以上的内存。

所以,在极限的情况下,TT机器确实由于不堪重负而挂掉了。
避免这样的情况的方法其实也很简单:以前hadoop中没有提供对TT上的任务进行内存管理 的方式,于是这时候采用的办法 就是,自己写监控程序,运行在各个slave机器上,对tasktracker的所有子孙进程进行监控,一旦某个 task的内存占用超过了某个阈值,就kill掉该task;或所有的TT子孙进程(包括java的和非Java的)占用内存的和超过某个阈值,就 kill掉占用内存最大的task,或者progress最少的task(progress最少这一点其实在hadoop的外围程序无法做到,因为没有 job的内部counter)。
后来惊喜的发现,hadoop中不知道从什么版本开始,就已经提供了类似的内部管理的组件:TaskMemoryManagerThread,它能够提供以上描述的所有功能,并且支持hadoop级别的配置选项来定义各种阈值和条件。
配置笔记 如下:

TT是可以用配置来监控在它之上运行的task的内存使用情况的,所以,一些写的很不好的程序,对内存的占用十分不合理,常常将TT机器搞挂的现象,就可以通过这个机制来避免。有了这个,任何一个task的运行,都会受到了task-limit for virtual memoey(task占用的虚拟内存)的限制,不仅如此,每一个TT节点也可以控制运行在其上的所有task占用的VMEM总和的限制。在这种机制下,TT会保证,当某个task,或者该task的子进程,一旦使用VMEM超过一个per-task limit,就会kill该task。并且还会保证,当该TT上所有的task及其子孙进程占用VMEM的总和超过一个node-limit时,kill 掉一些危险的task及其子孙进程,保证TT正常服务

用户可以对每个计算节点设置 这个VMEM task-limit per job选项,如果没有提供该limit,hadoop将会使用一个默认的值。而且还可以对每个TT节点上的所有task的node-limit进行设置。

要打开task memory的监控组件,可以使用如下配置:

选项名 类型 描述
mapred.tasktracker.vmem.reserved long 该选项用来指定,每一个TT节点上,需要保留多少的VMEM内存,以保证该TT节点正常可用。通常情况下,total VMEM - 该配置值,这个结果,就是该TT的node-limit VMEM。所有task及其子孙进程的VMEM使用量的总和,不能超过这个结果。该配置选项的单位为bytes。
mapred.task.default.maxvmem long 该选项用来指定对于task而言,默认最大占用的VMEM是多少,单位bytes。
mapred.task.limit.maxvmem long 该选项用来指定task的最大VMEM占用值,单位同样为bytes。


另外,如下配置选项也可以被设置:

mapred.tasktracker.taskmemorymanager.monitoring-interval
该选项用来指定每过多长时间,TT会check一遍它上面的task内存使用情况,并根据情况进行相应的处理。单位为毫秒。

TT 的TaskMemoryManager的运行机制如下:

  1. 如果这些配置选项中出现一个配置为-1的,那么该功能就会在TT上被 disable。
  2. 如果mapred.task.default.maxvmem的值大于 mapred.task.limit.maxvmem的值,那么该功能也会在TT上被disable。
  3. 如果TT接到一个task,该 task的运行选项中配置的内存使用超出了mapred.task.limit.maxvmem的值,TT会在log中记录一个警告,但是该task仍然会被运行
  4. TT会周期性的检查如下情况:
  • 如果某个task当前使用的VMEM超出了task- limit ,那么TT就会kill掉该task,并在log中记录原因。该task在job的调度中将被认为是fail,并记录到fail counter中去。
  • 如果TT上的所有task及其子孙进程的VMEM使用量超过了node-limit ,那么TT将会选择progress最小的几个task来kill,直到VMEM的使用下降到node-limit以下。这些被kill的task并不会认为是fail的,也不会记录到fail counter中去。

调度系统 还可以通过阻止太多的task在TT上运行,或者仅仅在TT有足够的VMEM的时候才分配task给该TT的方式来缓解TaskMemoryManager所带来的消耗。另外,调度器也可以考虑TT上的物理内存的情况。如要enable这个功能,TT及要定时的想JT 发送heartbeat,并在heartbeat中带上其物理内存的使用信息。如以下配置:
mapred.tasktracker.pmem.reserved
用来设置每台TT上保留的物理内存空间 ,单位为bytes,这个limit被 scheduler用来调度task,只有当TT上有足够的内存,才分配task给该TT。

TT在每个heartbeat中会发送以下信息给JT:

  • 该节点上的total VMEM
  • mapred.tasktracker.vmem.reserved 的值,如果设置了的话
  • 该节点上的total RAM
  • mapred.tasktracker.pmem.reserved 的值,如果设置了的话
原文地址:https://www.cnblogs.com/tangtianfly/p/2630719.html