记一次生产大对象及GC时长优化经验

最近在做一次系统整体优化,发现系统存在GC时长过长及JVM内存溢出的问题,记录一下优化的过程

面试的时候我们都被问过如何处理生产问题,尤其是线上oom或者GC调优的问题更是必问,所以到底应该如何发现解决这些问题呢,用真实的场景实操,更具有说服性。

一:如何发现

1.发现经过如下,首先pass服务的pod不停自动触发重启,因为pass配置系统health接口访问超时,通过系统的grafana监控发现二点异常,1.GC时间大量超时40s+,2.堆内存达到24G(也是我们配置最大的内存,触发OOM)
监控如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

所以我们可以梳理出以下链路

在这里插入图片描述

二:如何优化

1,我们dump系统的在业务低谷期的内存情况,看看业务的低谷期时系统中是否存在不合理的大对象,如果有肯定是要优化掉的,因为业务高峰期会肯定分配一些局部变量大对象,需要给他们腾空间,可以理解先优化最简单的,再优化运行中产生的,结果还真的发现在这个GoodsSetNormalGoodsCache类的中cache对象,存了一个近1200W(并且随业务持续增长)的内存大对象,用于全局skc分站点上下架的缓存信息
dump如下:

在这里插入图片描述
在这里插入图片描述

1.巧用redis优化大对象

优化策略:大家很容易想到将map由JVM内存移入redis的hash结构中存储(面试过很多人都说把oom的对象直接剔除,其实很多时候我们处理的场景是不允许删除,如果直接移除可以解决问题,我相信大部分开发就不会加载部分大对象进入内存,加载进去必然是为了快速查询全量数据),存储结构如下图:在这里插入图片描述

但是实际上线后,生产环境中又遇到新的问题,这个keyQPS很高达到几万qps,因为业务逻辑增量任务需要不停且大量的查询skc在不同站点的上下架信息,必然也导致这个key是一个热key
如图:(注意这里的元素个数是900w,因为在做初始化)
在这里插入图片描述

当然,系统中出现热key不是问题,问题在于redis也是个大key,导致数据产生倾斜,最高的节点和最低的节点相差一个G的数据,并且我们联系运维同学重平衡也无法生效,于是我们思考应该如何从开发角度解决这个问题,究其根本原因是key太大,存储的数据太多,那么我们的场景并没有统计功能,也就是说这个key我们可以拆开,降低单个key的大小,QPS自然也就降低下去了。
如图:

在这里插入图片描述

优化后重新写入数据,我们可以清晰看出倾斜的数据节点恢复正常了

在这里插入图片描述

2.巧用布隆过滤器优化大对象

上面我们dump了系统空闲水位的大对象也进行优化了,那么代码运行时产生的局部大对象,我们的优化思路时什么呢,正好我们的代码中,有一个很大的set存储商品集(可以理解为一些条件的skc集合)全量的skc,用于商品更新的时候和上一次数据进行对比产生增量,你可以理解为一个集合数据要更新,那么更新后产生了哪些新增的数据我们怎么知道呢,肯定是存了一份之前的历史数据,那这个数据就装在set,现在的问题是需要更新的商品集很多,所以set也很多,导致set的大对象的频繁创建和回收,触发GC压力很大

我们的优化思路是,1.首先这个set不是用于常驻查询,换句话说就不是热key,用于临时操作,那么放在redis就得不偿失了,当然了也是可以做到,2.这个set的作用主要用于存储全量进行判断是否存在,但是问题在于内存开销大,有没有一种结构可以内存占用小又可以判断元素是否存在,这个容器就是即布隆过滤器

我们利用guava的布隆过滤器写个简单的程序说明优化流程,以及内存占用对比

public class BloomFilterUtils {/*** builderBloomFilter** @param size 长度* @param fpp  误判率* @return*/public static BloomFilter<String> builderBloomFilter(int size, double fpp) {BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), size, fpp);return bf;}public static void main(String[] args) {HashSet<String> set = new HashSet<>();ArrayList<String> list = new ArrayList<>();//存储1000w元素,误判率百万分一,即10个误判BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 1000 * 10000, 0.0000001d);for (int i = 0; i <= 1000 * 10000; i++) {String skc = UUID.randomUUID().toString();set.add(skc);list.add(skc);bf.put(skc);}System.out.println("布隆内存占用 = " + RamUsageEstimator.humanSizeOf(bf));System.out.println("set 内存占用:" + RamUsageEstimator.humanSizeOf(set));System.out.println("list 内存占用:" + RamUsageEstimator.humanSizeOf(list));}
}

运行结果:
在这里插入图片描述

可以看出1000w-skc(字符串模拟skc)的存储,set占用最高,因为要记录额外的信息(hashcode)用于判重,list结构其次,而布隆仅仅为35分之一(受误判率影响),当然业务场景要允许存在个别误判

三:总结

昨晚上述优化后,我们成功将gc时间降低到5s内
在这里插入图片描述

  1. 对于jvm大对象的优化,我们要在于要明确大对象为什么会产生,结合业务和相关技术,采取最优的方式,既优化了大对象,也不损失性能甚至还能提速,而不是八股文中的直接移除一刀切
    2)oom或者gc时间增长的问题,并不是出现问题才排查修复,我们更应该关注和监控系统空闲时水位线,不要让内存慢慢的泄漏,从而导致出现压死骆驼的最后一个稻草时,我们才能发现,那样就太慢了

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Dockerfile搭建LNMP环境

准备工作 #关闭防火墙和防护机制 systemctl stop firewalld systemctl disable firewalld setenforce 0 docker network create --subnet172.18.0.0/16 --opt "com.docker.network.bridge.name""docker1" mynetwork#设置自定义网络模式&#xff0c;模…

【多线程案例】设计模式-单例模式

1.单例模式 什么是单例模式&#xff1f; 所谓单例&#xff0c;即单个实例。通过编码技巧约定某个类只能有唯一一个实例对象&#xff0c;并且提前在类里面创建好一个实例对象&#xff0c;把构造方法私有化&#xff0c;再对外提供获取这个实例对象的方法&#xff0c;&#xff0…

CSS 之 table 表格布局

一、简介 ​ 除了使用HTML的<table>元素外&#xff0c;我们还可以通过display: table/inline-table; 设置元素内部的布局类型为表格布局。并结合table-cell、table-row等相关CSS属性值可以实现HTML中<table>系列元素的效果&#xff0c;具有表头、表尾、行、单元格…

JS之同步异步promise、async、await

promise异步操作 Promise是异步编程的一种解决方案 JavaScript异步与同步解析 学习promise前我们先来了解下什么是异步&#xff1f; 基本概念&#xff1a; 消息队列中的任务分为宏任务与微任务;调用栈也可以称为主线程 首先我们要知道js是单线程语言&#xff0c;也就是说…

网工内推 | 技术支持工程师,厂商公司,HCIA即可,有带薪年假

01 华为终端有限公司 招聘岗位&#xff1a;初级技术支持 职责描述&#xff1a; 1、通过远程方式处理华为用户在产品使用过程中各种售后问题&#xff1b; 2、收集并整理消费者声音&#xff0c;提供服务持续优化建议&#xff1b; 3、对服务中发现的热点、难点问题及其他有可能造…

Linux CentOS8安装gitlab_ce步骤

1 下载安装包 wget --content-disposition https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/8/gitlab-ce-15.0.2-ce.0.el8.x86_64.rpm/download.rpm2 安装gitlab yum install policycoreutils-python-utilsrpm -Uvh gitlab-ce-15.0.2-ce.0.el8.x86_64.rpm3 更新配…

基于Qt C++的工具箱项目源码,含命令行工具、桌面宠物、文献翻译、文件处理工具、医学图像浏览器、插件市场、设置扩展等工具

一、介绍 1. 基本信息 完整代码下载地址&#xff1a;基于Qt C的工具箱项目源码 TBox是一款基于Qt C的工具箱。用户可以自行选择安装所需的工具&#xff08;以插件的形式&#xff09;&#xff0c;将TBox打造成专属于自己的效率软件。TBox基本界面展示如下&#xff1a; 2. 使用…

RustDay03——记录刷完Rust100题

刷了两三天Rust&#xff0c;终于把Rust100题刷完了&#xff0c;小小记录一下 明天白天的时候重开账户开题写答案

界面组件DevExpress WinForms v23.2新功能预览 - 增强MVVM相关功能

本文主要描述了DevExpress WinForms即将在几个月之后发布的v23.2中包含的新功能&#xff0c;持续关注我们获取更多最新资讯哦~ DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用…

【算法优选】 二分查找专题——贰

文章目录 &#x1f60e;前言&#x1f332;[山脉数组的峰顶索引](https://leetcode.cn/problems/peak-index-in-a-mountain-array/)&#x1f6a9;题目描述&#xff1a;&#x1f6a9;算法思路&#x1f6a9;代码实现&#xff1a; &#x1f334;[寻找峰值](https://leetcode.cn/pro…

技术先驱视角:长城汽车工程师揭秘Hi4技术的无限潜力

文 | 智能相对论 作者 | 沈浪 汽车行业的变革正在回归平衡和理性&#xff0c;混动市场再度掀起新的浪潮&#xff0c;以Hi4技术为代表的混合动力解决方案备受瞩目&#xff0c;并爆发出无限潜力。 日前&#xff0c;工信部等七个部门联合印发了《关于汽车行业稳增长工作方案&am…

ceph 分布式存储与部署

目录 一、存储基础&#xff1a; 1.单机存储设备&#xff1a; 2. 单机存储的问题&#xff1a; 3. 商业存储解决方案&#xff1a; 4. 分布式存储&#xff1a; 5. 分布式存储的类型&#xff1a; 二、Ceph 简介&#xff1a; 三、Ceph 优势&#xff1a; 四、Ceph 架构&#xff1a…