通常我看看到的表象是类似于 shuffle fetch fail ..caused by 某个host lost connection 这就是内存溢出挂掉了。为什么会出现这种情况呢。
1. 首先对于缓存非序列话数据的集合都实现了SizeTracker接口类,该接口有估计集合大小的方法,而SizeTracker接口类实际使用的是采样估计,在两次较为准确的采样估计之间,集合的大小是通过平均数计算的方法得到的大小,就容易导致如果在前几次更新的数据较小导致平均数较小,而现在数据较大,计算得到的大小远小于实际大小
2.对于集合的实际大小计算这里选择SizeEstimator进行计算,而SizeEstimator进行计算的方法是通过不断寻找集合引用的其他对象,计算每一个对象的大小,这样就会造成某些已经没有引用关联的类不能参与计算,而且这些类此时也还没有被垃圾回收器进行回收,就会导致计算得到的大小实际小于此时集合已经使用的大小
3.而spark的内存模型是逻辑上的内存模型,并不是物理上的,当调用集合的estimateSize计算其大小小于实际使用大小的情况下,spark内存模型就会过低的估计当前集合所占用的内存,虽然在内存模型看来当前内存并没有超过限制,但是实际上使用的内存可能已经超过了最大内存限制,所以会被yarn干掉