六、持久化

  1. 如果简单的对RDD 调用行动操作,则Spark 每次都会重新计算RDD 以及它所有的依赖RDD

    • 在迭代算法中,消耗会格外大。因为迭代算法通常会使用同一组数据。
  2. 当我们让spark 持久化存储一个RDD 时,计算出RDD 的节点会分别保存它们所求出的分区数据。

    • 如果一个拥有持久化数据的节点发生故障,则spark 会在需要用到该缓存数据时,重新计算丢失的分区数据。
    • 我们也可以将数据备份到多个节点上,从而增加对数据丢失的鲁棒性。
  3. 我们可以为RDD 选择不同的持久化级别:在pyspark.StorageLevel 中:

    • MEMORY_ONLY:数据缓存在内存中。

      • 内存占用:高;CPU 时间:低;是否在内存:是;是否在磁盘中:否。
    • MEMORY_ONLY_SER:数据经过序列化之后缓存在内存中。

      • 内存占用:低;CPU 时间:高;是否在内存:是;是否在磁盘中:否。
    • MEMORY_AND_DISK:数据缓存在内存和硬盘中。

      • 内存占用:高;CPU 时间:中等;是否在内存:部分;是否在磁盘中:部分。
      • 如果数据在内存中放不下,则溢写到磁盘上。如果数据在内存中放得下,则缓存到内存中
    • MEMORY_AND_DISK_SER:数据经过序列化之后缓存在内存和硬盘中。

      • 内存占用:低;CPU 时间:高;是否在内存:部分;是否在磁盘中:部分。
      • 如果数据在内存中放不下,则溢写到磁盘上。如果数据在内存中放得下,则缓存到内存中
    • DISK_ONLY:数据缓存在磁盘中 。

      • 内存占用:低;CPU 时间:高;是否在内存:否;是否在磁盘中:是。

    如果在存储级别末尾加上数字 N,则表示将持久化数据存储为 N份。如:

    1. MEMORY_ONLY_2 #表示对持久化数据存储为 2 份

    python 中,总是使用pickle library 来序列化对象,因此在python 中可用的存储级别有:

    MEMORY_ONLY、MEMORY_ONLY_2、MEMORY_AND_DISK、MEMORY_AND_DISK_2、DISK_ONLY、DISK_ONLY_2

  4. .persist(storageLevel=StorageLevel(False, True, False, False, 1)) :对当前RDD 进行持久化

    • 该方法调用时,并不会立即执行持久化,它并不会触发求值,而仅仅是对当前RDD 做个持久化标记。一旦该RDD 第一次求值时,才会发生持久化。
    • .persist() 的默认行为是:将数据以序列化的形式缓存在JVM 的堆空间中
  5. .cache():它也是一种持久化调用。

    • 它等价于.persist(MEMORY_ONLY)
    • 它不可设定缓存级别
  6. .unpersist():标记当前RDD 是未缓存的,并且将所有该RDD 已经缓存的数据从内存、硬盘中清除。

  7. 当要缓存的数据太多,内存放不下时,spark 会利用最近最少使用(LRU) 的缓存策略,把最老的分区从内存中移除。

    • 对于MEMORY_ONLY、MEMORY_ONLY_SER 级别:下一次要用到已经被移除的分区时,这些分区就要重新计算
    • 对于MEMORY_AND_DISK、MEMORY_AND_DISK_SER 级别:被移除的分区都会被写入磁盘。
  8. .getStorageLevel():返回当前的缓存级别