Metrics测量指标
1. Used Resources
Job使用资源的数量,单位是:GB Hours
计算方式
我们将任务的资源使用定义为:所有mapper任务和所有reducer任务的资源使用的总和。
例如:
有如下的job:
4 mappers with runtime {12, 15, 20, 30} mins.
4 reducers with runtime {10 , 12, 15, 18} mins.
向yarn申请的容器大小为:4 GB
那么,
所有mapper使用的资源: 4 * (( 12 + 15 + 20 + 30 ) / 60 ) GB Hours = 5.133 GB Hours
所有reducer使用的资源: 4 * (( 10 + 12 + 15 + 18 ) / 60 ) GB Hours = 3.666 GB Hours
Job使用的总资源= 5.133 + 3.6666 = 8.799 GB Hours
2.Wasted Resources
资源浪费就是指资源浪费的数量,我们通过GB
hours或者百分比方式展示job浪费资源的数量。
计算方式
为了计算资源的浪费情况,我们需要先计算下面的指标:
1)Map和reduce任务中浪费的最小的内存大小
2)Map和reduce任务的运行时间
任务浪费的最小的内存大小= 申请的yarn容器的大小- 所有的任务中最大使用的内存大小
任务浪费的资源= 任务浪费的最小内存大小* 任务运行的时间,
job总的资源浪费 = 所有的任务浪费的资源总和
对于每一个任务我们定义如下:
peak_memory_used := task使用的内存上界
runtime := task运行时长
通过所有task中的最大使用的物理内存(max_physical_memory)和虚拟内存(virtual_memory)可以计算出任意task的peak_memory_used,又由于每个任务的上界通过max_physical_memory来确定,因此我们可以说每个任务的peak_memory_used可以通过下面的公式计算出来:
peak_memory_used = Max(max_physical_memory, virtual_memory/2.1)
其中2.1是集群的内存因子(该参数yarn.nodemanager.vmem-pmem-ratio对应的值)
每个task的最小内存浪费可以通过下面的公式计算:
wasted_memory = container_size - peak_memory_used
每个任务的最小资源浪费可以通过下面的公式计算:
wasted_resource = wasted_memory * runtime
总的资源的浪费情况就等于所有任务的wasted_resource的总和
3.Runtime
运行时间指标展示作业总的运行时间。
计算方式
Job的运行时间是通过job的完成时间减去job提交到yarn的资源管理器的时间计算出来的。
例如:
Job的开始时间是:1461837302868 ms
Job的完成时间是:1461840952182 ms
Job的运行时间是:1461840952182 - 1461837302868= 3649314 ms or 1.01 hours
4.Wait time
Job的等待时间是指job运行中花费在等待状态总的时间。
计算方式
对于每一个job我们定义如下的名词:
ideal_start_time := 所有任务都应该完成启动的理想的时间
finish_time := 任务完成时间
task_runtime := 任务运行时间
- Map tasks
对于map任务,我们定义如下:
ideal_start_time := job的开始时间
我们找出所有map任务中最长运行时间(task_runtime_max)和最后的完成时间( finish_time_last ),那么job中mapper的总的等待时间就可以通过如下的公式计算出来:
mapper_wait_time = finish_time_last - (ideal_start_time + task_runtime_max)
- Reduce tasks
对于reducer任务,我们定义如下:
ideal_start_time := 通过获取的reducer慢开始的百分比(mapreduce.job.reduce.slowstart.completedmaps:这个参数的含义是,当Map Task完成的比例达到该值后才会为Reduce Task申请资源,默认是0.05)并找到map任务完成之后最先开始的那个reducer,就可以计算出该参数
我们找到reducer任务最大运行时间( task_runtime_max)和最后完成的时间( finish_time_last )
那么job的reducer任务的总等待时间就可以使用如下公式计算出来:
reducer_wait_time =finish_time_last - (ideal_start_time + task_runtime_max)
total_wait_time = mapper_wait_time + reducer_wait_time
例如:
如上图:
对于map任务:
ideal_start_time = t1
task_runtime_max = Map_1对应的运行时间
finish_time_last = t4
mapper_wait_time = t4 – Map_1对应的运行时间– t1
对于reduce任务:
ideal_start_time = t2
task_runtime_max = Reduce_3对应的运行时间
finish_time_last = t6
reducer_wait_time = t6 -
Reduce_3对应的运行时间- t2
总的等待时间:
total_wait_time =mapper_wait_time + reducer_wait_time
MapReduce算法分析
1.Mapper数据倾斜
数据进入到Mapper作业中后,有可能会发生数据的倾斜,这种数据倾斜主要是考虑到HDFS文件大小差别太大导致的。
1)判断依据
根据每个map task运行的时间和数据量两个指标进行判定。
2)原理
Mapper数据倾斜启发式算法(mapper
data skew heuristic)会将所有的Mapper分成两部分,其中一部分的所有作业(task)的平均数据量会大于另一部分的平均数据量,之后根据这两个组的平均数据量的差值的绝对值/这两组数据中平均数据量的最小值来判断数据倾斜程度。时间方面的倾斜程度算法一样。
此图中的A和B两组的平均数据量和平均运行时间都差不多,没有发生数据倾斜
此图中A和B两组的平均运行时间差不多,但是平均数据量差别很大,最终导致严重程度为Critical,这说明该作业读取的hdfs中的数据文件大小差别太大,1)可能是有很多小文件, 2)也可能是文件大小超过block大小的10%以上一点,导致超出的部分又占用了一个block
3)计算步骤
(1)递归的计算作业输入数据量的平均值,然后根据作业的输入量平均值将所有的作业分成两组Group_A 和Group_B。
(2)计算各组的平均值,并求出数据量小的组的平均值(minAvg)和两组平均值之差的绝对值(diffAvgAbs)
(3)求出误差( diffAvgAbs/ minAvg ),根据误差和给定的误差级别(比如:{2, 4, 8, 16})计算严重程度severity
(4)计算出数据量小的那组的的task数量,并根据配置的task数量级别(比如:{10, 50, 100, 200})计算出task数量的严重程度taskSeverity
(5)取数据量大的那组的平均数据量,并根据配置的文件大小级别(比如:{1d / 8, 1d / 4, 1d / 2, 1d}其中的每个值需要乘以block的大小)计算出task数据量的严重程度fileSeverity
(6)求出上面计算出来的严重程度的最小值作为map 数据倾斜程度的结果。
2.Mapper GC
Mapper GC会分析任务的GC效率。它会计算出所有mapper的平均GC时间占平均CPU时间的比例。避免打扰用户,该算法在代码中设置了很宽松的范围(观察线上跑的结果发现确实没有GC报警的情况),但是如果分析的结果仍然报警的话,说明你的代码确实需要优化了。
1)判断依据
平均GC时间占平均CPU时间的比例,比例越高,严重程度越大,通常来说代码需要优化。
2)原理
计算出所有作业的平均的CPU使用时间、平均运行时间以及平均GC的时间。我们要计算Mapper GC严重度的最小值,这个值可以通过平均运行时间和平均垃圾回收时间占平均CPU总消耗时间的比例来计算。
3)计算步骤
(1)计算出平均CPU使用时间(avgCPU)、平均运行时间(avgRuntime)、平均GC时间(avgGC)。
(2)计算出平均GC时间占平均CPU时间的比例(gcRatio)
(3)使用gcRatio和误差级别(比如:{0.01d, 0.02d, 0.03d, 0.04d})计算严重程度gcSeverity
(4)使用平均运行时间和运行时间的级别(比如:{5, 10, 12, 15} 单位:分钟数)计算运行时间的严重程度runtimeSeverity
(5)取上面两个严重程度的最小值作为gc的严重程度。
3.Mapper的内存消耗
分析每个Mapper实际内存的消耗,并检查作业消耗的内存比例以及向yarn申请的容器的总内存,该指标用于分析用户申请的容器内存是否合理,比如:你申请了10G的yarn容器的内存,但是实际消耗内存却只有1G,说明你的任务浪费了很多内存资源,此时就会显示严重级别为critical,说明你需要减少每个mapper向yarn容器申请的内存资源的大小。
1)判断依据
task任务平均使用内存占向yarn容器所申请的内存的比例。比例越低说明内存资源浪费程度越高,需要优化,反之则说明资源利用率越高越好。
2)原理
计算平均内存消耗占用向yarn资源容器申请的内存大小比率,使用该比率结合设置的内存利用率级别判断mapper对内存的消耗是否合理。
此图对内存的消耗就不合理,因为申请的内存高达24G,但是实际使用的内存最大却只有6G左右,平均内存使用才3.7G左右,严重浪费内存资源。
3)计算步骤
(1)计算所有task的平均物理内存消耗(avgPhysicalMemory)、平均虚拟内存消耗(avgVirtualMemory)、平均运行时间(avgRuntime),并从该应用的配置文件中获取向yarn容器申请的内存大小(containerMemory)
(2)计算平均物理内存消耗(avgPhysicalMemory)和向yarn容器申请的内存大小(containerMemory)的比值(ratio)。
(3)使用上面的比值(ratio)结合内存利用率级别(比如:{0.6d, 0.5d, 0.4d, 0.3d}),计算出严重程度severity。
(4)再使用向yarn容器申请的内存大小(containerMemory)与容器级别(比如:{1.1d,
1.5d, 2.0d, 2.5d} 中的每一个值需要乘以yarn的配置文件中配置的默认的容器大小)计算出申请的容器的严重程度containerSeverity
(5)计算出上面两个严重级别的最小值作为内存消耗的严重级别
4.Mapper的运行速度
分析Mapper代码的运行效率。通过这些分析可以知道mapper属于CPU消耗型的,或者是mapper处理的数据量过大。通过这个能够分析出mapper运行速度快慢和处理的数据量大小之间的关系。
1)判断依据
所有task的运行速度的中值作为判断mapper运行速度的依据,而运行速度是通过每个task的输入数据/运行时长得到的。
2)原理
通过计算每个task的运行速度的中值,结合配置的磁盘的读取速度,判断出mapper任务的执行速度,但是需要排除运行时间过短导致的错误的结果。
此任务运行速度就太慢了,也可以推断出该任务是CPU消耗型任务。
3)计算步骤
(1)计算出运行速度的中值(medianSpeed)、运行时间的中值(medianRuntime)、输入数据量的中值(medianDataSize)
(2)使用运行速度中值(medianSpeed)结合运行速度的级别(比如:{1d / 2, 1d / 4, 1d / 8, 1d / 32} 每个值需要乘以磁盘的读取速度,默认100M/s)计算出严重级别speedSeverity。
(3)再使用运行时间的中值(medianRuntime)结合运行时间级别(比如:{5, 10, 15, 30})计算出运行时间的严重程度runtimeSeverity
(4)取speedSeverity和runtimeSeverity两个严重级别的较小者作为运行速度的严重级别。
5.Mapper溢出
该算法从磁盘IO的角度去评测mapper的性能。mapper溢出比例(溢出的记录数/总输出的记录数)是衡量mapper性能的一个重要指标:如果这个值接近2,表示几乎每个记录都溢出了,并临时写到磁盘两次(其中一次发生在内存排序缓存溢出时,另一次发生在归并排序所有溢出的切换时)。当这些发生时表明mapper输入输出的数据量过大了。
1)判断依据
总的溢出记录数和总的输出记录数的比值。
2)原理
计算出所有task的溢出记录数和所有task的输出记录数的比值,使用该比值进行mapper溢出严重程度的判断,该比值越大说明输入输出的数据量过大,需要进行优化以提高运行速度。
3)计算步骤
(1)计算出所有task的总的溢出记录数(totalSpillRecords)、总的输出记录数(totalOutputRecords),并计算出其比值(ratioSpill)
(2)使用上面计算的比值结合配置的溢出级别(比如:{2.01d, 2.2d, 2.5d, 3.0d})计算出溢出的严重程度spillSeverity。
(3)根据task的数量计算出任务数的严重程度taskNumberSeverity
(4)取上面两个小的严重程度作为溢出严重程度。
6.Mapper运行时间
这部分分析mappers的数量是否合适。通过分析结果,我们可以更好的优化任务中mapper的数量这个参数的设置。有以下两种情况发生时,这个参数的优化就显得很迫切了:
1)Mapper的运行时间很短,可能的原因如下:
mapper的数量过多
mapper的平均运行时间很短
文件尺寸太小
2)Mapper的运行时间很长,可能的原因包括:
mapper的数量很少
mapper的平均运行时间很长
文件的大小过大(个别文件是GB级别)
1)判断依据
根据所有task运行的平均时长进行严重程度的判断
2)原理
首先计算出所有task的平均运行时间,之后根据该平均运行时间计算出最短和最长的任务运行时长严重级别,取两个严重级别中较大的作为运行时长的严重级别。
3)计算步骤
(1)计算出所有task的平均输入大小(avgInputSize)、平均运行时长(avgRuntime)(2)根据平均运行时长(avgRuntime)结合短运行时长级别(比如:{10, 4, 2, 1} 其中的每个值代表的是分钟数)计算出短运行时长的严重级别shortSeverity
(3)根据任务数结合任务数的级别(比如:{50, 101, 500, 1000})计算出任务数的严重程度taskNumberSeverity
(4)取上面shortSeverity和taskNumberSeverity的较小值作为短运行时长的严重级别realShortSeverity
(5)根据平均运行时长(avgRuntime)结合长运行时长级别(比如:{15, 30, 60, 120} 其中的每个值代表的是分钟数)计算出长运行时长的严重级别longSeverity
(6)取realShortSeverity和longSeverity总的较大则作为运行时长的严重级别
7.Reducer数据倾斜
分析进入到每个Reduce中的数据是否有倾斜。该分析能够发现Reducer中是否存在这种情况,将Reduce分为两部分,其中一部分的输入数据量明显大于另一部分的输入数据量。
1)判断依据
根据每个reduce task运行的时间和数据量两个指标进行判定。
2)原理
Mapper数据倾斜启发式算法(reducer
data skew heuristic)会将所有的Reducer分成两部分,其中一部分的所有作业(task)的平均数据量会大于另一部分的平均数据量,之后根据这两个组的平均数据量的差值/这两组数据中平均数据量的最小值来判断数据倾斜程度。时间方面的倾斜程度算法一样。
3)计算步骤
(1)递归的计算作业输入数据量的平均值,然后根据作业的输入量平均值将所有的作业分成两组Group_A 和Group_B。
(2)计算各组的平均值,并求出数据量小的组的平均值(minAvg)和两组平均值之差的绝对值(diffAvgAbs)
(3)求出误差( diffAvgAbs/ minAvg ),根据误差和给定的误差级别(比如:{2, 4, 8, 16})计算严重程度severity
(4)计算出数据量小的那组的的task数量,并根据配置的task数量级别(比如:{10, 50, 100, 200})计算出task数量的严重程度taskSeverity
(5)取数据量大的那组的平均数据量,并根据配置的文件大小级别(比如:{1d / 8, 1d / 4, 1d / 2, 1d}其中的每个值需要乘以block的大小)计算出task数据量的严重程度fileSeverity
(6)求出上面计算出来的严重程度的最小值作为map 数据倾斜程度的结果。
8.Reducer GC
Reduce GC用于分析任务的GC效率,能够计算并告诉我们GC时间占所用CPU时间的比例。该算法在代码中设置了很宽松的范围,避免打扰用户,但是如果分析的结果任然报警的话,说明你的代码确实需要优化了。
1)判断依据
平均GC时间占平均CPU时间的比例,比例越高,严重程度越大,通常来说代码需要优化。
2)原理
首先,会计算出所有任务的平均CPU消耗时间、平均运行时间以及平均垃圾回收所消耗的时间。然后,算法会根据平均运行时间以及垃圾回收时间占平均CPU时间的比值来计算出最低的严重度。
3)计算步骤
(1)计算出平均CPU使用时间(avgCPU)、平均运行时间(avgRuntime)、平均GC时间(avgGC)。
(2)计算出平均GC时间占平均CPU时间的比例(gcRatio)
(3)使用gcRatio和误差级别(比如:{0.01d, 0.02d, 0.03d, 0.04d})计算严重程度gcSeverity
(4)使用平均运行时间和运行时间的级别(比如:{5, 10, 12, 15} 单位:分钟数)计算运行时间的严重程度runtimeSeverity
(5)取上面两个严重程度的最小值作为gc的严重程度。
9.Reducer内存消耗
分析每个Reducer实际内存的消耗,并检查作业消耗的内存比例以及向yarn申请的容器的总内存,该指标用于分析用户申请的容器内存是否合理,比如:你申请了10G的yarn容器的内存,但是实际消耗内存却只有1G,说明你的任务浪费了很多内存资源,此时就会显示严重级别为critical,说明你需要减少每个Reducer向yarn容器申请的内存资源的大小。
1)判断依据
task任务平均使用内存占向yarn容器所申请的内存的比例。比例越低说明内存资源浪费程度越高,需要优化,反之则说明资源利用率越高越好。
2)原理
计算平均内存消耗占用向yarn资源容器申请的内存大小比率,使用该比率结合设置的内存利用率级别判断reducer对内存的消耗是否合理。
此图对内存的消耗就不合理,因为申请的内存高达24G,但是实际使用的内存最大却只有6G左右,平均内存使用才3.7G左右,严重浪费内存资源。
3)计算步骤
(1)计算所有task的平均物理内存消耗(avgPhysicalMemory)、平均虚拟内存消耗(avgVirtualMemory)、平均运行时间(avgRuntime),并从该应用的配置文件中获取向yarn容器申请的内存大小(containerMemory)。
(2)计算平均物理内存消耗(avgPhysicalMemory)和向yarn容器申请的内存大小(containerMemory)的比值(ratio)。
(3)使用上面的比值(ratio)结合内存利用率级别(比如:{0.6d, 0.5d, 0.4d, 0.3d}),计算出严重程度severity。
(4)再使用向yarn容器申请的内存大小(containerMemory)与容器级别(比如:{1.1d,
1.5d, 2.0d, 2.5d} 中的每一个值需要乘以yarn的配置文件中配置的默认的容器大小)计算出申请的容器的严重程度containerSeverity 。
(5)计算出上面两个严重级别的最小值作为内存消耗的严重级别。
10.Reducer时间
这部分分析Reducer的执行效率,可以帮助我们更好的配置任务中reducer的数量;当出现以下两种情况时,说明Reducer的数量需要进行调优:
1)Reducer过多,hadoop任务可能的表现是:
Reducer数量过多
Reducer的运行时间很短
2)Reducer过少,hadoop任务可能的表现是:
Reducer数量过少
Reducer运行时间很长
1)判断依据
根据所有task运行的平均时长进行严重程度的判断
2)原理
首先计算出所有task的平均运行时间,之后根据该平均运行时间计算出最短和最长的任务运行时长严重级别,取两个严重级别中较大的作为运行时长的严重级别。
任务数多,运行时长过短,属于严重级别的
运行时长计算:属于严重级别的
任务数方面计算:属于None级别的
取上面两个级别的较小者None级别作为最终的严重级别。
3)计算步骤
(1)计算出所有task的最大运行时长(minRuntime)、最小运行时长(maxRuntime)、平均运行时长(avgRuntime)(2)根据平均运行时长(avgRuntime)结合短运行时长级别(比如:{10, 4, 2, 1} 单位:分钟)计算出短运行时长的严重级别shortSeverity
(3)根据任务数结合任务数的级别(比如:{50, 101, 500, 1000})计算出任务数的严重程度taskNumberSeverity
(4)取上面shortSeverity和taskNumberSeverity的较小值作为短运行时长的严重级别realShortSeverity
(5)根据平均运行时长(avgRuntime)结合长运行时长级别(比如:{15, 30, 60, 120}单位:分钟数)计算出长运行时长的严重级别longSeverity
(6)取realShortSeverity和longSeverity总的较大则作为运行时长的严重级别
11.洗牌和排序
分析reducer消耗的总时间以及reducer在进行洗牌和排序时消耗的时间,通过这些分析,可以判断reducer的执行效率。
1)判断依据
所有task的平均shuffle时长和平均sort时长进行判断的,取两者中较大的作为洗牌和排序的严重级别
2)原理
首先计算出所有的task的平均shuffle时长和平均sort时长,之后再分别与平均执行时长(totalTime - shuffleTime - sortTime)进行相除,计算出shuffle和sort的严重级别,取两者中较大的作为洗牌和排序的严重级别。
其中后面的X代表倍数的意思,计算方式是:avgShuffleTime / avgCodeTime 和avgSortTime /
avgCodeTime。
此图显示shuffle的时间很长,但是sort的时间很短,说明你需要调整slowstart参数"mapreduce.job.reduce.slowstart.completedmaps"从0.90 调大一些,要小于1.0。但是需要注意的是,调整此参数可以降低shuffle的时间,但是可能会增加整个job的运行时间。
3)计算步骤
(1)计算出所有task的平均执行时长(avgExecuteTime)、平均shuffle时长(avgShuffleTime)、平均sort时长(avgSortTime)
(2)将平均shuffle时长结合运行时长的级别(比如:{1, 5, 10, 30} 单位:分钟数)计算出shuffle的严重级别shuffleSeverity
(3)计算shuffleRatio = avgShuffleTime* 2 / avgExecuteTime,之后使用shuffleRatio结合运行比率级别(比如:{1, 2, 4, 8})计算出shuffle运行比率级别shuffleRatioSeverity
(4)取shuffleSeverity 和shuffleRatioSeverity的较小者作为真正的shuffle严重级别realShuffleSeverity
(5)将平均sort时长(avgSortTime)结合运行时长的级别(比如:{1, 5, 10, 30}单位:分钟数)计算出sort的严重级别sortSeverity
(6)计算sortRatio = avgSortTime * 2 /avgExecuteTime,之后使用sortRatio结合运行比率级别(比如:{1, 2, 4, 8})计算出sort运行比率级别sortRatioSeverity
(7)取sortSeverity和sortRatioSeverity的最小值作为真正的shuffle严重级别realSortSeverity
(8)取realShuffleSeverity和realSortSeverity中较大者作为洗牌和排序的严重级别
参考文献:
1. CSDN一位大牛写的文章:
https://zhuanlan.zhihu.com/p/20855271?refer=dr-elephant
2. Dr-elephant官方文档:
https://github.com/linkedin/dr-elephant/wiki/Metrics-and-Heuristics
网友评论