当前位置: 首页 > news >正文

使用ArrayList.removeAll(List list)导致的机器重启

背景

先说一下背景,博主所在的业务组有一个核心系统,需要同步两个不同数据源给过来的数据到redis中,但是每次同步之前需要过滤掉一部分数据,只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。

由于是两个数据源,虽然拿到数据后存数据的代码能共用,但是从数据源拿数据由于协议不同所以还是需要分开写,就安排了两位同事完成这个任务。

重启现象

项目上线大半年,线上运行一直很平稳,突然在某一天ops开始报警该系统的两台机器一直在重启,cpu也一直报警,线上cpu监控如下所示:

机器也处于不断重启中:

两台机器表现几乎一致,于是马上重启一台机器,同时联系ops运维同学帮助临时扩容机器,另外一台机器抓取一下当时的运行详情。直接用下面的火线图更明显:

问题分析

可以看到几乎80%的cpu都在做一件事情:ArrayList.removeAll(),根据线程栈找到了线上的代码大致如下:

protected void updateMeta(String redisField, List<String> oldHotels, List<String> newHotels) {//1.diff两次数据涉及的酒店//2.从老数据中删除新数据oldHotels.removeAll(newHotels);
}

可以看到其实cpu大部分的时间都在执行一行代码oldHotels.removeAll(newHotels),所以可以定位到问题所在。

前面提到我们同步数据其实是有两个数据源的,前面任务堵塞的数据源成为数据源1,另一个数据源称为数据源2,那么为什么数据源2没有阻塞呢?经过定位,发现关于数据源2更新数据的代码大致如下:

    private List<String> calculateNeedDeleteHotelSeqByRedis(String tableName, Set<String> thisHotelSeqs) {List<String> saveHotelSeqs = queryHotelSeqs(STRING_OLD_SEQ_TABLE_PREFIX + tableName);if (CollectionUtils.isNotEmpty(saveHotelSeqs)) {// 删除diff数据saveHotelSeqs.removeAll(thisHotelSeqs);return saveHotelSeqs;}

其实两个方法要做的事情都是一样,只是各自的实现方式不一样,但是都有一个关键的步骤就是从新数据集合中批量删除掉老数据。第一个数据源调用的api是ArrayList.removeAll(List list),第二个数据源调用的api是ArrayList.removeAll(Set set),其实两个api都是同一个api,他的定义为:

//java.util.ArrayList#removeAllpublic boolean removeAll(Collection<?> c) {Objects.requireNonNull(c);return batchRemove(c, false);}

所以,可以看出来其实区别就在于传参类型不同,接下来就需要深究为什么传参类型为List集合时会导致cpu上涨。

通过查询相关资料可以得知:在集合数据比较多的情况下, ArrayList.removeAll(Set)的速度远远高于ArrayList.removeAll(List)!从1百万数据中remove掉30万数据,前者需要0.031秒,后者需要1267秒!

结合以下类图:

从图中可以看到,图中相关的集合类(HashSetLinkedListArrayList),除了ArrayList自己实现了removeAll()方法外,其他两个集合都是借助父类(或超父类)的Iterator迭代器进行删除。接下来再来看一下ArrayList类的removeAll()方法的实现。

    private boolean batchRemove(Collection<?> c, boolean complement) {final Object[] elementData = this.elementData;int r = 0, w = 0;boolean modified = false;try {for (; r < size; r++)if (c.contains(elementData[r]) == complement)elementData[w++] = elementData[r];} finally {// Preserve behavioral compatibility with AbstractCollection,// even if c.contains() throws.if (r != size) {System.arraycopy(elementData, r,elementData, w,size - r);w += size - r;}if (w != size) {// clear to let GC do its workfor (int i = w; i < size; i++)elementData[i] = null;modCount += size - w;size = w;modified = true;}}return modified;}

从火线图中可以看出,主要是卡在执行contains()方法,而contains()方法则是调用入参自身的方法,因此需要对比的是HashSet.contains() vs ArrayList.contains()。

ArrayList.contains()

实现很简单,即调用indexOf(),一个一个地遍历查找。最坏时间复杂度为O(总数据量)

HashSet.contains()

我们知道,HashSet的底层是HashMap,因此,实际也就是调用map.containKey()方法。

大家都知道,HashMap的查找速度非常快!因此,到这里,我们也就解释题目的问题。

 解决方案

在数据量比较大的的情况下,使用arrayList.removeAll(subList)时,可以更改为:

  • subList封装为HashSetarrayList.removeAll(new HashSet(subList))
  • arrayList改为LinkedListnew LinkedList(arrayList).removeAll(subList)

最终我们将数据源一的代码修改如下,解决问题:

protected void updateMeta(String redisField, List<String> oldHotels, List<String> newHotels) {//1.diff两次数据涉及的酒店//2.从老数据中删除新数据// 包装为set集合Set<String> newHotelSet = Sets.newHashSet(newHotels);oldHotels.removeAll(newHotels);
}

相关文章:

使用ArrayList.removeAll(List list)导致的机器重启

背景 先说一下背景&#xff0c;博主所在的业务组有一个核心系统&#xff0c;需要同步两个不同数据源给过来的数据到redis中&#xff0c;但是每次同步之前需要过滤掉一部分数据&#xff0c;只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。 由…...

如何在项目中使用uni-ui组件库

1、安装uni-ui npm i dcloudio/uni-ui 2、组件自动引用 配置easycom 使用 npm 安装好 uni-ui 之后&#xff0c;需要配置 easycom 规则&#xff0c;让 npm 安装的组件支持 easycom 打开项目根目录下的 pages.json 并添加 easycom 节点&#xff1a; // pages.json {"e…...

redis的过期策略和内存淘汰机制(redis篇)

分享并学习一下redis的过期策略和内存淘汰机制 在平时的工作或者学习中&#xff0c;即便自己没有实打实的用过redis。但是能有对这方面的思考&#xff0c;再结合一些实际场景和理论&#xff0c;那么我相信自己或者你都会越来越厉害的。 首先&#xff0c;我们需要认清为啥redis要…...

Java中Runnable和Callable有什么不同?(企业真题)

Java中Runnable和Callable有什么不同&#xff1f; 与之前的方式的对比&#xff1a;与Runnable方式的对比的好处 call()可以有返回值&#xff0c;更灵活 call()可以使用throws的方式处理异常&#xff0c;更灵活 Callable使用了泛型参数&#xff0c;可以指明具体的call()的返回值…...

图机器学习导论

图&#xff1a;描述关系数据的通用语言&#xff0c;起源于哥尼斯堡七桥问题 传统的机器学习&#xff1a;数据样本之间独立同分布&#xff0c;简单拟合数据边界&#xff0c;在传统的机器学习中&#xff0c;每个数据样本彼此无关。传统的神经网络&#xff0c;只能处理简单的表格、…...

地推网推拉新平台哪家强?一文清楚告诉你

在当今这个充满副业的时代&#xff0c;地推网推拉新平台的寻找与对接成为了许多人关注的焦点。那么&#xff0c;我们应该如何找到那些既靠谱又有潜力的拉新项目呢&#xff1f; 经过深入研究和全网检索&#xff0c;我为大家盘点了5个值得一试地推网推拉新平台。 尤其是“聚小推…...

Day:004(4) | Python爬虫:高效数据抓取的编程技术(数据解析)

XPath工具 浏览器-元素-CtrlF 浏览器-控制台- $x(表达式) Xpath helper (安装包需要科学上网) 问题 使用离线安装包 出现 程序包无效 解决方案 使用修改安装包的后缀名为 rar&#xff0c;解压文件到一个文件夹&#xff0c;再用 加载文件夹的方式安装即可 安装 python若使用…...

(80) 只出现一次的数字(81)反转字符串

文章目录 1. 每日一言2. (80) 只出现一次的数字2.1 解题思路2.2 代码 3. (81)反转字符串3.1 解题思路3.2 代码 4. 结语 1. 每日一言 生活是一场即兴表演&#xff0c;值得庆幸的是我们总是有所感受&#xff0c;并且将一直感受下去。 2. (80) 只出现一次的数字 题目链接&#x…...

基于拉格朗日分布算法的电动汽车充放电调度MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 程序简介 该模型主要做的是基于拉格朗日分布算法的电动汽车充放电调度模型。利用蒙特卡洛模拟法模拟出电动汽车负荷曲线&#xff0c;并求解出无序充电功率曲线和有序充电曲线&#xff0c;该模型在电动汽车个…...

【Linux 学习】进程优先级和命令行参数!

1. 什么是优先级? 指定进程获取某种资源&#xff08;CPU&#xff09;的先后顺序&#xff1b; Linux 中优先级数字越小&#xff0c;优先级越高&#xff1b; 1.1 优先级和权限的区别&#xff1f; 权限 &#xff1a; 能不能做 优先级&#xff1a; 已经能了&#xff0c;但是获…...

Git删除未跟踪的文件Untracked files

在 Git 中&#xff0c;要删除未跟踪的文件&#xff08;Untracked files&#xff09;&#xff0c;你可以使用 git clean 命令。请注意&#xff0c;这个命令会从你的工作目录中永久删除这些文件&#xff0c;因此在执行之前请确保你不再需要这些文件或已经妥善备份。 以下是如何使…...

S7-1200PLC控制V90伺服通过FB284实现位置控制的方法

S7-1200PLC控制V90伺服通过FB284实现位置控制的方法 通过西门子报文111和FB284功能块 在V-ASSISTANT中将V90 PN设置控制模式为"基本位置控制(EPOS)" V90 PN与PLC采用PROFINET RT通信方式并使用西门子报文111。 在博途中V90 PN的设备视图中更改报文为:报文111 安装…...

2024年阿里云优惠券领取和使用方法

阿里云优惠代金券领取入口&#xff0c;阿里云服务器优惠代金券、域名代金券&#xff0c;在领券中心可以领取当前最新可用的满减代金券&#xff0c;阿里云百科aliyunbaike.com分享阿里云服务器代金券、领券中心、域名代金券领取、代金券查询及使用方法&#xff1a; 阿里云优惠券…...

工业项目中你连PLM系统都没见过?

什么是 PLM 软件&#xff1f; PLM 软件是用于管理全球供应链中产品或服务全生命周期环节的解决方案。它包括从物料、零部件、产品、文档、规定、工程变更单到质量工作流的数据管理。 PLM 的发展历史 从最初的产品设计管理到如今的数字化转型和智能化生产&#xff0c;PLM 在不断…...

【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬浮按钮弹出对话框

往期回顾&#xff1a; 【QT入门】 Qt自定义控件与样式设计之qss选择器-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QLineEdit的qss使用-CSDN博客 【QT入门】Qt自定义控件与样式设计之QPushButton常用qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬…...

C盘变红怎么办?免费的系统C盘清理方法,C盘空间占用克星

百夫说&#xff1a;分享免费又好用的工具&#xff0c;是一件快乐的事情。 正文&#xff1a; 起因&#xff1a;C盘报警&#xff0c;系统变慢 立即下载XX系统清理大师&#xff0c;搜索出垃圾数据近30G&#xff0c;开心的点击“一键清理”&#xff0c;结果提示要收费&#xff1a…...

简述VPS 与 Apache 搭建网站方式对比:新手科普指南

在互联网时代&#xff0c;拥有一个网站对于个人、企业以及组织来说已经成为了必备的一项资源。然而&#xff0c;对于新手来说&#xff0c;如何搭建一个网站可能是一个挑战。在这篇文章中&#xff0c;我将探讨两种常见的搭建网站的方式&#xff1a;使用虚拟专用服务器&#xff0…...

js获取年月份

一、date 如何使用、如何获取年月日时分秒、时间戳、如何获取指定日期的时间戳或周几 1..Date 对象用于处理日期和时间。 创建 Date 对象的语法&#xff1a; var myDatenew Date() 获取年月日时分秒&#xff1a; // 格式化日对象 const getNowDate () > {let date new …...

Promise常用方法及区别

一、实例方法 let _fun new Promise((resolve, reject) > {reject("失败&#xff01;"); }); /* resolve&#xff1a;异步操作成功时调用的回调函数。 reject&#xff1a;异步操作失败时调用的回调函数。 */ _fun.then(res > { // 成功console.log(res: , re…...

pyqt 标题栏设置

在PyQt中&#xff0c;可以通过QWidget或其子类&#xff08;如QMainWindow或QDialog&#xff09;的setWindowTitle()方法来设置窗口的标题栏。以下是一个简单的例子&#xff0c;展示了如何为应用程序的主窗口设置标题&#xff1a; import sys from PyQt5.QtWidgets import QApp…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...