Uber 提升 Presto 集群稳定性的 GC 调优方法

news2024/11/25 20:24:19

Presto at Uber

Uber 利用开源的 Presto 查询各种数据源,无论是流式还是归档数据。Presto 的多功能性赋予我们做出基于数据的明智商业决策的能力。我们在两个地区运行了大约20个 Presto 集群,总共超过10,000个节点。我们有大约12,000个每周活跃用户,每天运行约500,000个查询,从 HDFS 读取约100 PB 的数据。现在,Presto 被用于查询各种数据源,如 Apache Hive、Apache Pinot、AresDb、MySQL、Elasticsearch 和 Apache Kafka,这是通过其可扩展的数据源连接器实现的。

3d958aecdc407bb06c29ac8ceb2c9e62.png

我们选择的集群类型可以满足各种请求,无论是交互式的还是批处理的。交互式工作负载适用于等待结果的仪表板/桌面用户,而批处理工作负载是根据预定的时间表运行的计划任务。我们的每个集群都根据其机器类型进行分类。我们的大部分集群由配备了超过300 GB 堆内存的大型机器组成,而其他集群由配备了不到200 GB 堆内存的小型机器组成,我们根据每个集群的大小和构成其的机器类型调整了每个集群的并发性。

每周,我们都会在所有生产集群中进行内存碎片优化活动。尽管我们一直在改善内存碎片问题,但我们仍然经常遭受全垃圾收集(长时间的暂停)的困扰,偶尔还会出现一些内存溢出错误。为了让你了解问题的严重性,我将向你展示 Presto 全 GC 的累计数量:

4adcbb490129541c944b3642700cdddc.png

每天 Presto Full GC 发生次数

G1GC 垃圾回收器简述

G1GC 是一种垃圾收集器,它的目标是在吞吐量和延迟之间找到平衡。G1 属于分代垃圾收集器,这和新型的并发垃圾收集器(如 Shenandoah,ZGC 等)有所不同。所谓的"分代",是指内存被分成短生命周期和长生命周期的对象。

首先,我们需要明白有两种类型的内存:栈内存和堆内存。栈内存的分配成本很低,只需要移动一个指针的位置即可,因此每当我们调用一个函数时,我们就减少栈指针的位置(栈是向下增长的),一旦我们完成了该函数,我们只需将指针位置增加,就完成了分配和回收,每个操作只需要一个语句。然而,堆内存的分配/回收则稍微复杂一些。对于 G1GC,其分配方式类似于栈内存,我们只需要移动一个指针的位置,但是回收则需要运行 GC。

在 Java 中,所有的对象都是在堆内存上分配的,那么我们在栈内存上分配的是什么呢?答案是,指向堆内存上对象的“指针”。然后对于堆内存,G1 将其划分为名为“区域”的小块。

G1 的目标是在堆内存上至少划分出 2,048 个区域。

1b1bae7b66adcccd2aab6ee5c094d59c.png

Heap 被分成一个一个区域

每个区域的大小是如何确定的呢?这主要取决于你的堆内存大小,其范围可以在1-32 MB之间。而这个具体的大小,由JVM决定,以确保我们至少有2048个这样的区域。

每个区域可以是年轻代(新生代),老年代(老生代),或者是还未分配的空闲区域。

7ae023da1c063a4a907eda723cc78f14.png

再深入一点,年轻代又被细分为 Eden 和 survivors 两部分。Eden  是所有新生成的对象分配的地方。对于 survivors 区域,它会创建两个不同的空间。这样做的原因何在?因为年轻代清除内存的方式是通过在不同区域之间复制对象,所以它需要一个空的幸存者区域来复制内存。

具体的过程是这样的:每当我们创建一个新的对象,这个对象就会在 Eden 区域被分配。当垃圾收集(GC)运行,如果这个对象还没有被回收,它就会被复制到 Survivor0 区域。下一次垃圾收集再次运行,如果这个对象仍然没有被回收,它就会被提升到 Survivor1 区域。这样,它就会在两个 survivors 区域之间来回复制,直到最后被提升到老年代。

简单总结一下,年轻代通过复制机制来释放内存。那么,我们什么时候会把对象分配到老年代呢?主要有两种情况:

  • G1设定了一个年龄阈值。每次年轻代的对象被复制,我们就会增加它的年龄。一旦达到这个阈值,它就会被复制到老年代。

  • 每个区域的大小在1-32 MB之间。任何大小达到或超过区域大小一半的对象,都会直接分配到老年代。G1称这种对象为巨大对象。

那么,G1是如何清理老年代的呢?它采用了一种叫做“并发标记和清扫”的算法。这是一个从根对象(如线程栈,全局变量等)开始的图遍历,遍历所有仍然被引用的对象。需要特别说明的是,G1使用了STAB(快照在开始时)策略,所以在它开始清扫后新生成的对象都会被认为是存活的,无论它的实际存活状态如何。一旦清扫完成,G1就能知道哪些对象仍然存活,那些已经死亡的对象可以在接下来的混合收集中被清理。

什么是混合收集?实际上,混合收集是一种包括老年代区域在内的年轻代收集方式。它会在另一个老年代区域中复制仍然存活的对象。这个过程对于减少内存碎片化至关重要。

那么,每个组件(Eden, survivor, old gen 等)的大小是由谁决定的呢?实际上,堆内存的大小是会变化的,虽然有一定的限制。比如,年轻代的大小只能占总堆内存的5-60%。

今天的讨论不需要深入到更高级的G1GC主题,所以让我们从我们在Uber所做的开始。

G1GC at Uber

当 Uber 开始更多地使用 Java 时,我们采用的是 OpenJDK 8。通常情况下,我们需要调整的唯一选项就是 -XX:InitiatingHeapOccupancyPercent=X。这个阈值决定了 G1 是否应该启动并发标记和清除的过程。

它的默认值是45%,这通常会导致 CPU 使用率的提高,因为任何使用缓存的服务最终都会超过这个阈值,并且会不断触发它。例如,服务 A 将所有用户数据存储在内存中,这导致老年代占据了堆内存的大约60%。这样一来,45%的阈值就总是会被触发。

那么我们应该如何进行调整呢?

  • 启用垃圾收集日志和垃圾收集指标

  • 在混合收集后寻找老年代利用率的最高点

  • 选择一个比峰值稍高的值——通常比峰值高出5-10%

但是,要注意,Presto 服务器现在运行在 JDK 11 上。我们怎么调整它们呢?这是我们首次尝试调整这个版本。为什么它会有所不同呢?Java 引入了动态 IHOP(InitiatingHeapOccupancyPercent)。因此,我们不再有一个固定的45%的默认值,而是有一个可以随时变化的值,这个值只能在垃圾收集日志中找到。

JDK 11 调优

动态 IHOP 是怎么计算出来的呢?它是通过将年轻代的当前大小和一个自由阈值(基本上是这个思路,但实际上使用的是一个稍微复杂一点的公式)相加得出的。这个自由阈值默认是总堆的 10%,作为一个缓冲区,让垃圾收集(GC)能够顺利完成(请记住,并发标记和清扫是和你的应用程序同时运行的)。

我们的操作流程如下(每一步之间,我们都会等待 1-2 周,以便有足够的数据来验证我们的实验结果)。我们先在一个集群上试验以下步骤,以避免影响到所有的用户。

增加更多的 GC 指标

我们没有年轻代和老年代的使用率数据,所以我们无法轻松地了解我们的使用率的历史情况。

将最大年轻代大小从 60% 降低到 20%

我们注意到年轻代有几次扩大的情况(总堆的 50%)。这导致了 GC 暂停时间过长,以及并发标记需要更长的时间才能重新运行。如果我们还在进行混合收集,那么并发标记就无法运行。

结果如何呢?

  • GC 暂停时间有所改善。

  • 并发标记仍然不理想。这是因为我们把最大大小减少了 40%,把这部分空间让给了老年代,导致并发标记还是开始得太晚。

将 Free space 从 10% 增加到 35%,将 Heap waste 从 5% 降低到 1%

首先,让我们来谈谈 Heap Waste 百分比。这个调整选项默认是 5%,告诉 G1 只有当垃圾超过总堆的 5% 时,才能释放任何垃圾。为什么这么做呢?这是为了避免在混合收集过程中出现长时间的 GC 暂停。当我们进行并发标记时,G1 会根据它们的使用率对老年代的区域进行排序,优先选择那些有更多空闲空间的区域,因为它们复制到新区域的速度更快。

对于我们的 300G 集群来说,这意味着有 15G 的空间永远不会被清理。我们决定根据过去的经验,将这个数值降低到 3G(-XX:G1HeapWastePercent=1)。

对于 free space,我们分析了几个 GC 日志,发现在混合收集(mixed collections)后,使用率保持在 20-35%。因此,20% 的最大年轻代加上 35% 的 free space 会给我们一个 45% 的阈值(100-(35+20)%)。有了这个配置,我们至少有 10% 的缓冲区(35 到 45%)可以用来清理一些垃圾。

结果如何呢?

  • 1% 的 Heap Waste 似乎太多了,我们开始看到大于 1s 的长暂停。这个改变是有帮助的,因为有了 GC 日志,我们能够确定长暂停开始发生是在混合收集试图从 2% -> 1% 的垃圾时。

  • 35% 的 free space 表现良好。全 GCs 减少了(~80% 对于这个集群)。

将 free space 从 35% 增加到 40% 和将 Heap Waste 从 1% 增加到 2%

结果是:

  • 2% 的 Heap Waste 给我们提供了额外的 9G 空间,对延迟的影响也很小(~50-100ms vs. 1-1.5s with 1%)。

  • 40% 的 free space 比 35% 的表现稍好一些,但我们并没有得到太多的提升(85-90% vs. 80%)。我们决定不再增加,以避免抖动。

在另一个集群上尝试相同的调整选项

我们在一个新的集群上测试了相同的配置,并在尝试所有的之前验证了行为,以了解影响。我们决定抓取过去几周内 Full GCs 最多的集群。部署后的 24 小时,我们就能看到影响:

12cb6e00991f501a4725f2145b73df37.png

以前,只过了几个小时,我们就开始看到 Full GCs,但是在这些改变后,我们没有看到任何 FGC。

总结

在对上述调优进行了几周的测试后,我们决定在所有集群中统一使用这些标志。当这些标志被添加或更新后,所有的集群都能以最小的内部 OOM 错误达到最佳性能。这项改变提高了 Presto 集群的稳定性,减少了因 OOM 错误而需要重新执行的查询,从而提升了 Presto 集群的整体性能。我们最终调优中使用的标志包括:

  • -XX:+UnlockExperimentalVMOptions

  • -XX:G1MaxNewSizePercent=20

  • -XX:G1ReservePercent=40

  • -XX:G1HeapWastePercent=2

这些调优参数是专门针对 Uber 中 Presto 的使用场景而设定的,经过多轮调优后最终确定。我们预期,每个组织的参数设置可能会因其特定的工作负载而有所不同,需要根据具体情况进行逐个调优。启用这些标志后,虽然我们会看到更频繁的垃圾收集,但它们使我们的 Presto 集群更加稳定,减轻了负责人的值班压力。

对于我们所有的集群,我们观察到了以下的影响:

79f852f83d90fd16bf95563514988677.png

3be51ad62d503d1d71db40179f2d8e53.png

后续规划

我们大部分的垃圾回收优化工作都集中在面向产品的应用上,对于存储应用的优化并未给予足够的关注。因此,我们计划将调优工作扩展到 Uber 提供的其他解决方案上。这将是一次有趣的学习过程,因为存储应用通常会使用大量的堆内存,这与我们通常优化的对象有所不同。一旦我们收集到更多的数据,我们会与社区分享。

在 Presto 上进行的垃圾回收优化工作就是一个很好的例子,它向我们展示了优化垃圾回收如何提升系统的整体性能和稳定性。我们接下来的工作重点将是进一步优化 Presto 集群的垃圾回收,特别是在那些性能较弱且仍然遇到全垃圾回收问题的机器上,以提高系统的整体稳定性。

所有列出的优化措施都是专为 Uber 中的 Presto 部署设计的,不能直接应用到其他服务上。列出的参数只是为了演示我们在优化过程中使用了哪些参数。此外,我们还会提出一些最佳实践和指导原则,这些原则可以根据 Uber 的存储应用的一般使用情况来使用,作为我们优化的起点。这将使我们有能力改进所有的存储应用,从而提高整体的稳定性和性能。

本文翻译:https://www.uber.com/en-HK/blog/uber-gc-tuning-for-improved-presto-reliability/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1805876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python010】获取任意多边形区域内的经纬度点并可视化

1.熟悉、梳理、总结项目研发实战中的Python开发日常使用中的问题、知识点等,如获取任意多边形区域内的经纬度点并可视化,找了N篇文章没发现有效的解决方案。 2.欢迎点赞、关注、批评、指正,互三走起来,小手动起来! 3.欢…

Here Doucument

一、Here Document概述 1.概念 使用I/0重定向的方式将命令列表提供给交互式程序 标准输入的一种替代品 2.语法格式 命令 <<标记 标记 3.注意事项 标记可以使用任意合法字符&#xff08;通常为EOF&#xff09; 结尾的标记一定要顶格写&#xff0c;前面不能有任何字符…

【爬虫实战项目一】Python爬取豆瓣电影榜单数据

目录 一、环境准备 二、编写代码 2.1 分页分析 2.2 编码 一、环境准备 安装requests和lxml pip install requests pip install lxml 二、编写代码 2.1 分页分析 编写代码前我们先看看榜单的url 我们假如要爬取五页的数据&#xff0c;那么五个url分别是&#xff1a; htt…

关于智慧校园建设的几点建议

随着科技的迅猛发展&#xff0c;智慧校园建设已成为现代教育的重要组成部分&#xff0c;对于提升教育质量、改善学生学习环境具有重要意义。为此&#xff0c;我提出以下几点建议&#xff0c;以帮助智慧校园建设更加有效和可持续。 首先&#xff0c;应注重基础设施建设。智慧校园…

java 实现导出word 自定义word 使用aspose教程包含图片 for 循环 自定义参数等功能

java 实现导出word 主要有一下几个知识点 1&#xff0c;aspose导入 jar包 和 java编写基础代码下载使用 aspose-words jar包导入 aspose jar 包 使用 maven导入java代码编写 2&#xff0c;if判断 是否显示2&#xff0c;显示指定值3&#xff0c;循环显示List 集合列表 使用 fore…

【CTF MISC】XCTF GFSJ0290 reverseMe Writeup(图像处理)

reverseMe 暂无 解法 导入 Photoshop。 水平翻转&#xff0c;得到 flag。 Flag flag{4f7548f93c7bef1dc6a0542cf04e796e}声明 本博客上发布的所有关于网络攻防技术的文章&#xff0c;仅用于教育和研究目的。所有涉及到的实验操作都在虚拟机或者专门设计的靶机上进行&#xf…

住宿管理系统 java+jsp+web三件套

文章目录 1、简要介绍2、数据库设计3、中间遇到的困难一、数据问题二、文件问题 4、项目 写了将近3周&#xff0c;人都写麻了 记录下&#xff0c;第一个 ss 代码 仅仅使用了layui作为前端UI框架&#xff0c;因为另一个项目用的也是他&#xff0c;感觉一些组件比较好用 后端是j…

Leetcode:三数之和

题目链接&#xff1a;15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; 普通版本&#xff08;排序 双指针法&#xff09; 分析&#xff1a; 1、我们可以通过三个循环嵌套找到符合题目要求的三元组组合 2、但由于题目要求中的三元组i、j、k并不要求连续&#xff0c;所以会…

大模型的发展历程

1、早期模型的探索与局限性 1.1早期模型的探索与局限性 从早期的符号逻辑到现代的深度学习 1 模型&#xff0c;AI 领域经历了数十年的探索和迭代&#xff0c;为后续突破打下了坚实基础。随着大数据的发展和 AI 计算能力的爆炸式增长&#xff0c;深度学习模型的崛起显得尤为突出…

Spring运维之业务层测试数据回滚以及设置测试的随机用例

业务层测试数据回滚 我们之前在写dao层 测试的时候 如果执行到这边的代码 会在数据库 里面留下数据 运行一次留一次数据 开发有开发数据库&#xff0c;运行有运行数据库 我们先连数据库 在pom文件里引入mysql的驱动和mybatis-plus的依赖 在数据层写接口 用mybatis-plus进…

使用Python在Word中创建和提取表格

目录 安装Python Word库 使用Python在Word中创建预定义行和列的表格 使用Python在Word中动态创建表格 使用Python在Word中提取表格数据 Word 文档中的表格是一种强大且灵活的数据组织和展示工具&#xff0c;它能将信息以行和列的形式有序地排列&#xff0c;使文档内容更加清…

SQL Developer迁移第三方数据库单表到Oracle

在SQL Developer中&#xff0c;除可用Migration Wizard迁移第三方数据库到Oracle外&#xff0c;单表的迁移可以用Copy To Oracle ...菜单。右键单击源表即可。 本例的源表为MySQL数据库employees中的表&#xff1a;departments。 Options页面&#xff1a;指定目标库&#xff…

如何将 Windows图片查看器的背景颜色改成浅色(灰白色)?

现在大家基本都在使用Win10系统&#xff0c;我们在双击查看图片时&#xff0c;系统默认使用系统自带的图片&#xff08;照片&#xff09;查看器去打开图片。图片查看器的背景色默认是黑色的&#xff0c;如下所示&#xff1a;&#xff08;因为大家可能会遇到同样的问题&#xff…

pxe自动装机与无人值守

一、pxe与无人值守 pxe&#xff1a;c/s 模式&#xff0c;允许客户端通过网络从远程服务器&#xff08;服务端&#xff09;下载引导镜像&#xff0c;加载安装文件&#xff0c;实现自动化安装操作系统。 pxe的优点&#xff1a; 1、规模化 同时装配多台服务器&#xff08;20多&…

Hive知识体系保姆级教程

一. Hive概览 1.1 hive的简介 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能。 其本质是将SQL转换为MapReduce/Spark的任务进行运算&#xff0c;底层由HDFS来提供数据的存储&#xff0c;说白了h…

【wiki知识库】06.文档管理页面的添加--前端Vue部分

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、&#x1f525;今日目标 二、&#x1f43b;前端Vue模块的改造 BUG修改 1.wangeditor无法展示问题 2.弹窗无法正常关闭问题 2.1 添加admin-doc.vue 2.1.1 点击admin-ebook中的路由跳转到admin-doc 2.2.2 进入…

【DrissionPage】Linux上如何将https改为http

最近有个老板找我做一个自动化的程序&#xff0c;要求部署到Linux上 这是一个http协议的网站&#xff0c;chrome在默认设置下&#xff0c;会将http的网站识别成不安全的内容&#xff0c;然后自动将http转化成https访问 但是&#xff0c;这个http的网站它的加载项里既有http的…

Java | Leetcode Java题解之第132题分割回文串II

题目&#xff1a; 题解&#xff1a; class Solution {public int minCut(String s) {int n s.length();boolean[][] g new boolean[n][n];for (int i 0; i < n; i) {Arrays.fill(g[i], true);}for (int i n - 1; i > 0; --i) {for (int j i 1; j < n; j) {g[i]…

Centos X系统yum安装mysql数据库

安装之前需要将系统自带的mariadb-libs软件包删除。 检查是否存在mariadb-libs包。 yum list installed|grep mariadb-libs 删除mariadb-libs包 yum -y remove mariadb-libs 声明&#xff1a; 系统&#xff1a;CentOS-7-x86_64-DVD-2009 安装为最小化安装&#xff0c;没…

[线程与网络] Java虚拟机常考面试题(线程与网络完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…