Yahoo是大数据巨头中对Spark最情有独钟的一家。这次峰会,Yahoo贡献了三个演讲,让我们一一道来。
Andy Feng是从浙大走出来的Yahoo杰出架构师,他的主题演讲试图回答两个问题。
第一个问题,为什么Yahoo爱上Spark?当Yahoo的内容从编辑选择变成数据驱动的、上下文敏感的、个性化的页面时,机器学习、数据科学是 盖子下面的引擎。技术团队苦苦寻找一个可以支撑大规模、实时、适合机器学习探索的平台,特别是内容的生命周期短、对突发内容的响应要快,模型需要在一个小 时或者更短的时间内重新训练,而训练数据可能来自150PB的巨大黑洞,计算可能发生在35000台服务器上。Yahoo的解决方案是 Hadoop+Spark。
这就引出了第二个问题,Hadoop和Spark如何精诚合作?简单来说,前者做批量计算,后者做迭代计算,两者共存于YARN之上,同时共享HDFS、HBase等数据存储。 Yahoo的第一个试验项目是用于Yahoo日本的电商。第一个Spark程序是Collaborative Filtering,30行的代码,在10 台机器上耗时10分钟,而基于Hadoop的实现需要106分钟。第二个试验项目是流广告,算法是基于Vowpal Wabbit的 logistic regression,120行代码,1亿样本、13000个特征,30个迭代,耗时30分钟。最有意思的是这个算法在Spark- on-YARN宣布后2个小时就完成了。
目前Yahoo已经有4个Spark committer,在Spark-on-YARN、Shark、安全、可扩展性和可运营性上做出了可观的贡献。
下一个主题演讲者Tim Tully同样是Yahoo的杰出架构师,他详细讲述了Spark和Shark在Yahoo数据和分析平台里的应用。
1999到2007年间的Yahoo数据处理平台采用NFS保存数据,C++写就的Map/Reduce实现,和Perl脚本做粘合,这个架构的缺 点就是要把数据搬到计算所在的地方。逐渐演化到以Hadoop为核心的架构:日志先采集到NFS,进而移到HDFS,用Pig或MapReduce做 ETL或massive joins,结果加载到数据仓库,然后用Pig、MapReduce或Hive做聚合和报表生成,报表存入 Oracle/MySQL,同时还有一些商业BI工具,和Storm-on-YARN做流处理。这个架构的问题是,太慢。报表的生成延迟长达2-6小时, 海量的join耗时更长,交互式查询也几乎不可能。原先的解决方案并不完美,如预先计算、把结果存下来供未来查询,但结果不能反映实时的变化。
Yahoo考虑过Pig on Tez,或者Hive on Tez。这时候,Spark/Shark的出现使之成为Yahoo的圣杯。所 以,Hadoop+Spark的架构就应运而生了,基本设计是Hadoop和Spark肩并肩共存于YARN之上,而由于有些SQL负载需要可预测的服务 质量,所以又加入了一些专门跑Shark的大内存集群(卫星集群)。在这个架构里,Spark取代Hadoop做ETL,而Shark取代商业 BI/OLAP工具,承担报表/仪表盘和交互式/即席查询,同时与桌面BI工具(如Tableau)对接。目前在Yahoo部署的Spark集群有112 台节点,9.2TB内存,还在考虑加入SSD。
Tim介绍了未来的工作。首先,Pig/MapReduce将完全让位,由Spark承担所有的ETL任务。其次,虽然卫星集群仍将存在,Shark-on-Spark-on-YARN将在2014年部署。
第三个出场的是Yahoo的工程师Gavin Li,此君介绍了Spark在Audience Expansion中的应用。 Audience Expansion是广告中寻找目标用户的一种方法:首先广告者提供一些观看了广告并且购买产品的样本客户,据此进行学习,寻找更多可 能转化的用户,对他们定向广告。Yahoo采用的算法是logistic regression,输入数据和中间数据都是TB级,原来的系统采用 Hadoop Streaming,2万多行代码,运行时30000+ mappers,2000 reducers,20+作业,耗时16小时。直接移 植到Spark需要6个工程师3个季度的工作量。Yahoo的做法是构建一个transition层,自动把Hadoop Streaming作业转化为 Spark作业,只需2人季。下一步就是分析性能,进行优化。
开始的Spark版本相比Hadoop Streaming版本的加速只是2倍多,远远低于期望。下面对可扩展性的分析和优化就跟 Audience Expansion不相干了,有普遍的借鉴意义。影响可扩展性的主要因素是shuffle,其过程如下:mapper-side把中间 结果(非压缩数据)写到文件里,每个文件对应一个reducer的partition;reducer-side把文件读到内存里才能计算,所以 reducer所在机器的内存决定了partition的大小;所有的mapper结束后,reducer才开始把全部shuffle文件拉过来,进行计 算。
下面仔细分析一下它的问题:由于partition受限内存大小,在数据量较大时,partition的数目、也就是shuffle文件的数目将会 很大。在Yahoo的例子中,3TB压缩数据(相当于90TB非压缩)需要46080个partition/shuffle文件。第一个问题在 mapper-side,每个mapper需要并发写46080个文件,每个文件要164KB的I/O buffer,如果一个服务器有16个 mapper,这需要115GB的内存。解决方案是减小buffer大小到12KB,这样使内存消耗降到10GB。第二个问题是巨大数量的小文件使得磁盘 读写效率降低,文件系统元数据的开销也大(光删除这些文件就要花2个小时),怎么解决呢?直接的办法是在reducer-side做内存压缩,这样使得内 存“大”了10-100倍,这样partition的有效大小也变大了,shuffle文件的数目可以减少到1600个左右。Yahoo的patch甚至 允许reducer在内存不够时spill到磁盘,这就完全解决了可扩展性的问题。
Gavin还描述了个场景,Spark的输入数据来自Hadoop,如果Spark采用与Hadoop同样的hash函数,就可以免去反复 partition、极大减少shuffle文件的数量。最后一个问题,考虑到reducer必须等所有mapper结束才能开始拉shuffle文件, 为了提高资源利用率,Yahoo增大了maxBytesInFlight来提升网络效率,同时分配相当于物理核数目2倍的线程数来增加核的使用率。
Yahoo的解决方案具有普遍意义,其贡献已经进入Spark的codebase,这也是很多公司开始拥抱Spark的原因,一方面其尚年轻、有贡献的机会,另一方面它又很活跃,迅速成熟。
除了Matei的主题演讲,有一个演讲在Youtube上获得了最多的点击率,它来自Adatao。Adatao是Spark社区的早期贡献者之 一,这次的演讲不仅描绘了一个建筑在Spark之上数据智能的美好愿景,而且带来了精彩的demo。Christopher从穿越大西洋说起,泰坦尼克悲 剧性地在中途沉没;同样的,当横跨大数据之洋时,黄色小象(Hadoop)也只能行一半的路。
紧接着就是干货了。Christopher展示了第一个demo:Adatao的pInsight是个叙述式的BI工具,表现为文字处理工具(基于 浏览器);Adatao的cofounder,Michael在文档中键入类似自然语言的操作语句,其被送往云中(EC2)的pAnalytics后端服 务器;pAnalytics运行于Spark之上,做数据处理和挖掘,返回结果后,pInsight对其做可视化,显示于文档中。Michael演示了从 data.gov抓下航班数据,可视化到美国地图之上,可以看数据的schema,进行各种聚合、分析和交互式的可视化,非常简单。
除了商业视图,pInsight还提供了数据科学视图。该视图基于一个集成开发环境,交互式开发可以基于R语言,可以很好利用R的可视化(plot)能力。Michael演示了利用航班数据,分析并且预测延误,非常简单。
有趣的是,商业视图也支持数据科学工作,它的交互语言也支持R和Python。
随后Christopher介绍了几个商业案例:互联网服务提供商(ISP)从Hive+Tableau转到Adatao,做交互式、即席查询;客 户服务提供商做多渠道(mobile、Web等)销售和产品推荐;重型机械设备生产商对传感器数据分析,做预测性维护,之前MongoDB,不易分析,现 转到Spark;移动广告平台做定向广告和转化率预测。
pAnalytics能够在10秒内完成所有的分析。Christopher认为10秒跟10分钟的差距不是60倍,而是天壤之别,因为一旦延迟超 过某个阈值,数据科学家会改变行为,他们将失去一些创造力。另外,对于linear modeling,pAnalytics达到了1GB/秒的吞吐量, 相当可观。
Christopher感叹Spark社区的强大,能够让Adatao在短期内实现目前的成就,他承诺未来将代码回馈给社区。
对于Spark程序员来说,这个演讲是必看的。Patrick从一个简单的例子说明理解Spark工作机制的重要性,使用Group By Key的实现比基于reduceByKey的版本性能慢10-100倍。随着他介绍了RDD、DAG、Stage和Task的概念,尤其是Task内部的工作机制相信对很多Spark工程师都是新的认识。
他演示了Spark 0.9将发布的带有更丰富性能数据的Web UI,用以了解Spark应用的底层细节。最后,他分析了性能的几个常见问题和解决方案:
map算子的闭包(Closure)如果自由变量是个大的数据结构,序列化的代价非常高,要采用广播变量;
因为filter类算子导致结果RDD稀疏,可能会生成很多空的task(或执行时间<20ms的task),可以用coalesce或repartition对RDD重新划分;
如果map算子的闭包需要做heavy的初始化和结束工作(如连接MongoDB,算完后关闭连接),这些开销是对每个数据记录都要付出的,可以用mapPartitions或mapWith,仅对每个partition(而不是每个记录)做一次这种工作;
因为partition key不合适导致的数据skew,需要重写程序;
因为straggler导致的worker skew,可以打开spark.speculation开关或手动关掉有问题的节点;
Stage之间的shuffle需要写大量数据到文件,这依赖于OS的buffer cache,因此不要让JVM的heap把内存用满,留20%给OS buffer cache;
本地shuffle文件不要写到/tmp,用spark.local.dir配置多个硬盘保证高吞吐量;
控制reducer的数量,过多的话任务启动开销大,过少的话并行性不够;
最后,用户常常用collect算子退入Scala空间,在driver里串行执行一些逻辑,又慢又容易出现内存不够的问题,尽量用Spark算子并行地计算或存储数据。
Kay是斯坦福教授、Tcl/Tk和Lustre主创者John Ousterhout的女儿,操作系统功力自然深厚。目前Spark的调度是中心 式的,一个节点上的Spark Context调度众多的task到很多worker节点上。多个用户可能同时使用同一个Spark Context,造成瓶颈。从趋势上看,作业越来越短,从MapReduce最早的10分钟级别,到Spark的秒级和Spark Streaming的 亚秒级(<100ms);同时,集群越来越大,大到几百台以后,调度成为主要瓶颈。对于0.8版本,Spark的调度吞吐量是1500个 task/sec,这限制了task的运行时间和集群的大小:如果task运行时间在10秒级,能够支持1000个16核节点;如果task是秒级,支持 最多100节点;而到100ms级时,最多只能10个节点。在现有调度器上做优化边际效益有限。
Sparrow应运而生,它首先让每个用户有独立的调度器,另外,要支持更大的集群或更短的task时,只需增加新的调度器,整体的吞吐量和容错性 都得到提升。Sparrow设计了一个调度器对众多worker的探测协议来选择合适的worker来执行task,具体细节请参考 视频、 slides和 SOSP’13论文。当task运行时间小于3秒时,Sparrow已经优于现在的Spark调度器,小于1.5秒时,则远为优胜。而跑TPC-H时Sparrow相比理论最优的调度器只有12%的差距。
Jason的团队试图在Spark上构建一个集流处理、交互式查询、多迭代计算(图计算和机器学习)于一身的分析栈。他讨论了三个案例。第一个是实 时的日志聚合和分析,采用了Kafka+Spark mini-batch的做法,未来会迁移到Spark Streaming。第二个是交互式查询,基 于Spark/Shark,他特别介绍了一个统计Unique Event Occurrence(如Unique View)的时间序列分析,采用2- level aggregation。第三个是复杂机器学习和图计算,他介绍了一个N-degree Association问题,用于视频相似性图谱做 聚类,做视频推荐。这些案例都来自实际需求,如优酷土豆的生产环境。