如何处理大数据性能问题?

发表于:2017-2-20 09:53

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:译 者:yonger    来源:51Testing软件测试网原创

  下一代开源大数据框架如spark和Flink的目标是达到大规模并行处理数据库如Netezza那样的性能和良好的用户体验
  由于所有主流的大数据框架(Hadoop,spark,Flink)使用JVM,所有他们都有着两个JVM限制:
  1、Java对象消耗的内存远大于对象中所有属性的大小
  2、Major GC 的停顿会使得性能下降,尤其是当你尝试缓存更多的数据(Java对象)以便后期对数据进行纯内存处理
  所有Flink,Spark,Hadoop为高性能引入的工程技术主要目的就是为了尽可能的减少这两方面的影响.本文将为你展示这些技术。
  在所有性能改进的之外,Alexey Grishchenko所写的如下blog给了我们一个清晰的提醒,虽然基于Java的大数据框架在性能方面已经有很大提升,但是要追上大规模并行处理系统的性能还有很长一段路要走
  性能的80/20原则
  不是所有操作所需要的开销都是一样的,极少数的操作产生了很高的性能开销,许多大数据框架常用操作组合是:
  1、压缩vs不压缩-这直接影响到数据被读出和写入的速率,不同的压缩方式/算法消耗的cpu资源差异很大
  2、排序-大数据处理基本都会有"reduce"操作,而排序在map-reduce处理方式中则是"reduce"阶段的关键。由于"join"操作会依赖于"reduce",所以对key的排序也会关系到"join"的操作上
  3、清洗-"reduce"阶段第二个最重要的操作就是清洗了,清洗操作也是关联操作的关键
  4、关联-只有map阶段的job通常有很好的性能.但当有reduce阶段的时候性能会变成一个需要考虑的重要因素。一个reduce操作包含了关联,在只有map阶段的任务中可以使用广播关联,但广播关联通常在关联的一端数据量足够小的时候才用,这个很小的数据集被广播到所有节点,由一个hashmap的数据结构来维护同时由关联键来索引。另外一端大一点的数据集通过使用关联键在这个内存中的hashmap中查找相应的记录。当只有map阶段时,即使两端数据集都比较大也可以按照关联键来排序,Pig框架就是充分利用了这一点,被称为"merge-joins"技术,它会把两边的数据集都在lock-step中遍历,然后在map阶段中关联起来(这里实际上有一个预先索引的过程)。当然有关联键进行自然排序对数据集是很少见的,在关联大数据集的时候reduce操作还是必不可少的。
  搞定上面的这些问题是使得大数据处理效率变得更快的关键。
  性能约束和JVM特征
  就像前面提到的,Java在性能方面引入的两个约束因素:
  1、Java对象的存储开销不容小觑
  2、使用大量生存周期很短的对象会使得吞吐量性能下降,因为大量的时间会花在Major GC上
  只在JVM堆栈上操作处理大数据很容易导致内存溢出错误,这会使得JVM进程被杀死退出(不像其他错误可以被处理).这是大数据应用中最常见的一个性能问题.
  比如,在一个有许多记录但是只有少数键值对能够发生关联的不均衡数据集中,当所有的键值都保存在内存中时reduce操作会失败
  从索引技术可以避免在reduce阶段时把所有的键值放到内存中,图像应用就是属于这类应用中的一种.
  这就是大数据框架在使用内存时小心谨慎的重要原因了,比如磁盘溢出技术.这虽然会影响性能,但是会使得框架足够健壮来处理不同的负载.
  比如,Pig框架会把数据保存在磁盘上,DataBag接口的实现及其广泛的应用在Pig中,当tuples的数量达到一个预先定义的值时会把数据刷到磁盘上(默认是20000)
  JVM 存储开销
  在Java堆栈中一个典型的对象存储由如下组成-
  1.对象头-只有几个字节用作维护信息.Hotspot 版本的VM使用8个字节来表示一个普通对象的头,另外再使用4个字节来表示数组对象的长度
  2.原始类型-原始类型也需要字节来存储.比如boolean类型需要1个字节,char需要两个字节,int需要4个。
  3.引用类型存储-引用类型占用4个字节
  4.空占位符-每个对象存放时总字节数是8的倍数,所有这中间总是有空的占位符
  如图1所示,一个Java类对象的实例包含了一个原始类型boolean实例所占用的8个字节用作头,另外一个字节表示boolean实例本身,剩余7个字节就会被空占位符填满。
   
  图1:一个只有一个boolean实例变量的java类在内存中的占用情况
  这个例子证实了一个普通java对象很大的存储开销,并且随着如hashmap 和list这样复杂对象变得非常大
  JVM 存储开销影响序列化和反序列化
  在大数据范围内发生如下情形时你肯定需要序列化和反序列化:
  1、Mapper输出结果到本地磁盘
  2、Mappers从本地磁盘读出数据来做map端的排序
  3、Reducers从mapper 节点上获取排序和清洗好的结果
  在上面的每种情形中,实际的数据量都比原始字节表示的要多很多
  Java 对象的存储开销影响到内存如何有效的使用分级缓存。即使所有你想要的数据在内存中,L1/L2/L3级别的缓存也不可能大到能装下这些所有的数据,这也会使得缓存在过渡的交换之中从而降低性能。
  JVM 存储开销影响GC
  JavaGC最关键的是要更多的对象在年轻代时就被收集. Java堆栈被划分为两个区域,年轻代和年老代。一般来说年轻代占用整个堆栈空间的20%,而年老代占用了剩余的80%。当一个对象第一次被创建时,他们被分配在年轻代,当年轻代满了的时候,minorGC就会执行。在这个过程中不再被引用的对象就被清除掉,剩余的还在被引用的就移到年老代。当年老代被填满时,major GC最终就会发生。Major收集算法会遍历在图中的每个对象,从老年代中回收内存。注意这只是非常简单的描述了GC的过程,更加详细的了解可以上官方网站查找。
   ... ...
   查看全文内容,请点击下载:http://www.51testing.com/html/15/n-3715215.html
版权声明:51Testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号