You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
10 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 19 | Spark的性能优化案例分析
我们知道现在最主流的大数据技术几乎都是开源的产品不管是Hadoop这样的大数据存储与计算产品还是Hive、Spark SQL这样的大数据仓库又或者Storm、Flink这样的大数据流计算产品还有Mahout、MLlib这样的大数据机器学习算法库它们都来自开源社区。所以我们在使用大数据、学习大数据的过程中肯定少不了要和开源社区打交道。
我在Intel工作期间主要工作就是参与Apache开源社区的大数据项目开发其实上一期我讲的Panthera最初也是准备为Hive项目增强标准SQL处理能力而开发但是因为和Apache Hive项目管理方在开发理念上的冲突最终选择独立开源。后来我又参与了Apache Spark的开发为Spark源代码提交了一些性能优化的Patch。我想通过专栏两期的内容具体介绍一下如何参与Apache这样开源社区的软件开发如何进行软件性能优化以及我在Apache Spark源码上做的一些优化实践。
一方面我希望你能借此更深入、系统地了解软件性能优化另一方面也可以更深入了解Spark的一些运行机制同时也可以了解Apache开源社区的运作模式。因为我们在使用各类大数据产品的时候一定会遇到各种问题想要解决这些问题你可以直接到官方的开源社区去求助并寻找答案。在使用过程中如果这些大数据产品不能满足你的需求你可以阅读源代码并直接对源代码进行修改和优化。因为你在实践过程中产生的需求可能其他人也会有你可以将你修改的源代码提交到开源社区请求合并到发布版本上供全世界开发者使用。这也是开源最大的魅力。
你可能已经注意到作为软件开发人员日常我们使用的大量软件基本上全部来自美国不管是免费开源的Linux、Java、Hadoop、PHP、Tomcat、Spring还是商业收费的Windows、WebLogic、Oracle大到编程语言、操作系统、数据库小到编程框架、日志组件几乎全部来自美国。
软件,特别是开源软件,是没有国界的,属于全人类的技术财富。但是,我觉得我们还要承认,中美之间的技术差距真的很惊人。在当前这样一个中美贸易摩擦不断的背景下,难免让人有些忧虑。缩短这种技术差距也许非一日之功,但是更多的中国工程师参与到开源软件的开发中,让中国在世界软件技术领域获得很多影响力,也许是当下就可以迈出的一步。
## Apache开源社区的组织和参与方式
Apache是一个以基金会方式运作的非盈利开源软件组织旗下有超过一百个各类开源软件其中不乏Apache、Tomcat、Kafka等知名的开源软件当然也包括Hadoop、Spark等最主流的大数据开源软件。
Apache每个项目的管理团队叫项目管理委员会PMC一般由项目发起者、核心开发者、Apache基金会指定的资深导师组成主导整个项目的发展。此外项目的主要开发者叫作committer是指有将代码合并到主干代码权限的开发者而其他没有代码合并权限的开发者叫作contributor。
一般说来参与Apache开源产品开发先从contributor做起。一般的流程是从GitHub项目仓库fork代码到自己的仓库在自己仓库修改代码然后创建pull request提交到Spark仓库后如果有committer认为没问题就merge到Spark主干代码里。
一旦你为某个Apache项目提交的代码被merge到代码主干你就可以宣称自己是这个项目的contributor了甚至可以写入自己的简历。如果能持续提交高质量的代码甚至直接负责某个模块你就有可能被邀请成为committer会拥有一个apache.org后缀的邮箱。
当然我希望你提交的是有质量的代码而不仅仅是对代码注释里某个单词拼写错误进行修改然后就号称自己是某个著名开源项目的contributor了。虽然修改注释也是有价值的但是如果你的pull request总是修改注释的拼写错误很难被认为是一个严肃的开发者。
除了ApacheLinux、以太坊等开源基金会的组织和运作方式也都类似。就我观察最近几年越来越多来自中国的开发者开始活跃在各种重要的开源软件社区里我希望你也成为其中一员。
## 软件性能优化
在熟悉开源社区的运作方式后,接下来我们就可以考虑开始进行性能优化了。但在上手之前,你是否清楚所谓性能优化具体要做些什么呢?
关于软件性能优化,有个著名的**论断**。
1.你不能优化一个没有经过性能测试的软件。
2.你不能优化一个你不了解其架构设计的软件。
不知你是否听过这个论断,我来解释一下。
如果没有性能测试,那么你就不会知道当前软件的主要性能指标有哪些。通常来说,软件的主要性能指标包括:
* 响应时间:完成一次任务(请求)花费的时间。
* 并发数:同时处理的任务数(请求数)。
* 吞吐量:单位时间完成的任务数(请求数、事务数、查询数……)。
* 性能计数器System Load线程数进程数CPU、内存、磁盘、网络使用率等。
如果没有性能指标,我们也就不清楚软件性能的瓶颈,优化前和优化后也是无从对比。这样的优化工作只能是主观臆断:别人这样做说性能好,我们也这样优化。
而如果不了解软件的架构设计,你可能根本无从判断性能瓶颈产生的根源,也不知道该从哪里优化。
所以性能优化的一般过程是:
1.做性能测试,分析性能状况和瓶颈点。
2.针对软件架构设计进行分析,寻找导致性能问题的原因。
3.修改相关代码和架构,进行性能优化。
4.做性能测试,对比是否提升性能,并寻找下一个性能瓶颈。
## 大数据软件性能优化
在大数据使用、开发过程的性能优化一般可以从以下角度着手进行。
**1\. SQL语句优化**。使用关系数据库的时候SQL优化是数据库优化的重要手段因为实现同样功能但是不同的SQL写法可能带来的性能差距是数量级的。我们知道在大数据分析时由于数据量规模巨大所以SQL语句写法引起的性能差距就更加巨大。典型的就是Hive的MapJoin语法如果join的一张表比较小比如只有几MB那么就可以用MapJoin进行连接Hive会将这张小表当作Cache数据全部加载到所有的Map任务中在Map阶段完成join操作无需shuffle。
**2\. 数据倾斜处理**。数据倾斜是指当两张表进行join的时候其中一张表join的某个字段值对应的数据行数特别多那么在shuffle的时候这个字段值Key对应的所有记录都会被partition到同一个Reduce任务导致这个任务长时间无法完成。淘宝的产品经理曾经讲过一个案例他想把用户日志和用户表通过用户ID进行join但是日志表有几亿条记录的用户ID是nullHive把null当作一个字段值shuffle到同一个Reduce结果这个Reduce跑了两天也没跑完SQL当然也执行不完。像这种情况的数据倾斜因为null字段没有意义所以可以在where条件里加一个userID != null过滤掉就可以了。
**3\. MapReduce、Spark代码优化**。了解MapReduce和Spark的工作原理了解要处理的数据的特点了解要计算的目标设计合理的代码处理逻辑使用良好的编程方法开发大数据应用是大数据应用性能优化的重要手段也是大数据开发工程师的重要职责。
**4\. 配置参数优化**。根据公司数据特点为部署的大数据产品以及运行的作业选择合适的配置参数是公司大数据平台性能优化最主要的手段也是大数据运维工程师的主要职责。比如Yarn的每个Container包含的CPU个数和内存数目、HDFS数据块的大小和复制数等每个大数据产品都有很多配置参数这些参数会对大数据运行时的性能产生重要影响。
**5\. 大数据开源软件代码优化**。曾经和杭州某个SaaS公司的大数据工程师聊天他们的大数据团队只有5、6个人但是在使用开源大数据产品的时候遇到问题都是直接修改Hadoop、Spark、Sqoop这些产品的代码。修改源代码进行性能优化的方法虽然比较激进但是对于掌控自己公司的大数据平台来说效果可能是最好的。
## Spark性能优化
有了上面这些性能优化原则和过程我们在了解Spark架构和代码的基础上就可以进行性能优化了。
关于性能测试我们使用的是Intel为某视频网站编写的一个基于Spark的关系图谱计算程序用于计算视频的级联关系。我们使用5台服务器对样例数据进行性能测试程序运行总体性能如下图。
![](https://static001.geekbang.org/resource/image/2b/d0/2bf9e431bbd543165588a111513567d0.png)
这张图我在专栏Spark架构原理分析过。我们将4台Worker服务器上主要计算资源利用率指标和这张图各个job与stage的时间点结合就可以看到不同运行阶段的性能指标如何从而发现性能瓶颈。
![](https://static001.geekbang.org/resource/image/7a/cc/7af885b0492aa68ffbe05bee7e04cdcc.png)
![](https://static001.geekbang.org/resource/image/2f/12/2f8f43d795247f575e953a027070d012.png)
![](https://static001.geekbang.org/resource/image/86/56/86cb0d0beea4178cbf5f7031fec7a956.png)
![](https://static001.geekbang.org/resource/image/09/33/093c888a13a58802413f9d1e2eafcb33.png)
从这些图我们可以看到CPU、内存、网络、磁盘这四种主要计算资源的使用和Spark的计算阶段密切相关。后面我主要通过这些图来分析Spark的性能问题进而寻找问题根源并进一步进行性能优化。
下一期我们一起来看几个Spark性能优化的案例进一步了解Spark的工作原理以及性能优化的具体实践。
## 思考题
如果性能测试发现网卡是整个系统的瓶颈程序运行过程中网卡达到了最大I/O能力整个系统经常在等待网卡的数据传输请问你有什么性能优化建议呢
欢迎你点击“请朋友读”,把今天的文章分享给好友。也欢迎你写下自己的思考或疑问,与我和其他同学一起讨论。