spark性能优化----缓存清除

spark是一款优秀的框架,计算性能相当优异,已经发展成大数据主流计算引擎,在spark开发过程中有很多优化的点。其中去除重复计算是非常重要的。一般操作调用cache/persist,来缓存中间结果,避免重复计算。其中cache是persist的一个特列(cache相当于persist())。persist拥以下几个级别的缓存:

NONE  默认配置(不缓存)
DISK_ONLY  数据缓存到磁盘,特点读写特别慢,内存占用比较少
DISK_ONLY_2 数据缓存到磁盘两份,特点读写比较慢(比DISK_ONLY读写快,稳定性好)
MEMORY_ONLY 数据缓存到内存和cache()功能之一,读写最快但是内存消耗比较大
MEMORY_ONLY_2 数据缓存到内存,并且缓存两份,特点读写速度快内存消耗很大,稳定性比较好,适用于集群不稳定,缓存的数据计算过程比较复杂的情况
MEMORY_ONLY_SER 数据缓存到内存并序列化,一般可以配合kyro一起使用,读写过程需要序列化和反序列化,读写速度比Memory_only慢,但是数列化后的数据占用内存比较少
MEMORY_ONLY_SER_2 数据序列化后存两份到内存,读写过程同上,特点内存占用量较大,适用于不太稳定的集群
MEMORY_AND_DISK 数据缓存到内存,内存不够溢写到磁盘,一般情况这个使用的比较多一点,是读写性能和数据空间的平衡点
MEMORY_AND_DISK_2 数据缓存两份到内存,内存不够溢写到磁盘,一般情况这个使用的比较多一点,是读写性能和数据空间的平衡点
MEMORY_AND_DISK_SER 数据序列化后缓存到内存,内存不够溢写到磁盘
MEMORY_AND_DISK_SER_2数据序列化后缓存2份到内存,内存不够溢写到磁盘
 
OFF_HEAP 使用堆外内存缓存数据可以配合tachyon一起使用

这些缓存各有特点,视具体情况使用不同级别。
可能有很多初学者都在困惑一个问题,到底什么时候该释放这些内存。比较官方的说法是在action之后释放这些缓存比较科学。但是更加具体一点是在shuffle之后就可以释放掉,或者在数据又一次被序列化以后,上一个cache可以释放掉。这个实验可以在单机版自行测试。

在很多场景下,程序员自己缓存的数据可以通过unpersist手动去除。但是在有些场景可能会忘掉去除缓存,或者引用在shuffle/action之后丢失了,就没法调用unpersist方法。在一些框架内部(比如graphx)为达到优化目的会调用persist却没有释放(因为提前释放cache将无效)。这些情况缓存的数据无法释放,内存空间不足时系统按照最久最近未使用算法去除掉一部分缓存,后续有在用到再重新计算。遇到这种情况性能就会直线下降。

其实spark框架还提供另外一个api供开发者调sc.getPersistentRDDs,这个方法返回所有这在被缓存的RDD数据,开发者可以根据自己需求去除掉不需要的缓存,以下是实现方法:

def unpersistUnuse(rddString: Set[String], sc: SparkContext) = {
  var persistRdds = sc.getPersistentRDDs
  persistRdds.foreach(truple => {
    val xx = truple._2.toString()
    val ddd = rddString
    if (!rddString.contains(truple._2.toString())) {
      truple._2.unpersist()
    }
  })
}

入参rddString是不能清除缓存的RDD.toString之后的字符串集合。调用完之后不需要的缓存就被清除掉。 

posted @ 2019-06-30 11:20  大葱拌豆腐  阅读(4191)  评论(0编辑  收藏  举报