Spark:The Definitive Guide--读书小结(四)

前言

大概花了一个月(2020-09~2020-10)左右的时间,看完了整本书。笔者毕业后,主要从事机器学习、数据挖掘方向的相关工作。由于Spark作为目前主流的分布式计算引擎,个人也一直在用Spark进行相关的数据分析与建模工作。通读全书,感觉比较适合入门级学习,主要介绍了Spark 2.0相关API及Spark生态。涵盖Spark SQL、Struct Streaming、GraphX、MLlib等内容。对初学者而言是一本不错的书籍。

数据、源码链接: https://github.com/databricks/Spark-The-Definitive-Guide

第Ⅰ部分 大数据与Spark概述

链接: https://blog.csdn.net/Java_Man_China/article/details/109321946

第Ⅱ部分 结构化API–DataFrame、SQL和Dataset

链接: https://blog.csdn.net/Java_Man_China/article/details/109321946

第Ⅲ部分 低级API

链接: https://blog.csdn.net/Java_Man_China/article/details/109378254

第Ⅳ部分 生产与应用

Spark UI
无论是为了调试还是更好的理解应用程序在集群上的执行过程,通过Spark UI和Spark日志是最方便获取监控报告的方式,这些报告包括Spark应用程序的运行状态,如RDD的转化和查询计划的执行信息等。
在这里插入图片描述
Jobs:对应Spark作业
Stages:对应各个阶段(及相关任务)
Storage:包含当前在Spark应用程序中缓存的信息和数据
Environment: Spark应用程序的配置信息
SQL: 对应提交的结构化API查询(SQL及DataFrame)
Executors: 应用程序中各执行器的详细信息

Summary Metrics:
查看某个Job的某个stage中所有task的执行情况,显示了各种指标的统计概要,注意警惕不均匀的数据分布。在本例中,各项指标分布均匀。
在这里插入图片描述
Spark常见问题:

  1. Spark作业未启动:
    集群配置问题或应用程序资源需要过大导致,常见的问题是每个执行器进程分配了太大的内存,超过了集群管理器的内存资源配额。

    解决方案:
    合理申请Spark资源

  2. 任务缓慢
    此问题在优化程序时非常常见,这可能是由于工作负载没有被均匀分布在集群各节点上(数据倾斜),或者由于某台计算节点比其它节点速度慢(硬件问题)。

    解决方案:
    1.尝试增加分区数,减少每个分区被分配到的数据量。
    2.分配给执行器进程更多的内存。
    3.尝试通过另一列组合来重新分区或自定义分区。
    4.打开推测功能,可以解决单节点硬件带来的速度缓慢问题。
    5.检查UDF函数是否在其对象分配或业务逻辑中有资源浪费。
    6.Dataset在执行大量的对象实例化并将记录转化为用户定义函数中的Java对象,可能会导致大量垃圾回收。请查看Spark UI中垃圾回收指标。

    任务缓慢和落后者可能是调试中遇到的最困难的问题之一,因为有太多的可能性导致任务缓慢,然而大多数情况下是某种数据倾斜导致的。

  3. 缓慢的聚合操作
    在执行groupby操作时产生缓慢任务或聚合操作之后的作业也执行的非常缓慢。

    解决方案:
    1.在聚合操作前增加分区数量可能有助于减少每个任务中处理不同key的数量。
    2.增加执行器的内存配额也可以缓解此问题。如果一个key数据量过大,增加内存可以减少与磁盘交互数据并更快的完成任务,尽管他可能依旧比其它进程要慢得多。
    3.如果你发现聚合操作之后的任务也很慢,这意味着你的数据集在聚合后依旧可能不均衡,尝试repartition并对数据进行随机重分区。
    4.优化代码逻辑,尽可能使所有filter操作和select操作在聚合之前发生。
    5.确保空值被正确的表示(建议使用Spark的null关键字),不要用”"或“empty”等表示,因为Spark优化器通常会在作业初期来跳过对null值得处理,但它无法为你自定义的空值进行此优化。
    这个问题并不能总是能够得到解决,如果你的作业中需要对存在数据倾斜的某个Key执行聚合操作,那么执行聚合操作时就是很慢。

  4. 缓慢的连接操作

    解决方案:
    1.实验不同的连接操作顺序,前提是一些连接操作会过滤大量数据。
    2.执行连接操作前,对数据集进行分区,这对于减少数据集在集群之前的移动是非常有用的,特别是多个连接操作中使用相同的数据集时。请注意,分区是以数据shuffle为代价的。
    3.数据倾斜导致的连接变慢
    4.可以强制采用广播小表的方式

  5. driver端OOM
    通常是由于驱动器进程收集了过多的数据集,从而导致内存不足。
    解决方案:
    1.查看collet之类操作的数据集是否过大
    2.可能使用了广播数据,但是广播的数据集太大
    3.应用程序长时间运行导致生成了大量对象,并且无法释放它们。
    4.增加driver端内存

  6. excutor OOM
    应用程序有时可以自动从这类错误中恢复,但不一定,主要还是取决于导致这种错误的根本原因。

    解决方案:
    1.增加excutor 内存
    2.在使用RDD或Dataset时,由于对象实例化可能导致产生执行器的内存溢出,应尽可能避免使用UDF,同时尽可能使用Spark的结构化操作。

  7. 序列化错误
    主要表现为作业失败并显示序列化错误。用结构化API时,这种现象非常罕见。但当你使用RDD或UDF执行自定义逻辑时,或序列化到执行器的任务或共享数据无法被序列化时,就常会遇到序列化错误。

    解决方案:
    1.如果你正在使用Kyro序列化,确保注册了你的类
    2.在scala或java中创建UDF时,不要在UDF中引用封闭对象的任何字段

Spark性能优化
提高性能最好的方法是实现良性的检测功能和作业历史跟踪功能,没有这些信息就很难理解你的优化策略是否真的提高了性能。

间接性能优化
1.RDD对象序列化:Kryo序列化比Java序列化更紧凑,效率更高

2.数据存储:Spark处理最有效的文件存储格式是parquet

3.文件可拆分:无论选择哪种文件都应该保证它式可拆分的,这样不同的任务就可以并行的读取文件。通常选择gzip压缩的parquet文件。zip和tar压缩的文件不可拆分

4.表分区:如果用户在其查询时经常按照”date“进行过滤,就可以用该列进行分区,这可以大大减少用户在大多数查询中读取的数据量,从而显著提高速度。

5.表分桶:当按列分区时,若分割细粒度太细导致很多小文件,此时可以尝试表分桶。

6.文件的数量:如果有很多小文件,获得文件列表和找到每个文件的开销都将非常大。例如,hdfs每个数据块是128MB,如果你有30个小文件,每个是5MB,实际上只要2个数据块就可以存储,但此时却需要请求30个块。可以通过maxRecordsPerFile选项控制每个文件中的记录数。一般建议调整文件大小几十兆(至少)。

7.内存压力、垃圾回收:尽可能的多使用结构化API,这不仅会提高Spark执行效率,而且还会大大降低内存压力,因为结构化API不会产生JVM对象。

直接性能优化

1.并行度:如果需要加速某一个特地的阶段,最先尝试的应该就是增加其并行度。可以通过spark.default.parallelism属性来设置它。

2.过滤优化:尽可能的将过滤器移动到Spark任务的最开始,有时,甚至可以放置在数据的源头。启动表分区和表分桶也有助于实现此目的。

3.重分区、合并
重分区的调用可能会导致Shuffle操作,但是通过平衡集群上的数据可以从整体上优化作业的执行,所以这个代价是值得的。重分区主要有coalesce(不会发生shuffle、单节点合并分区)、repartition(发生shuffle、跨节点重分区)。重分区操作应该在连接操作之前或这cache操作之前调用会产生非常好的效果。

4.自定义分区
尝试在RDD级别上自定义分区,可以更好的解决数据倾斜问题。DataFrame上的分区主要采用的是hash分区。

5.避免使用UDF函数
UDF是昂贵的,因为它们强制的将数据表示为JVM对象

6.缓存
重复使用相同的数据集时,最有用的优化方式之一就是将其缓存(内存或磁盘)。这将使得后续多次读取更块,不会再重头执行一遍。由于缓存会导致数据序列化、反序列化和存储开销,因此并不是我们应该一直做的事。例如,你只想在后续的操作中访问该数据集一次,此时缓存只会降低速度。

7.广播变量,针对大小表Join操作时可采用

8.聚合操作时,采用RDD,用reduceByKey替换groupByKey

第Ⅴ部分 流处理

链接: https://editor.csdn.net/md/?articleId=109321946//未写待续

第Ⅵ部分 高级分析与机器学习

链接: https://editor.csdn.net/md/?articleId=109321946//未写待续

第Ⅶ部分 生态系统

链接: https://editor.csdn.net/md/?articleId=109321946//未写待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值