阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

大数据中的Java虚拟机优化

64次阅读
没有评论

共计 2894 个字符,预计需要花费 8 分钟才能阅读完成。

导读 Java 基于 JVM 运行的特性使得 Java 程序可以一次编写,多处运行,摆脱分布式集群中不同操作系统和硬件处理框架带来的束缚,使得开发者可以更加专注于代码逻辑的开发。

近年以来,大数据应用取得了长足的进展,各种大数据处理框架也应运而生,并得到了业界的高度认可,如 Hadoop 生态、Spark 系列、Flink、Cassandra、Hive 等等。这类编程模型通常采用分治的思想,将大的数据处理作业拆分为多个小的计算任务,分配到分布式集群中的不同节点中运行,然后将结果汇聚起来,得出最终结果。

由于使用习惯等关系,业内主流的大数据处理框架都采用 Java 语言进行编写。原因在于以下几点:

1、很多程序开发人员对于 Java 语言比较熟悉,使用起来轻车熟路;

2、Java 提供了便捷的自动内存管理机制,避免了用户在处理内存过程中可能出现的问题;

3、Java 基于 JVM 运行的特性使得 Java 程序可以一次编写,多处运行,摆脱分布式集群中不同操作系统和硬件处理框架带来的束缚,使得开发者可以更加专注于代码逻辑的开发;

4、Java 语言拥有成熟的社区和丰富的编程资源,可以实现快速开发,出现问题也可以快速寻求帮助。

大数据中的 Java 虚拟机优化

正是基于这些优点,Java 语言成为了目前最主流大数据编程技术。但是,在实际使用的过程中,开发者们发现了一系列 JVM 相关的性能瓶颈,主要包括以下几个方面:

1、垃圾回收(GC)占用时间长,在一些大数据应用中,GC 时间甚至可以达到总执行时间的 50%;

2、GC 频率高,造成任务执行频繁暂停,应用吞吐率降低,响应延迟升高;

3、GC 算法挤占应用线程 CPU 资源,存在 GC 线程竞争时,大数据应用执行时间增长可达 60%;

4、数据对象在分布式节点间传输时需要序列化和反序列化,在某些大数据应用中,用时占比可达 30%;

5、JVM 冷启动时需要大量的类加载和代码即时编译工作,在应用执行中的用时可达数十秒;

6、JVM 运行和维护需要内存消耗,在内存紧张的情况下,可能因为内存耗尽或内存碎片触发 OOM 错误。

大数据中的 Java 虚拟机优化

总的来说,这些问题的产生,可以归纳为以下一些原因:

1、内存使用压力增大

与普通的 Java 应用不同,大数据应用是“内存密集”型的,应用的内存使用量更大,在大数据处理框架下,JVM 的内存使用压力具体来源于:

(1)大数据应用数据计算和存储产生的大量内存消耗,大量数据在计算过程中需要同时被读取到内存中,而一些应用为了更进一步加快处理速度,将中间数据的聚合和可重用数据也缓存在内存当中,这决定了 JVM 在执行大数据应用时将面对更大的内存使用量;

(2)数据在 JVM 堆内存当中以对象的形式存储需要额外的内存占用,对象在 JVM 当中的数据结构包含了对象头以及对其它对象的引用,而数据本身在对象中的空间占比往往不超过一半。这些对象的外壳伴随着数据缓存在内存当中,也需要占用相当数量的空间;

由于 JVM 垃圾回收机制的原因,会经常触发全局暂停,而这个问题很难通过简单的增减内存大小来解决,如果降低内存大小,GC 的触发频率会增加,对象被扫描和的去的次数增加,应用程序的吞吐量相应降低。可用内存不足还会影响到应用的正常缓存和处理机制,甚至引发内存溢出。而如果提升内存大小,单次 GC 则需要处理更多的数据对象,平均的暂停时间加长,应用程序的最大延迟相应增加。对于周期性标记扫描的 GC 算法而言,还会在最终触发 GC 之前消耗更多 CPU 时序进行不必要的标记。

2、内存使用模式变化

大数据应用中数据在内存当中保留的时间周期与普通应用不尽相同。在传统应用中,堆内存中创建的绝大部分对象在产生之后不久就不再被使用,经典的 GC 算法正是基于这种内存使用模式,将堆内存进行粗粒度的年代划分,绝大部分瞬时对象会在针对年轻代的 Minor GC 当中很快被清理。而大数据应用产生的对象有两种,一种是由控制大数据处理框架运行逻辑的代码产生的,即控制路径对象,它们的内存使用模式一般依旧符合弱世代假设。另一种是输入数据和计算中间数据在大数据处理框架中封装生产的,统称为数据路径对象。这种对象的内存使用模式要更加复杂,它们可能在内存中长时间累积或缓存,也可能在一个迭代轮次后被清理和输出。通常来说,数据路径所创建的对象数量远超控制路径。传统 GC 算法并不能适应大数据环境下内存使用模式的这种变化,原因在于:

(1)当前 GC 算法下,长时间存活的数据路径对象最终都会晋升到老年代中,它们在数次 Minor GC 当中幸存并最终晋升的过程中,需要在内存中多次移动。而对象移动是 GC 循环当中最耗时的部分,每一次移动都意味着内存读写,而内存位置的改变也需要对相关引用的指针进行更新。考虑到数据路径对象的数量极为庞大,整个晋升过程会消耗大量 CPU 时间,触发多次 GC 暂停;

(2)数据路径对象在晋升到老年代之后,在作业执行的时间尺度上,短时间内也不会被回收。传统的 GC 算法不会考虑这些对象的存活时间,在涉及到老年代空间的 MajorGC 或者 Mixed GC 之前还是会整个堆内存空间进行标记扫描,这些标记扫描过程对于长时间存活的数据对象来说是不必要的。当长时间存活对象占用老年代的比例过高,每次传出较大代价的 Major GC 就只能回收有限大小的空间,可能造成 GC 频繁触发,部分缓存数据被迫转移到磁盘,甚至出现 OOM 错误,浪费大量的 CPU 时间和全局暂停时间,影响到应用执行效率。

大数据中的 Java 虚拟机优化

3、JVM 与上层框架存在隔阂

大数据处理框架将计算任务分配到各个执行器 JVM 节点之后,并不会干预 JVM 的具体执行过程,每个执行器 JVM 独立运行,并不感知分布式集群中其它执行器 JVM 的执行情况,作业的整体进度,以及集群和节点的内存资源使用情况,只是根据自身的运行状态作出触发 GC,调整堆内存,进行代码即时编译等决策,而这些决策从历史和全局的角度上观察可能并不是最优的。原因在于:

(1)JVM 不清楚任务执行产生的数据对象特征,例如对象数量、内存占用大小、生命周期等,只能根据弱世代假说,对所有对象进行统一的管理。由于大数据应用产生的大量对象长时间存活,JVM 的内存管理效率会受到严重影响,而这些对象本可以通过大数据框架对用户代码和数据流的全局静态分析进行甄别。

(2)大数据处理框架并不考虑 JVM 具体的内存管理机制,将所有 JVM 节点的内存当做连续的全局地址空间,但是实际上 JVM 在 GC 算法下对堆内存采取分代管理,存在非连续区域,对象在内存中离散分布,另外大数据处理框架在采用全局地址空间的物理架构下,可能产生大量跨节点对对象引用,给 JVM 的 GC 任务带来了远程内存访问的负担。

(3)大数据处理框架下的 JVM 之间不清楚彼此的运行情况,如果大数据操作需要在各个 JVM 之间同步,由于 JVM 独立进行 GC 决策,大数据操作的执行就可能被不同的 JVM 的 GC 连续打断,另外由于互相不感知,处于同一物理节点的 JVM 之间可能内存资源分配不合理,而大数据框架在相关问题上缺少统筹协调。

因此,开发者们需要针对这些问题产生的原因,进行针对性优化。我们下次文章将会继续讨论这个问题。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-24发表,共计2894字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中