前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >浅谈Spark在大数据开发中的一些最佳实践

浅谈Spark在大数据开发中的一些最佳实践

作者头像
五分钟学大数据
发布于 2022-10-05 11:36:12
发布于 2022-10-05 11:36:12
1.8K0
举报

1

前 言

eBay 智能营销部门致力于打造数据驱动的业务智能中台,以支持业务部门快速开展营销活动。目前在我们正在构建一个基于eBay站外营销的业务全渠道漏斗分析指标,涉及近十个营销渠道、数十张数据源表,每天处理的数据达到上百TB。由于业务复杂、数据源异构、指标计算逻辑频繁变更、数据体量巨大,如何快速完成数据处理开发任务是一个巨大的挑战。在长时间的生产实践中,我们总结了一套基于Scala开发Spark任务的可行规范,来帮助我们写出高可读性、高可维护性和高质量的代码,提升整体开发效率

2

基本开发规范

一、字段名规范

  • 字段名应足够简洁清晰,使阅读者能快速理解字段内容。
  • 相似字段名应加上数据源、级别名、细分属性加以区分,例如我们有 Google 的 click数据和内部的click数据,那么就应该使用 PARTNER_CLICK, INTERNAL_CLICK 来命名不同的点击数据。

二、业务字典

  • 对于公司已有统一命名的专业术语,应采用此命名方式,例如 GMB。
  • 对于公司级别命名并未统一的专业术语,在 domain 或 team 内部应有统一的命名规范。比如你的ETL任务中用到了多个系统的数据,对于用户ID,系统A里面叫user_id,系统B里面叫u_id,系统C里面叫mapped_id,当经过我们数据清洗流程后我们应该将这些字段统一成同个概念,比如USER_ID。
  • 数据 schema 中字段名应用下划线分割,而代码变量仍旧应该采用驼峰命名法,字段与变量应该有默认对应关系。
  • 建议维护一个业务名词库用来统一定义专业概念和术语,注明是公司级别的术语或是 domain/team 级别的术语,级别名称应在字段名上体现。

三、幂等性

  • 一个spark任务应该是幂等的,这个任务在有同样的输入时被执行多次输出是恒定的,不应该产生副作用。

四、数值类型

在分析计算需求的时候,需要先对数值类型进行分类,不同的数值类型的计算方式也会不同。

  • 原始数值指标:由事件带出的数值指标,在定比数据级别(ratio level),可以直接进行算数运算 🚩 示例:Clicks,GMB,Spend,Watch Count等 🚩 对于一个广告系列中,我们可以直接将广告系列中的产品的GMB直接相加得到总GMB
  • 衍生数值指标:由原始数值指标进行衍生计算而获得的指标,适用于固定场景。根据衍生计算逻辑,不一定能直接进行算数运算。因而,在计算涉及衍生数值指标时,需考虑该逻辑的影响。 🚩 示例:CPC(每次点击成本=广告费用/点击量),ROAS(支出回报率=广告收入/广告费用) 🚩 对于一个广告系列,我们不能直接将广告系列中的CPC相加得到总CPC
  • 定类数据 (Nominal level) 定类数据不作为数值指标,不可进行算数计算。

3

基本编码规范

一、建议将建表DDL和写数据分离,并且不要在编码中使用drop+create来覆写表数据

  • 当使用drop table再重建table的方式刷新表数据时,会有一定的风险。因为 drop table 和 create table 是非原子性操作,如果drop table完成后,重建的sql因为某些不可抗原因失败了,会直接导致数据丢失,而这个表也变成不可用状态。 如下sql,如果create table失败,table将处于不可用状态:
  • 更佳的方式应该如下:

当数据重新生成完以后只需要使用原子操作更新hive的location即可,这样就可以保证每次写入数据时不影响表的使用。

二、特殊的逻辑应该要有注释,比如 ,应该说明这个字段和对应的值的作用,或者定义一个常量来语义化这个魔法值,比如:

三、在hive中没有布尔值,禁止使用true/false,它在hive中会变成字符串‘true’/’false’,所以请使用数值类型代替布尔类型。

四、若使用Spark SQL编写代码,那么最好不要将核心的SQL逻辑拆分成片段,这样会使可读性下降。对于有多段逻辑的Job,需要让代码更多的暴露出表操作的核心逻辑。

以下是一个反例的伪代码,过度的函数分装会使代码可读性下降,从而无法快速直观的了解表操作的逻辑,那么就需要添加相关的注释方便阅读:

稍微修改一下,以下是伪代码, 我们可以将表操作的逻辑暴露出来,而把非核心逻辑封装起来,这样我们可以轻松理解这段代码到底是在做什么:

4

Spark开发最佳实践

一、使用Spark cache时,需要考虑它能否带来计算时间上的提升。Spark cache是使用给定的存储级别来缓存表的内容或查询的输出内容,常用于未来查询中复用原始文件的场景。

Cache的存储级别分为以下几种:

  • NONE:不进行缓存
  • DISK_ONLY:只在磁盘中缓存
  • DISKONLY_2:只在磁盘中缓存并进行2次备份
  • MEMORY_ONLY:只在内存中缓存
  • MEMORY_ONLY_2:只在内存中缓存并进行2次备份
  • MEMORY_ONLY_SER:只在内存中缓存并进行序列化
  • MEMORY_ONLY_SER_2:只在内存中缓存并进行序列化和2次备份
  • MEMORY_AND_DISK:在内存中缓存,如果内存不足将写入磁盘 (默认缓存级别)
  • MEMORY_AND_DISK_2 :在内存中缓存并进行2次备份,如果内存不足将写入磁盘
  • MEMORY_AND_DISK_SER:在内存中缓存并序列化,如果内存不足将写入磁盘
  • MEMORY_AND_DISK_SER_2 :在内存中缓存并序列化和2次备份,如果内存不足将写入磁盘
  • OFF_HEAP:使用堆外内缓存

如果所需要 cache的数据集过大,使用 MEMORY_ONLY 容易导致OOM;而使用默认的MEMORY_AND_DISK,当内存不适合写入时则会写入磁盘,这时I/O会占用大量时间,并且由于内存减少导致频繁GC,反而使效率下降。在使用 cache 的时候需要平衡好数据 I/O 的开销和计算资源的使用。如果一个数据集cache消耗的I/O时间不是明显小于直接重计算消耗的时间,不建议使用cache。

以下是一个例子,可以看到这里 被使用了两次,那么对于这种场景我们需要权衡通过join计算和cache所消耗的I/O的代价。 是由一张小表 join大表生成的,如果在join完后我们添加了cache,数据量仍旧非常大,cache数据时会产生额外的磁盘写入开销;而考虑到这个 join 操作本身所需要的计算时间并不多,如果从时间性能的角度考虑,这个case我们就不应该使用cache

二、DataFrame的 API 和Spark SQL中的 union 行为是不一致的,DataFrame中union默认不会进行去重,Spark SQL union 默认会进行去重。

三、两个DataFrame来源于同一个数据源,如果直接将它们join则会报以下错:

Detected implicit cartesian product for LEFT(INNER/RIGHT) OUTER join between logical plans

由于来自同一个数据源的DataFrame join很容易产生笛卡尔积,所以Spark默认禁止这种行为。但是在一些业务场景中的确有这种join的情况,解决方案有两种:

  • 在join前将数据存储到临时目录(一般是HDFS),再重新加载进来,用来截断血缘。
  • 添加spark配置:spark.sql.crossJoin.enabled=true 但是不建议这么做,这样会导致其他可能有隐患的join也被忽略了

四、写入分区表时,Spark会默认覆盖所有分区,如果只是想覆盖当前DataFrame中有数据的分区,需要配置如下参数开启动态分区,动态分区会在有数据需要写入分区时才会将当前分区清空。需要注意的是开启动态分区会导致写入效率下降:

五、DataFrame中使用udf时,需要注意udf的参数如果是基础类型则必须不为空,否则不会被执行。

示例:如下代码,一个简单根据int值生成对应的flag,但是如果norb是null的话,那么这段udf不会被执行,对应的norbFlag为null。对于这种由于null值导致的逻辑不一样问题,可以借助DataFrameNaFunctions 来协助处理null值情况。

六、Spark原生不支持数据更改,所以对一些非分区表更新数据是有挑战的。这里我们可以借鉴一个类似delta lake的upsert方案「1」:取出历史数据,按照唯一键将需要upsert的数据挖去,再和待添加的数据做union,可以实现更新有唯一键的表的功能。以下是示例代码:

5

后 记

使用 Spark 开发大数据 ETL 已经成为业界的主流方案。此篇文章总结了我们在使用 Spark 过程中所遇到的挑战和技术案例,希望能够抛砖引玉,引出更多更好的实践方案。最后,也要感谢杨青波对此文章的贡献,以及刘炼刘轶的审稿。

参考

「1」https://github.com/delta-io/delta/blob/73ca6fcea0a25f302ee655f9849f86832bbe5f23/examples/scala/src/main/scala/example/QuickstartSQL.scala

--END--

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学大数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Pyspark学习笔记(四)弹性分布式数据集 RDD(下)
本篇主要讲述了如何在执行pyspark任务时候缓存或者共享变量,以达到节约资源、计算量、时间等目的
TeeyoHuang
2021/08/18
2.7K0
Pyspark学习笔记(四)弹性分布式数据集 RDD(下)
2021年大数据Spark(十七):Spark Core的RDD持久化
在实际开发中某些RDD的计算或转换可能会比较耗费时间,如果这些RDD后续还会频繁的被使用到,那么可以将这些RDD进行持久化/缓存,这样下次再使用到的时候就不用再重新计算了,提高了程序运行的效率。
Lansonli
2021/10/09
4100
Spark面对OOM问题的解决方法及优化总结
map执行中内存溢出代表了所有map类型的操作,包括:flatMap,filter,mapPatitions等。shuffle后内存溢出的shuffle操作包括join,reduceByKey,repartition等操作。后面先总结一下我对Spark内存模型的理解,再总结各种OOM的情况相对应的解决办法和性能优化方面的总结。如果理解有错,希望在评论中指出。
王知无-import_bigdata
2019/12/24
3.1K0
自己工作中超全spark性能优化总结
Spark是大数据分析的利器,在工作中用到spark的地方也比较多,这篇总结是希望能将自己使用spark的一些调优经验分享出来。
guichen1013
2020/11/25
2K0
自己工作中超全spark性能优化总结
【PySpark大数据分析概述】02 Spark大数据技术框架
PySpark作为Apache Spark的Python API,融合Python易用性与Spark分布式计算能力,专为大规模数据处理设计。支持批处理、流计算、机器学习 (MLlib) 和图计算 (GraphX),通过内存计算与弹性数据集 (RDD) 优化性能,提供DataFrame API和SQL接口简化结构化数据处理。可跨Hadoop/云平台部署,适用于ETL、日志分析、实时推荐等场景,具备TB级数据横向扩展能力,并与Pandas等Python工具无缝集成,兼顾高效分析与易用性。
Francek Chen
2025/04/07
780
【PySpark大数据分析概述】02 Spark大数据技术框架
Spark重要知识汇总
RDD(Resilient Distributed Dataset)弹性分布式数据集,是Spark中最基本的数据抽象,代表一个不可变、可分区、里面的元素可并行计算的集合。
Lansonli
2024/08/02
3720
Spark重要知识汇总
如何应对大数据分析工程师面试Spark考察,看这一篇就够了
可以说Spark几乎是企业搭建大数据平台必备组件,作为数据分析工程师在工作中执行程序、调试程序、查询数据都会和Spark打交道,所以对Spark知识的考察也就顺理成章了。
AI科技大本营
2019/09/03
1.7K0
大数据知识点杂记
  ⅲ、重新创建表,在表创建时会自动挂载该协处理器(表在挂载协处理器的时候,回去HBase的根目录下的lib文件夹下面找到jar包)
挽风
2021/04/13
3570
大数据入门:Spark持久化存储策略
持久化存储是Spark非常重要的一个特性,通过持久化存储,提升Spark应用性能,以更好地满足实际需求。而Spark的持久化存储,根据不同的需求现状,可以选择不同的策略方案。今天的大数据入门分享,我们就来具体讲讲Spark持久化存储策略。
成都加米谷大数据
2020/12/14
1.8K0
大数据入门:Spark持久化存储策略
Spark入门必读:核心概念介绍及常用RDD操作
导读:Spark是由加州大学伯克利分校AMP实验室开源的分布式大规模数据处理通用引擎,具有高吞吐、低延时、通用易扩展、高容错等特点。Spark内部提供了丰富的开发库,集成了数据分析引擎Spark SQL、图计算框架GraphX、机器学习库MLlib、流计算引擎Spark Streaming。
IT阅读排行榜
2019/05/10
6920
Spark入门必读:核心概念介绍及常用RDD操作
Spark 基础面试题
答:RDD(Resilient Distributed Dataset)叫做分布式数据集,是spark中最基本的数据抽象,它代表一个不可变,可分区,里面的元素可以并行计算的集合
Tim在路上
2020/08/05
7700
Spark基础全解析
第一,MapReduce模型的抽象层次低,大量的底层逻辑都需要开发者手工完成。 第二,只提供Map和Reduce两个操作。 举个例子,两个数据集的Join是很基本而且常用的功能,但是在MapReduce的世界中,需要对这两个数据集 做一次Map和Reduce才能得到结果。 第三,在Hadoop中,每一个Job的计算结果都会存储在HDFS文件存储系统中,所以每一步计算都要进行硬 盘的读取和写入,大大增加了系统的延迟。 第四,只支持批数据处理,欠缺对流数据处理的支持。
luozhiyun
2020/03/19
1.3K0
Spark Persist,Cache以及Checkpoint
下面我们将了解每一个的用法。重用意味着将计算和数据存储在内存中,并在不同的算子中多次重复使用。通常,在处理数据时,我们需要多次使用相同的数据集。例如,许多机器学习算法(如K-Means)在生成模型之前会对数据进行多次迭代。如果处理过程中的中间结果没有持久存储在内存中,这意味着你需要将中间结果存储在磁盘上,这会降低整体性能,因为与RAM相比,从磁盘访问数据就像是从隔壁或从其他国家获取内容。下面我们看一下在不同存储设备上的访问时间:
smartsi
2019/08/07
2K0
用PySpark开发时的调优思路(上)
这一小节的内容算是对pyspark入门的一个ending了,全文主要是参考学习了美团Spark性能优化指南的基础篇和高级篇内容,主体脉络和这两篇文章是一样的,只不过是基于自己学习后的理解进行了一次总结复盘,而原文中主要是用Java来举例的,我这边主要用pyspark来举例。文章主要会从4个方面(或者说4个思路)来优化我们的Spark任务,主要就是下面的图片所示:(本小节只写了开发习惯调优哈)
Sam Gor
2021/06/25
1.6K0
用PySpark开发时的调优思路(上)
[spark] RDD缓存源码解析
我们可以利用不同的存储级别存储每一个被持久化的RDD。可以存储在内存中,也可以序列化后存储在磁盘上等方式。Spark也会自动持久化一些shuffle操作(如reduceByKey)中的中间数据,即使用户没有调用persist方法。这样的好处是避免了在shuffle出错情况下,需要重复计算整个输入。
UFO
2018/09/04
1.1K0
Spark基础
1.Spark 使用DAG 调度器、查询优化器和物理执行引擎,能够在批处理和流数据获得很高的性能。2.spark把运算的中间数据(shuffle阶段产生的数据)存放在内存,迭代计算效率更高,mapreduce的中间结果需要落地,保存到磁盘;3.Spark计算框架对内存的利用和运行的并行度比mapreduce高,Spark运行容器为executor,内部ThreadPool中线程运行一个Task,mapreduce在线程内部运行container,container容器分类为MapTask和ReduceTask。Spark程序运行并行度高;
857技术社区
2022/05/17
4540
Spark基础
spark中的rdd的持久化
rdd的全称为Resilient Distributed Datasets(弹性分布式数据集) rdd的操作有两种transfrom和action。 transfrom并不引发真正的rdd计算,action才会引发真正的rdd计算。 rdd的持久化是便于rdd计算的重复使用。 在rdd参与第一次计算后,设置rdd的存储级别可以保持rdd计算后的值在内存中。(1)另外,只有未曾设置存储级别的rdd才能设置存储级别,设置了存储级别的rdd不能修改其存储级别。(2)(1)的举例如下:rdd1要经过trans
Albert陈凯
2018/04/08
1.2K0
Spark2.3.0 持久化
Spark 中最重要的功能之一是在操作之间将数据集持久化(缓存)在内存中。当你持久化一个 RDD 时,每个节点都会保存 RDD 的任意分区,RDD在内存中计算时该数据集(或从其派生的数据集)上的其他 Action 可以重用它。这样可以使后面的 Action 操作执行的更快(通常超过10倍)。缓存是迭代算法和快速交互的关键工具。
smartsi
2019/08/07
5850
RDD原理与基本操作 | Spark,从入门到精通
欢迎阅读美图数据技术团队的「Spark,从入门到精通」系列文章,本系列文章将由浅入深为大家介绍 Spark,从框架入门到底层架构的实现,相信总有一种姿势适合你,欢迎大家持续关注:)
美图数据技术团队
2018/09/18
5K0
RDD原理与基本操作 | Spark,从入门到精通
关于Spark的面试题,你应该知道这些!
之前分享过一篇博客,?不会这20个Spark热门技术点,你敢出去面试大数据吗?,那一篇确实是非常精华,提炼出了非常重要同样非常高频的Spark技术点,也算是收到了一些朋友们的好评。本篇博客,博主打算再
大数据梦想家
2021/01/27
1.8K0
关于Spark的面试题,你应该知道这些!
相关推荐
Pyspark学习笔记(四)弹性分布式数据集 RDD(下)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档