Apache Spark在reducer端使用键映射和源数据而不是groupByKey()有啥好处?
Posted
技术标签:
【中文标题】Apache Spark在reducer端使用键映射和源数据而不是groupByKey()有啥好处?【英文标题】:Apache Spark any benefit in using map of keys, and source data on reducer side instead of groupByKey()?Apache Spark在reducer端使用键映射和源数据而不是groupByKey()有什么好处? 【发布时间】:2016-06-25 17:04:30 【问题描述】:在回顾这个问题时,Spark groupByKey alternative,我发现我有类似的需求,但在更大的数据集上。好消息是,我每组的数据将适合 reducer 端的内存。
我需要对每个组的数据做一些处理,并写出结果。可能有许多分组值。
输入(从那个问题复制):
"key1": "1", "key1": "2", "key1": "3", "key2": "55", "key2": "66"
输出(从那个问题复制):
"key1": ["1","2","3"], "key2": ["55","66"]
由于这非常低效并且迫使数据大量移动,我在想是否可以使用 spark 框架仅将不同的键映射到不同的减速器,并让减速器侧获取数据(来自数据库或其他)并进行计算。
在这种情况下,我将使用 Spark 来分散工作负载,而不是其他任何东西。这是一种有用的方法吗?还有其他选择吗?
【问题讨论】:
【参考方案1】:这真的取决于数据源;在很多方面,groupBy 逻辑所做的工作与关系数据库在构建索引或查询时所做的工作相同。
记录的完全洗牌在 spark 和 hadoop 中最常见的原因是,这些系统通常用于处理数据在预处理中无法很好组织的情况,或者是因为数据太大或者因为它以未排序的形式(例如来自许多不同服务器源的日志文件)到达,因此访问频率不足以证明持续预处理的合理性。
因此,一般来说,如果您的源数据已经按您需要的分组进行了有效的组织,或者因为分组键是您的数据库源中的主键,或者它们已经在源文件中以这种方式分组,那么您确实可以只在 reducer 中拉入记录值会做得更好,因为您的存储格式已经有效地执行了 shuffle 操作。
但是,如果您的分组键尚未对数据进行索引,或者它分散在未排序的文件中,则尝试在 reducer 中按键提取数据总体上效率低下,因为每次您尝试获取一个单个密钥,底层存储层或读取器必须扫描可能包含这些密钥的完整数据集,有效地将数据访问次数乘以您拥有的密钥数量。
即使数据有索引,如果记录值需要额外的磁盘搜索才能访问它,那么支付额外数据 shuffle 的成本仍然是值得的,因为顺序磁盘访问可以获得数量级比随机访问更高的吞吐量。
主要的收获是,数据洗牌经过优化,可以将数据组织成或多或少的单通道分组,而按键过滤是多通道,除非有效索引。所以 shuffle 成本是源存储层成本的权衡。
【讨论】:
太棒了....验证了我关于不要不必要地移动数据的想法。在我的用例中,特别是 Spark 和 map 任务似乎只是将“工作”(分配键)分配给不同的减速器,就是这样。这种用例正常吗?当然,我可以编写代码将键“分配”到不同的计算节点以进行处理,但似乎 Spark 映射器可以轻松做到这一点。这是使用 Spark 的有用方式吗? 是的,虽然对于一些基本的可并行化任务来说,使用 Spark 是否过度杀伤还存在争议,但将其用作主要处理并行化控制平面的便捷框架绝对是一种常见模式; Hadoop 也是如此。如果不使用 shuffle 功能,您仍然可以从容错、从工作人员那里获取日志、自动重试失败的任务、确保即使在添加/删除节点时也将工作均匀地分配到不同的节点等中受益。以上是关于Apache Spark在reducer端使用键映射和源数据而不是groupByKey()有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章
Apache Spark:在 map reduce 管道中获取执行者 ID
Apache Spark Reduce 与 java.lang.Math.max 意外行为
9. spark源代码分析(基于yarn cluster模式)- Task执行,Reduce端读取shuffle数据文件