一、来源

Streaming Hadoop Performance Optimization at Scale, Lessons Learned at Twitter

(Data platform @Twitter)

二、观后感

2.1 概要

此稿介绍了Twitter的核心数据类库团队,在使用Hadoop处理离线任务时,使用的性能分析方法,及由此发现的问题和优化手段,对如何使用JVM/HotSpot profile(-Xprof)分析Hadoop Job的方法调用开销、Hadoop配置对象的高开销、MapReduce阶段的排序中对象序列化/反序列的高开销问题及优化等给出了实际可操作的方案。

其介绍了Apache Parquet这一面向列的存储格式,并成功应用于列投影(column project),配合predicated push-down技术,过滤不需要的列,极大提高了数据压缩比和序列化/反序列化的性能。
纯干货。
32个赞!

2.2 优化总结

1) Profile!(-Xprofile)性能优化不能靠猜,而应靠分析!
2) 序列化开销很大,但是Hadoop里有许多序列化(操作)!
3) 根据特定(数据)访问模式,选择不同的存储格式(面向行还是面向列)!
4) 使用column projection。
5) 在Hadoop的MR阶段,排序开销很大,使用Raw Comparators以降低开销。
注:此排序针对如Comparator,其会引发序列化/反序列化操作。
6) I/O并不一定就是瓶颈。必要的时候要多I/O换取更少的CPU计算。

JVM/HotSpot原生profile能力(-Xprof),其优点如下:
1) 低开销(使用Stack sampling)。
2) 能揭示开销最大的方法调用。
3) 使用标准输出(Stdout)将结果直接写入Task Logs。

2.3 Hadoop的配置对象

1) Hadoop的Configuration Object开销出人意料的高。
2) Conf的操作看起来就像一个HashMap的操作。

3) 构造函数:读取+解压+分析一个来自磁盘的XML文件

4) get()调用引起正则表达式计算,变量替换。

5) 如果在循环中对上述等方法进行调用,或者每秒一次调用,开销很高.某些(Hadoop)Jobs有30%的时间花在配置相关的方法上!(的确是出人意料的高开销)

总之,没有profile(-Xprof)技术,不可能获取以上洞察,也不可能轻易找到优化的契机和方向,需要使用profile技术来获知I/O和CPU谁才是真正的瓶颈。

2.4 中间结果的压缩

  • Xprof揭示了spill线程中的压缩和解压缩操作消耗了大量时间。
  • 中间结果是临时的。
  • 使用lz4方法取代lzo level 3,减少了30%多的中间数据,使其能被更快地读取。
  • 并使得某些大型Jobs提速150%。

2.5 对记录的序列化和反序列,会成为Hadoop Job中开销最高的操作!

2.6 对记录的序列化是CPU敏感的,相对比之下,I/O都不算什么了!

2.7 如何消除或者减小序列化/反序列化引起的(CPU)开销?

2.7.1 使用Hadoop的Raw Comparator API(来比较元素大小)

开销分析:如下图所示,Hadoop的MR在map和reduce阶段,会反序列化map结果的keys以在此阶段进行排序。

(反序列化操作)开销很大,特别是对于复杂的、非原语的keys,而这些keys又很常用。

Hadoop提供了一个RawComparator API,用于对已序列化的(原始的)数据(字节级)进行比较:

不幸的是,需要亲手实现一个自定义的Comparator。

现在,假设数据已序列化后的字节流,本身是易于比较的:
Scala有个很拉风的API,Scala还有一些宏可以产生这些API,以用于:
Tuples , case classes , thrift objects , primitives , Strings,等等数据结构。

怎么拉风法呢?首先,定义一个密集且易于比较的数据序列化(字节)格式:

其次,生成一个用于比较的方法,以利用这种数据格式的优势:

下图是采用上述优化手段后的比较开销对比:

提速到150%!
接着优化!

2.7.2 使用column projection

不要读取不需要的列:

1) 可使用Apache Parquet(列式文件格式)。

2) 使用特别的反序列化手段可以在面向行的存储中跳过一些不需要的字段。

面向列的存储中,一整列按顺序存储(而不是向面向行的存储那样,列是分开存储的):

可以看到,面向列的存储,使得同类型的字段被顺序排在一起(易于压缩):

采用Lzo + Parquet,文件小了2倍多!

2.7.3 Apache Parquet

1) 按列存储,可以有效地进行列投影(column projection)。
2) 可按需从磁盘上读取列。
3) 更重要的是:可以只反序列化需要的列!

看下效果:

可以看到,列数越少,Parquet的威力越大,到40列时,其效率反而不如Lzo Thrift。

  • 在读取所有列的情况下,Parquet一般比面向行的存储慢。
  • Parquet是种密集格式,其读性能和模式中列的数目相关,空值读取也消耗时间。
  • 而面向行的格式(thrift)是稀疏的,所以其读性能和数据的列数相关,空值读取是不消耗时间的。

跳过不需要的字段,如下所示:

  • 虽然,没有降低I/O开销
  • 但是,可以仅将感兴趣的字段编码进对象中
  • 相对于从磁盘读取 + 略过编码后字节的开销,在解码字符串时所花的CPU时间要高的多!

看下各种列映射方案的对比:

Parquet Thrift还有很多优化空间;Parquet在选取的列数小于13列之前,是更快的;此模式相对平坦,且大多数列都被生成了。

  • 还可以采用Predicate Push-Down策略,使得Parquet可以跳过一些不满足过滤条件的数据记录。
  • Parquet存储了一些统计信息,比如记录的chunks,所以在某些场景下,可以通过对这些统计信息进行读取分析,以跳过整个数据块(chunk)。

注:左图为column projection,中图为predicate push-down过滤,右图为组合效果。可以看到很多字段被跳过了,那绝壁可以优化序列化/反序列化的效率。

下图则展示了push-down过滤 + parquet的优化成效:

2.8 结语

感叹:Twitter真是一家伟大的公司!
上述优化手段,集群越大、Hadoop Job越多,效果越明显!

学习笔记:Twitter核心数据类库团队的Hadoop优化经验的更多相关文章

  1. 微信小程序开发:学习笔记[9]——本地数据缓存

    微信小程序开发:学习笔记[9]——本地数据缓存 快速开始 说明 本地数据缓存是小程序存储在当前设备上硬盘上的数据,本地数据缓存有非常多的用途,我们可以利用本地数据缓存来存储用户在小程序上产生的操作,在 ...

  2. springmvc学习笔记(18)-json数据交互

    springmvc学习笔记(18)-json数据交互 标签: springmvc springmvc学习笔记18-json数据交互 springmvc进行json交互 环境准备 加入json转换的依赖 ...

  3. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

  4. MyCat 学习笔记 第九篇.数据分片 之 数值分布

    1 应用场景 Mycat 自带了多套数据分片的机制,其实根据数值分片也是比较简单,其实这个和数据取摸是类似的实现. 优.缺点同上一篇 2 环境说明 参考  <MyCat 学习笔记>第六篇. ...

  5. 《C#并发编程经典实例》学习笔记—3.1 数据的并行处理

    问题 有一批数据,需要对每个元素进行相同的操作.该操作是计算密集型的,需要耗费一定的时间. 解决方案 常见的操作可以粗略分为 计算密集型操作 和 IO密集型操作.计算密集型操作主要是依赖于CPU计算, ...

  6. Hadoop学习笔记1-如何简单布署hadoop

    企业机型配置: 选型标准:普通的,廉价的,标准的(容易替换的),工业化大规模生产的 CPU:支持多核CPU,如2个4核CPU 内存:16G以上,内存越大,常用数据都缓存在内存,提高速度 硬盘:不需RA ...

  7. 【学习笔记】大数据技术原理与应用(MOOC视频、厦门大学林子雨)

    1 大数据概述 大数据特性:4v volume velocity variety value 即大量化.快速化.多样化.价值密度低 数据量大:大数据摩尔定律 快速化:从数据的生成到消耗,时间窗口小,可 ...

  8. NodeJS学习笔记 (15)二进制数据-buffer(ok)

    模块概览 Buffer是node的核心模块,开发者可以利用它来处理二进制数据,比如文件流的读写.网络请求数据的处理等. Buffer的API非常多,本文仅挑选 比较常用/容易理解 的API进行讲解,包 ...

  9. Guava学习笔记:Google Guava 类库简介

    http://www.cnblogs.com/peida/tag/Guava/ Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, cachin ...

随机推荐

  1. Angular动态注册组件(controller,service...)

    使用angular的场景一般是应用类网站 这也意味着会有很多的controller,service,directive等等 正常情况下我们要把这些内容一次性下载并注册,由于文件较多,对首次加载的效率影 ...

  2. ASP.NET操作Cookie

    1.生成Cookie public static void SetDataByCookie(string mainKey, string subKey, string value, string do ...

  3. 【mysql】使用tpcc-mysql进行压力测试

    Tpcc-mysql是percona基于tpcc衍生出来专用于mysql基准测试的产品 ,可以参见 <高性能MySQL第三版> 一.安装 rpm -Uvh http://dl.fedora ...

  4. 详解Winform里面的缓存使用

    缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力.本文主要针对自己在Winform方面的缓存使用做一个引导性的介绍,希望大家能够从中了解一些缓存 ...

  5. QT的QWebView显示网页不全

    最近使用QWebView控件遇到一个问题,就是无论窗口多大,网页都显示那么大,而且,显示不完全,有滚动条 试过使用showMaximized()方法, 还是一样,网上一直说是布局问题,也没说清楚是虾米 ...

  6. NoSQL介绍

    NoSQL(Not Only SQL),是一种非关系型数据库:说到这里,大家需要了解关系型数据库和非关系型数据库的区别,可参考:从关系型数据库到非关系型数据库. NoSQL是以key-value形式存 ...

  7. HTTP详解2-请求、响应、缓存

    1. HTTP请求格式 做过Socket编程的人都知道,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干.HTTP协议传输的消息 ...

  8. pyhon之Tkinter实例化学习

    Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口,位Python的内置模块,直接import tkinter即可使用. 作为实践, 用Tkinter ...

  9. hdu2527哈夫曼编码

    /* Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  10. 【C#】1.算法温故而知新 - 简单的桶排序

    该算法的时间复杂度是O(M+N),M为桶的个数,N为待排序的个数 缺点: 1.不适用于小数 2.当数值过多,太浪费空间,比如数值范围为0~99999,那需申请100000个变量,也就是要写成a[100 ...