4. 缓存
-
缓存的意义
-
缓存相关的 API
-
缓存级别以及最佳实践
4.1. 缓存的意义
-
使用缓存的原因 - 多次使用 RDD
- 使用缓存的原因 - 容错
上述两个问题的解决方案其实都是 缓存
, 除此之外, 使用缓存的理由还有很多, 但是总结一句, 就是缓存能够帮助开发者在进行一些昂贵操作后, 将其结果保存下来, 以便下次使用无需再次执行, 缓存能够显著的提升性能.
所以, 缓存适合在一个 RDD 需要重复多次利用, 并且还不是特别大的情况下使用, 例如迭代计算等场景.
4.2. 缓存相关的 API
-
可以使用
- 也可以使用 persist 方法进行缓存
- 缓存其实是一种空间换时间的做法, 会占用额外的存储资源, 如何清理?
cache
方法进行缓存
4.3. 缓存级别
其实如何缓存是一个技术活, 有很多细节需要思考, 如下
-
是否使用磁盘缓存?
-
是否使用内存缓存?
-
是否使用堆外内存?
-
缓存前是否先序列化?
-
是否需要有副本?
如果要回答这些信息的话, 可以先查看一下 RDD 的缓存级别对象
val conf = new SparkConf().setMaster("local[6]").setAppName("debug_string") val sc = new SparkContext(conf) val interimRDD = sc.textFile("dataset/access_log_sample.txt") .map(item => (item.split(" ")(0), 1)) .filter(item => StringUtils.isNotBlank(item._1)) .reduceByKey((curr, agg) => curr + agg) .persist() println(interimRDD.getStorageLevel) sc.stop()
打印出来的对象是 StorageLevel
, 其中有如下几个构造参数
根据这几个参数的不同, StorageLevel
有如下几个枚举对象
缓存级别 | userDisk 是否使用磁盘 | useMemory 是否使用内存 | useOffHeap 是否使用堆外内存 | deserialized 是否以反序列化形式存储 | replication 副本数 |
---|---|---|---|---|---|
| false | false | false | false | 1 |
| true | false | false | false | 1 |
| true | false | false | false | 2 |
| false | true | false | true | 1 |
| false | true | false | true | 2 |
| false | true | false | false | 1 |
| false | true | false | false | 2 |
| true | true | false | true | 1 |
| true | true | false | true | 2 |
| true | true | false | false | 1 |
| true | true | false | false | 2 |
| true | true | true | false | 1 |