首页 » 漏洞 » Spark 缓存机制小计

Spark 缓存机制小计

 
文章目录

首发个人公众号  spark技术分享 ,  同步个人网站  coolplayer.net ,未经本人同意,禁止一切转载

上次写 彻底理解 spark 的checkpoint 机制

有读者跟我留言

多谢,学习了。有个问题请教,文中多次提到”如果已经cache 了,就可以直接使用缓存中的 RDD 了, 就不需要重头计算一遍了“,我在源码中(V2.1)找过没有找到,楼主是否能再详细说明一下

今天翻了下 spark 2.1 的代码, 看了下 spark 的缓存机制

spark 在老版本  sparkEnv 中维护了 一个 cacheManager, 顾名思义,就是用来管理缓存的。 我以前提到过, 在老版本中, CacheManager主要负责 缓存, 如果 用户把一个分区的 RDD 数据 cache了, 下次再用到了这份数据, 就直接可以从 缓存中获取,  CacheManager 底层存储 用的是 BlockManager,  CacheManager负责维护 缓存的元信息和协调

但是现在这个 cacheManager 被干掉了, 在一次重构中, 我还特意研究了一下 pr

https://github.com/apache/spark/pull/11436

CacheManager directly calls MemoryStore.unrollSafely() and has its own logic for handling graceful fallback to disk when cached data does not fit in memory. However, this logic also exists inside of the MemoryStore itself, so this appears to be unnecessary duplication.

大意就是 CacheManager 里面就是调用 MemoryStore.unrollSafely 方法, 加了一点内存不够情况下的处理, 但是这部分逻辑 MemoryStore 中也有, 所以没有必要同一个逻辑出现在两个地方, 这个pr 就针对这个问题进行重构,

spark 开发人员还是很讲究 Don’t repeat yourself 原则的, 赞一个

我看了下这个 pr,  里面就是把 cacheManager 这个类干掉了, 然后把里面响应的逻辑都放在了 BlockManager 的 getOrElseUpdate 方法中, 其实挺简单的。

我们来看下 spark 的缓存机制

spark 中的缓存, 就是把 RDD cache 在 Blockmanager 中, 下次再用到这个 RDD, 直接从缓存中获取,省掉从头再算,

我们考虑一下缓存中一些常见的问题

  • 持久化策略

  • RDD 缓存的过程

  • 什么时候缓存

  • 淘汰机制

  • 怎么更新缓存

我们来看下 spark cache 机制中怎么来处理这些问题

持久化策略

下面是几种持久化策略

  • MEMORY_ONLY 内存中,默认策略, 如果内存不够, 则数据就不会进行持久化,

  • MEMORY_AND_DISK 优先放内存, 如果内存不够, spill 到磁盘

  • MEMORY_ONLY_SER  同 MEMORY_ONLY, 只不过会对数据进行序列化,序列化为字节数组

  • MEMORY_AND_DISK_SER 同 MEMORY_AND_DISK , 只不过会对数据进行序列化,序列化为字节数组

  • DISK_ONLY 只写磁盘

  • MEMORY_ONLY_2 只写磁盘, 复制因子为 2, 会复制1个副本到其他节点

什么时候缓存

这个过程其实很简单, 我们通过一个流程图来看下

Spark 缓存机制小计

RDD 缓存的过程

RDD 缓存之前, Partition 数据 是 Iterator[T] 类型, 遍历获取里面的 Record, Record 空间不连续,

RDD 在缓存到存储内存之后,Partition 被转换成 Block,Record 在堆内或堆外存储内存中占用一块连续的空间。将Partition由不连续的存储空间转换为连续存储空间的过程,Spark称之为”展开”(Unroll)。

注意这里, 如果数据是非序列化的数据, 在 Unroll 过程中, 如果内存用着用着没有了, 就会回滚, 已经申请的内存也会释放, 当然如果是序列化的数据, 就不存在这个问题, 因为开始的时候就能计算出来总共需要多大内存, 一次申请。

淘汰机制

在数据缓存, 数据持久化的时候, 会注册 RDD,  RDD引用为null的时候, 在context cleaner 里面会回调 sc.unpersistRDD 方法, 会把 缓存的RDD 数据从 BlockManager 中删除。

怎么更新缓存

我们都知道, 在数据库缓存中, 或者说在 CDN 缓存中, 如果源数据变了,需要主动去更新缓存数据, 在数据库缓存中, 一般写 DB 的时候,就更新一下缓存数据,  CDN 缓存中, 会主动去节点上刷新 缓存数据。

spark 中怎么来处理这个问题呢, 也就是说,如果依赖链变了, 如果从头 compute 出来的数据, 和现在缓存中的数据不一致,假设一个场景,从 hdfs 中读取数据, 然后做了几个 map 操作, cache 起来, 这个时候我手动把 hdfs 源数据改了, 然后在这个 cache 的RDD 上做 action 操作, 用的还是缓存数据。

所以说 spark 是感知不到的, 需要业务层自己负责。

原创精品,首发个人公众号  spark技术分享 ,  同步个人网站  coolplayer.net ,未经本人同意,禁止一切转载

欢迎关注公众号 spark技术分享

Spark 缓存机制小计

原文链接:Spark 缓存机制小计,转载请注明来源!

0