看起来广播方法在我的集群中生成RDD的分布式副本。另一方面,cache()方法的执行只是将数据加载到内存中。
但我不明白缓存的RDD是如何在集群中分发的。
您能告诉我在哪些情况下我应该使用rdd.cache()
和rdd.broadcast()
方法吗?
答案 0 :(得分:16)
你能告诉我在什么情况下我应该使用rdd.cache()和 rdd.broadcast()方法?
RDD分为分区。这些分区本身充当整个RDD的不可变子集。当Spark执行图的每个阶段时,每个分区都会被发送给一个对数据子集进行操作的worker。反过来,如果需要重新迭代RDD,每个工作人员都可以缓存数据。
广播变量用于将一些不可变状态一次发送给每个工作者。如果需要变量的本地副本,可以使用它们。
这两个操作彼此完全不同,每个操作代表不同问题的解决方案。
答案 1 :(得分:13)
cache()或 persist()允许跨操作使用数据集。
当持久 RDD时,每个节点都会存储它在内存中计算的任何分区,并在该数据集(或从中派生的数据集)的其他操作中重用它们。这使得未来的行动更快(通常超过10倍)。 缓存是迭代算法和快速交互使用的关键工具。
每个持久化的RDD可以使用不同的存储级别进行存储,例如,允许您将数据集保留在磁盘上,将其保留在内存中,但作为序列化的Java对象(以节省空间), 跨节点复制,或将其存储在堆外
Broadcast variables允许程序员在每台机器上保留一个只读变量,而不是随副本一起发送它的副本。例如,它们可用于以有效的方式为每个节点提供大输入数据集的副本。 Spark还尝试使用高效的广播算法来分发广播变量,以降低通信成本。
您可以在此documentation页面找到更多详细信息。
有用的帖子:
答案 2 :(得分:6)
请问您能在什么情况下使用rdd.cache()和rdd.broadcast()方法?
我们举一个例子 - 假设你有一个employee_salary数据,其中包含每个员工的部门和薪水。现在说,任务是找到每个员工的平均部门薪水的比例。 (如果员工e1他的部门是d1,我们需要找到e1.salary / average(d1中的所有工资))。
现在一种方法是 - 你首先将数据读入rdd - 比如说rdd1。然后一个接一个地做两件事* -
首先,使用rdd1 *计算部门明智的工资平均值。你最终会得到部门平均工资结果 - 基本上是一个包含deptId与平均值的地图对象 - 在驱动程序上。
其次,您需要使用此结果将每位员工的工资除以各自部门的平均工资。请记住,每个工人都可以有来自任何部门的员工,因此您需要访问每个员工的部门明智的平均工资结果。这该怎么做?那么,您可以将您在驱动程序上获得的平均薪资图发送给广播中的每个工作人员,然后可以将其用于计算rdd1中每个“行”的工资分数。
缓存RDD怎么样?请记住,从最初的rdd1开始,有两个计算分支 - 一个用于计算dept wise average,另一个用于计算rdd中每个雇员的平均值。现在,如果你没有缓存rdd1,那么对于上面的第二个任务,你可能需要再次返回磁盘来读取并重新计算它,因为当你到达这一点时火花可能已经从内存驱逐了这个rdd。但是既然我们知道我们将使用相同的rdd,我们可以要求Spark第一次将它保存在内存中。然后下次我们需要在它上面应用一些转换时,我们已经将它存储在内存中。
*我们可以使用基于dept的分区,这样你就可以避免广播,但为了说明的目的,假设我们不这样做。
答案 3 :(得分:0)
如果要多次使用它,可以缓存或广播对象。
您只能缓存RDD或RDD衍生物,而您可以广播任何类型的对象,包括RDD。
当我们处理RDD / DataFrame / DataSet时,我们使用 cache(),我们希望多次使用数据集,而不是每次都重新计算它。
我们广播一个对象