Spark Cache 的用武之地

在什么情况下适合使用 Cache

我建议你在做决策的时候遵循以下 2 条基本原则:

  • 如果 RDD/DataFrame/Dataset 在应用中的引用次数为 1,就坚决不使用 Cache
  • 如果引用次数大于 1,且运行成本占比超过 30%,应当考虑启用

Cache第一条很好理解,我们详细说说第二条。这里咱们定义了一个新概念:运行成本占比。它指的是计算某个分布式数据集所消耗的总时间与作业执行时间的比值。我们来举个例子,假设我们有个数据分析的应用,端到端的执行时间为 1 小时。应用中有个 DataFrame 被引用了 2 次,从读取数据源,经过一系列计算,到生成这个 DataFrame 需要花费 12 分钟,那么这个 DataFrame 的运行成本占比应该算作:12 * 2 / 60 = 40%。
你可能会说:“作业执行时间好算,直接查看 Spark UI 就好了,DataFrame 的运行时间怎么算呢?”这里涉及一个小技巧,我们可以从现有应用中 把 DataFrame 的计算逻辑单拎出来,然后利用 Spark 3.0 提供的 Noop 来精确地得到 DataFrame 的运行时间。假设 df 是那个被引用 2 次的 DataFrame,我们就可以把 df 依赖的所有代码拷贝成一个新的作业,然后在 df 上调用 Noop 去触发计算。
Noop 的作用很巧妙,它只触发计算,而不涉及落盘与数据存储,因此,新作业的执行时间刚好就是 DataFrame 的运行时间。

//利用noop精确计算DataFrame运行时间
df.write.format("noop").save()

你可能会觉得每次计算占比会很麻烦,但只要你对数据源足够了解、对计算 DataFrame 的中间过程心中有数了之后,其实不必每次都去精确地计算运行成本占比,尝试几次,你就能对分布式数据集的运行成本占比估摸得八九不离十了。

##Cache 的注意事项
弄清楚了应该什么时候使用 Cache 之后,我们再来说说 Cache 的注意事项。首先,我们都知道,.cache是惰性操作,因此在调用.cache之后,需要先用 Action 算子触发缓存的物化过程。
但是,我发现很多同学在选择 Action 算子的时候很随意,first、take、show、count 中哪个顺手就用哪个。这肯定是不对的,这 4 个算子中只有 count 才会触发缓存的完全物化,而 first、take 和 show 这 3 个算子只会把涉及的数据物化。举个例子,show 默认只产生 20 条结果,如果我们在.cache 之后调用 show 算子,它只会缓存数据集中这 20 条记录。
选择好了算子之后,我们再来讨论一下怎么 Cache 这个问题。你可能会说:“这还用说吗?在 RDD、DataFrame 后面调用.cache不就得了”。还真没这么简单,我出一道选择题来考考你,如果给定包含数十列的 DataFrame df 和后续的数据分析,你应该采用下表中的哪种 Cache 方式?

val filePath: String = _
val df: DataFrame = spark.read.parquet(filePath)//Cache方式一
val cachedDF = df.cache
//数据分析
cachedDF.filter(col2 > 0).select(col1, col2)
cachedDF.select(col1, col2).filter(col2 > 100)//Cache方式二
df.select(col1, col2).filter(col2 > 0).cache
//数据分析
df.filter(col2 > 0).select(col1, col2)
df.select(col1, col2).filter(col2 > 100)//Cache方式三
val cachedDF = df.select(col1, col2).cache
//数据分析
cachedDF.filter(col2 > 0).select(col1, col2)
cachedDF.select(col1, col2).filter(col2 > 100)

我们都知道,由于 Storage Memory 内存空间受限,因此 Cache 应该遵循最小公共子集原则,也就是说,开发者应该仅仅缓存后续操作必需的那些数据列。按照这个原则,实现方式 1 应当排除在外,毕竟 df 是一张包含数十列的宽表。
我们再来看第二种 Cache 方式,方式 2 缓存的数据列是col1和col2,且col2数值大于 0。第一条分析语句只是把filter和select调换了顺序;第二条语句filter条件限制col2数值要大于 100,那么,这个语句的结果就是缓存数据的子集。因此,乍看上去,两条数据分析语句在逻辑上刚好都能利用缓存的数据内容。但遗憾的是,这两条分析语句都会跳过缓存数据,分别去磁盘上读取 Parquet 源文件,然后从头计算投影和过滤的逻辑。这是为什么呢?究其缘由是,Cache Manager 要求两个查询的 Analyzed Logical Plan 必须完全一致,才能对 DataFrame 的缓存进行复用。
Analyzed Logical Plan 是比较初级的逻辑计划,主要负责 AST 查询语法树的语义检查,确保查询中引用的表、列等元信息的有效性。像谓词下推、列剪枝这些比较智能的推理,要等到制定 Optimized Logical Plan 才会生效。因此,即使是同一个查询语句,仅仅是调换了select和filter的顺序,在 Analyzed Logical Plan 阶段也会被判定为不同的逻辑计划。因此,为了避免因为 Analyzed Logical Plan 不一致造成的 Cache miss,我们应该采用第三种实现方式,把我们想要缓存的数据赋值给一个变量,凡是在这个变量之上的分析操作,都会完全复用缓存数据。
你看,缓存的使用可不仅仅是调用.cache那么简单。除此之外,我们也应当及时清理用过的 Cache,尽早腾出内存空间供其他数据集消费,从而尽量避免 Eviction 的发生。一般来说,我们会用.unpersist 来清理弃用的缓存数据,它是.cache 的逆操作。unpersist 操作支持同步、异步两种模式:

异步模式:调用 unpersist() 或是 unpersist(False)
同步模式:调用 unpersist(True)

在异步模式下,Driver 把清理缓存的请求发送给各个 Executors 之后,会立即返回,并且继续执行用户代码,比如后续的任务调度、广播变量创建等等。在同步模式下,Driver 发送完请求之后,会一直等待所有 Executors 给出明确的结果(缓存清除成功还是失败)。各个 Executors 清除缓存的效率、进度各不相同,Driver 要等到最后一个 Executor 返回结果,才会继续执行 Driver 侧的代码。
显然,同步模式会影响 Driver 的工作效率。因此,通常来说,在需要主动清除 Cache 的时候,我们往往采用异步的调用方式,也就是调用 unpersist() 或是unpersist(False)。

总结

我们要掌握使用 Cache 的一般性原则和注意事项,我把它们总结为 3 条:

  • 如果 RDD/DataFrame/Dataset 在应用中的引用次数为 1,我们就坚决不使用 Cache
  • 如果引用次数大于 1,且运行成本占比超过 30%,我们就考虑启用 Cache(其中,运行成本占比的计算,可以利用 Spark 3.0 推出的 noop 功能)
  • Action 算子要选择 count 才能完全物化缓存数据,以及在调用 Cache 的时候,我们要把待缓存数据赋值给一个变量。这样一来,只要是在这个变量之上的分析操作都会完全复用缓存数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/38332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各维度卷积神经网络内容收录

各维度卷积神经网络内容收录 卷积神经网络(CNN),通常是指用于图像分类的2D CNN。但是,现实世界中还使用了其他两种类型的卷积神经网络,即1D CNN和3D CNN。 在1D CNN中,内核沿1个方向移动。1D CNN的输入和…

高通Android 12 /13根据包名授权悬浮窗权限

代码路径frameworks/base/service/core/com/android/server/policy/PhoneWindowManager.java 1、 PhoneWindowManager.java中关于根据包名实现悬浮窗权限授权的功能实现 在实现根据包名授予悬浮窗权限的核心的功能开发中,在通过上述的功能原理实现的过程中分析得知…

EigenLayer 生态解析-再质押与 AVS 崛起

基于以太坊网络的再质押协议 EigenLayer 提出了利用为以太坊网络验证而质押的 ETH 来与其他协议共享安全性和资本效率,同时为协议参与者提供额外利息。在 AVS、再质押、积分系统等概念的推动下,逐渐形成一个庞大的生态系统,从 2024 年初到现在 EigenLayer 的 TVL 增加了 12 …

5.Spring IOC 循环依赖问题源码深度剖析

Spring IOC 容器解决循环依赖问题主要涉及到几个关键的缓存和对象创建过程中的处理逻辑。以下是对循环依赖问题进行深度剖析的概述: 循环依赖的背景 循环依赖发生在两个或多个Bean相互依赖对方,形成一个闭环。这可能是直接的,比如Bean A依赖B…

全球最大智能立体书库|北京:3万货位,715万册,自动出库、分拣、搬运

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 北京城市图书馆的立体书库采用了先进的WMS(仓库管理系统)和WCS(仓库控制系统),与图书…

Linux磁盘监控思路分析

磁盘监控原理 设备又名I/O设备,泛指计算机系统中除主机以外的所有外部设备。 1.1 计算机分类 1.1.1 按照信息传输速度分: 1.低速设备:每秒传输信息仅几个字节或者百个字节,如:键盘、鼠标等 2.中速设备&#xff1a…

leetCode.98. 验证二叉搜索树

leetCode.98. 验证二叉搜索树 题目描述 代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(n…

100张linux C/C++工程师面试高质量图

文章目录 杂项BIOSlinux开机启动流程内核启动流程网络编程网络编程流程tcp状态机三次握手四次断开reactor模型proactor模型select原理poll原理epoll原理文件系统虚拟文件系统文件系统调用阻塞IO非阻塞IO异步IO同步阻塞同步非阻塞IO多路复用进程管理进程状态程序加载内存管理MMU…

力扣(2024.06.30)

1. 81——搜索旋转排序数组2 已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了旋转&#xff0c;使数组变为 [nums[k], n…

vue响应式原理细节分享

在讲解之前&#xff0c;我们先了解一下数据响应式是什么&#xff1f;所谓数据响应式就是建立响应式数据与依赖&#xff08;调用了响应式数据的操作&#xff09;之间的关系&#xff0c;当响应式数据发生变化时&#xff0c;可以通知那些使用了这些响应式数据的依赖操作进行相关更…

前端:多服务端接口资源整合与zip打包下载

项目需求 前端项目开发中,有一个页面需要去整合多个服务接口返回的数据资源,并且需要将这多个服务接口接口返回的数据进行资源压缩,最终打包成zip压缩包,并在客户端完成下载。 基本需求梳理如下, 实现思路 这个需求点其实本质上还是传统的“文件下载”功能需求,常见的例如…

Python使用defaultdict简化值为list的字典

原始代码&#xff1a; from typing import Dictrelated_objects_for_fetch: Dict[str, list] {}for key, value in [(k1, v1), (k1, v2), (k2, v2), (k3, v3), (k2, v2)]:if key not in related_objects_for_fetch:related_objects_for_fetch[key] []if value not in (value…

贪心问题(POJ1700/1017/1065)(C++)

一、贪心问题 贪心算法 贪心算法&#xff08;greedy algorithm&#xff09;&#xff0c;是用计算机来模拟一个「贪心」的人做出决策的过程。这个人十分贪婪&#xff0c;每一步行动总是按某种指标选取最优的操作。而且他目光短浅&#xff0c;总是只看眼前&#xff0c;并不考虑…

第三天:LINK3D核心原理讲解【第1部分】

第三天:LINK3D核心原理讲解 LINK3D学习笔记 目标 了解LINK3D velodyne64线激光雷达LINK3D质心点提取效果: 分布在车道与墙体的交界处。 课程内容 LINK3D论文精讲LINK3D聚合关键点提取代码讲解LINK3D描述子匹配代码讲解除了ALOAM的线特征、面特征,还有其他点云特征吗,是…

如何使用 Postgres 折叠您的堆栈 实现一切#postgresql认证

技术蔓延如何蔓延 假设您正在开发一款新产品或新功能。一开始&#xff0c;您的团队会列出需要解决的技术问题。有些解决方案您将自行开发&#xff08;您的秘诀&#xff09;&#xff0c;而其他解决方案您将使用现有技术&#xff08;可能至少包括一个数据库&#xff09;来解决。…

人工智能期末复习笔记(更新中)

分类问题 分类&#xff1a;根据已知样本的某些特征&#xff0c;判断一个新的样本属于哪种已知的样本类 垃圾分类、图像分类 怎么解决分类问题 分类和回归的区别 1. 逻辑回归分类 用于解决分类问题的一种模型。根据数据特征或属性&#xff0c;计算其归属于某一类别 的概率P,…

ComfyUI局部重绘的四种方式 (附件工作流在最后)

前言 局部重绘需要在图片中选择重绘区域&#xff0c;点击图片右击选择Open in MaskEditor&#xff08;在蒙版编辑器中打开&#xff09;&#xff0c;用鼠标描绘出需要重绘的区域 方式一&#xff1a;重绘编码器 这种方式重绘比较生硬&#xff0c;需要额外搭配使用才行 方式二&…

el-upload 上传图片及回显照片和预览图片,文件流和http线上链接格式操作

<div v-for"(info, index) in zsjzqwhxqList.helicopterTourInfoList" :key"info.id" >编辑上传图片// oss返回线上地址http链接格式&#xff1a;<el-form-itemlabel"巡视结果照片":label-width"formLabelWidth"><el…

Cyber Weekly #13

赛博新闻 1、谷歌发布最强开源小模型Gemma-2 本周五&#xff08;6月28日&#xff09;凌晨&#xff0c;谷歌发布最强开源小模型Gemma-2&#xff0c;分别为9B&#xff08;90亿&#xff09;和27B&#xff08;270亿&#xff09;参数规模&#xff0c;其中9B 模型在多项基准测试中均…

颍川韩氏,来自战国七雄韩国的豪族

颍川是战国七雄韩国故土&#xff0c;韩国被秦国灭国后&#xff0c;王公贵族们除了坚决反秦的被杀了外&#xff0c;大部分都留存了下来。这些人在楚、汉反秦战争中&#xff0c;成为反秦统一战线的重要力量&#xff0c;其中两人先后被封为重新恢复的韩国的国王。 一个是横阳君韩…