spark从入门到放弃六: RDD 持久化原理

文章地址:http://www.haha174.top/article/details/252484
spark 中一个非常重要的功能特性就是可以将RDD 持久化到内存中。当对RDD进行持久化操作时,每个节点都会将自己操作的RDD的partition持久化到内存中,并且之后对该RDD的反复使用直接使用内存缓存的partion.这样的话针对一个RDD反复执行多个操作的场景就只要对RDD计算一次即可。后面直接使用改RDD,而不是需要反复多次计算该RDD。
巧妙的使用RDD的持久化甚至在某些场景下。可以将spark应用程序的性能提升10倍。对于迭代式算法和快速交互式应用来说RDD持久话是非常重要的。
要持久化一个RDD。只要调用其cache()方法或者persist方法即可。在该RDD第一次被计算出来时,就会直接缓存在每一个节点。而且spark持久化机制还是自动容错的。如果持久化的RDD的任何partion丢失了,那么soark会自动通过其源RDD使用transformation 操作重新计算该partion。
那么cache方法和persist方法有什么区别呢区别在于 cache 是 persist 方法的一种简化方式。cache()的底层就是调用persist的无参版本。同时调用persist(MEMORY_ONLY),将数据持久化到内存中。如果需要从内存中清除缓存那么可以使用unpersist()方法。
spark自己也会在shuffle 操作时,进行数据持久化。比如写入磁盘,主要是为了在节点失败时,避免需要重新计算整个过程。
假设我们不适用RDD持久话会出现什么呢

《spark从入门到放弃六: RDD 持久化原理》 这里写图片描述

由图可知 假设我们需要做两次count 但是没有做持久化的话 需要从hdfs 读取两次如果数据量比较大的话会非常影响性能。

持久化如下:

《spark从入门到放弃六: RDD 持久化原理》 这里写图片描述

cache 和persisit 使用 是有规则的
必须在创建一个RDD 之后执行
另起一行单独执行这个方法是没有效果的
例如 list=sc.textFile(“C:\Users\haha174\Desktop\data\test\hive-site.xml”).cache();
但是如果是这样的
list=sc.textFile(“C:\Users\haha174\Desktop\data\test\hive-site.xml”);
list.cache();
是没有效果的
下面给出java 示例:

public class Persist {
    static SparkConf conf=new SparkConf().setMaster("local").setAppName("persist");
   static  JavaSparkContext sc=new JavaSparkContext(conf);
    public static void main(String[] args){

       // noCache();
        cache();

    }
    public static void noCache(){

        JavaRDD<String> list=sc.textFile("C:\\Users\\haha174\\Desktop\\data\\test\\hive-site.xml");
        long beginTime=System.currentTimeMillis();
        long count=list.count();
        System.out.println("无持久化第一次"+(System.currentTimeMillis()-beginTime));


        beginTime=System.currentTimeMillis();
        count=list.count();
        System.out.println("无持久化第二次"+(System.currentTimeMillis()-beginTime));
    }
    public static void cache(){

        JavaRDD<String> list=sc.textFile("C:\\Users\\haha174\\Desktop\\data\\test\\hive-site.xml").cache();
        long beginTime=System.currentTimeMillis();
        long count=list.count();
        System.out.println("持久化第一次"+(System.currentTimeMillis()-beginTime));


        beginTime=System.currentTimeMillis();
        count=list.count();
        System.out.println("持久化第二次"+(System.currentTimeMillis()-beginTime));
    }
}

RDD的持久化是可以手动选择不同的持久化策略的。比如可以将RDD持久化到内存中,持久化到磁盘上,使用序列化的方式持久化,多持久化的数据进行多路复用。只要在调用persist()时传入对应的StorageLevel即可。

MEMORY_ONLY:以非序列化的java对象的方式持久化在JVM内存中。如果内存无法完全存储RDD所有的partition,那么那些没有持久化的partition就会在下一次需要使用它的时候,重新被计算。

MEMORY_AND_DISK
同上但是当某些partiition无法存储在内存中时会持久化到磁盘上,下次需要使用这些partition时,需要从磁盘上读取。

MEMORY_ONLY_SER

同MEMORY_ONLY 但是会使用java序列化方式。将java 对象序列化后进行持久化可以减少内存开销。但是需要进行反序列化会增大cpu 开销
欢迎关注,更多福利

《spark从入门到放弃六: RDD 持久化原理》 这里写图片描述

    原文作者:意浅离殇
    原文地址: https://www.jianshu.com/p/038aa0c1a6ec
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞