使用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);
}

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

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

相关文章

Qt/QML编程之路:图片进度条的实现(50)

要实现进度条,而进度条是通过一个图片来展示的,比如逐渐增大的音量,或者逐步增大的车速,通过图片显示的效果肯定更好一些。最直接的想法是通过一个透明的rectagle,把不想让看到的遮住,实际上这种方法不可行。 import QtQuick 2.5 import QtQuick.Window 2.2 import QtGra…

【学习】移动端兼容性测试有什么方法及重要性

随着移动互联网的快速发展&#xff0c;移动应用程序已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;由于各种移动设备的硬件和软件差异&#xff0c;移动应用程序的兼容性问题也越来越突出。因此&#xff0c;移动端兼容性测试成为了一个重要的环节&#xff0c;它可以…

如何在 Android 设备上恢复已删除/丢失的文档

随着Android设备内存容量的不断增加&#xff0c;许多人将手机作为移动硬盘来存储大量文档或其他文件。由于某些原因&#xff0c;文件丢失绝对是一场彻头彻尾的噩梦&#xff0c;因为里面的数据可能是要汇报的学习档案、领导会议的安排、或者付费电子书等。通常&#xff0c;你首先…

如何备考蓝桥杯赛事 怎样才能取得好成绩?

在计算机领域&#xff0c;蓝桥杯赛事一直是备受关注的比赛之一。参加蓝桥杯不仅可以锻炼自己的编程能力&#xff0c;还能够结识志同道合的朋友&#xff0c;拓展自己的人际关系。然而&#xff0c;想要在蓝桥杯赛事中取得好成绩并不是一件容易的事情&#xff0c;需要充分的准备和…

02_JavaWeb中的Tomcat(详解)

文章目录 Tomcat1, 概述1.1 安装1.2 目录结构1.3 启动/停止 2, 资源部署2.1 直接部署: 主要和重要的方式2.2 虚拟映射: 重要2.2.1 方式一:2.2.1 方式二: 2.3 原理解析 3, Tomcat组件3.1 Connector3.2 Engine3.2.1 Host3.2.1.1 Context 4, 其它: 重要4.1 设置 Tomcat 1, 概述 w…

sql server2008触发器

sql server在Navicat工具不能插入数据 可以去写代码插入&#xff0c;代码连接sql server可以插入 或者使用sql server专门的工具 BEGINdeclare a int;declare s t_amount;select a baddebt_age_id,srate from aa_baddebt_age;INSERT INTO dade(id,name) VALUES(a,s) END

手机外屏碎8折维修,天星金融(原小米金融)助阵米粉节

今年4月6日是小米公司14岁生日&#xff0c;也是一年一度的盛会“米粉节”。据“小米服务”官方公众号发布的消息&#xff0c;为庆祝这一重要日子&#xff0c;从4月6日起至4月17日&#xff0c;为用户带来一系列服务权益。 据悉&#xff0c;活动共包括8项服务权益&#xff0c;其…

2024年认证杯SPSSPRO杯数学建模B题(第一阶段)神经外科手术的定位与导航全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 B题 神经外科手术的定位与导航 原题再现&#xff1a; 人的大脑结构非常复杂&#xff0c;内部交织密布着神经和血管&#xff0c;所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术&#xff0c;通常需要…

12.4.1 实验1:配置CDP

12.4.1 实验1&#xff1a;配置CDP 1、实验目的 通过本实验可以掌握: CDP特征。CDP配置和调试方法。通过CDP查看设备直连邻居信息的方法。 2、实验拓扑 配置CDP的实验拓扑如上图所示。 3、实验步骤 &#xff08;1&#xff09;配置路由器R1 R1(config)#interface serial 0…

选择成为一名程序员:兴趣与职业发展的交织

在当今信息化、数字化的时代&#xff0c;程序员这一职业越来越受到年轻人的青睐。那么&#xff0c;是什么原因驱使他们选择走上编程这条道路呢&#xff1f;是纯粹的兴趣使然&#xff0c;还是对未来职业发展的深思熟虑&#xff1f;本文将深入探讨这一话题&#xff0c;分析兴趣与…

【opencv】示例-pca.cpp PCA图像重建演示

// 加载必要的头文件 #include <iostream> // 用于标准输入输出流 #include <fstream> // 用于文件的输入输出 #include <sstream> // 用于字符串的输入输出流操作#include <opencv2/core.hpp> // OpenCV核心功能的头文件 #include "o…

Pycharm通过配置隧道连接远程服务器

前言&#xff1a; 上篇有说到局域网windows和服务器互通的情况下连接远程pycharm&#xff0c;这次咱们来说下通过跳板机的方式连接服务器如何做到windows远程连接到服务器 1&#xff1a;设置SSH隧道或SSH代理 ssh -L localhost:LOCAL_PORT:FINAL_SERVER_IP:FINAL_SERVER_PORT…

Prompt编写——安全边界

在编写prompt&#xff08;提示、指令或引导语&#xff09;时&#xff0c;设置安全边界主要是为了防止生成的内容超出预期或包含不合适、有害的信息。特别是在使用大型语言模型时&#xff0c;如GPT系列模型&#xff0c;设置安全边界至关重要。以下是一些建议来设置安全边界&…

如何实现vue点击按钮进行图片浏览 ?

以下是官方的写法&#xff0c;并不能达到我们的要求&#xff0c;官方实现的功能是点击图片达到预览大图的效果。如果你的按钮就是图片&#xff0c;也可以达到目前的功能 <div class"demo-image__preview"><el-imagestyle"width: 100px; height: 100px…

AI赋能的BIM体验

近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术与建筑信息模型&#xff08;BIM&#xff09;的融合给建筑行业带来了革命性的变化。 BIM 是建筑物物理和功能特征的数字表示&#xff0c;与 AI 功能相结合&#xff0c;显着改变了客户的体验。 在本文中&#xff0c;我们…

搭建Android内核和Framework开发和调试环境

环境 ubuntu20.04或者22.04 x86_64 步骤 搭建cuttlefish运行环境 参考:搭建 Cuttlefish 运行环境 安装下面的软件包sudo apt install -y git devscripts config-package-dev debhelper-compat golang curl 其他,可以参考这个链接,安装android依赖的软件包: sudo apt i…

1.Chinese Tiny LLM_ Pretraining a Chinese-Centric Large Language Model

文章目录 摘要一、背景二、预训练数据统计信息数据处理 模型架构 三、SFT四、Learning from Human Preferences五、评估数据集和指标训练过程和比较分析安全性评估中文硬指令理解与遵循评价 六、结论 https://arxiv.org/abs/2404.04167https://github.com/Chinese-Tiny-LLM/Chi…

python 今日小知识1——parser

argparse模块&#xff0c;其实质就是将相关参数进行设置。相对专业说法&#xff1a; argparse 模块提供轻松编写用户友好的命令行接口。 程序定义它需要的参数&#xff0c;然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块会自动生成帮助和使用手册&#…

江科大笔记

这里写目录标题 片上资源/外设引脚定义表启动配置推挽开漏oc/od 门漏极/集电极 电阻的上拉下拉输入捕获输入捕获通道主从触发模式输入捕获基本结构PWMI基本结构PWMPSC ARR CRR输入捕获模式测频率TIM_PrescalerConfig()初始化输入捕获测频法测周法 PWMI模式测频率占空比定时中断…

C语言经典例题(24) --- 计算体重指数、计算三角形的周长和面积、计算球体的体积、成绩的输入输出、变种水仙花数

文章目录 1.计算体重指数2.计算三角形的周长和面积3.计算球体的体积4.成绩的输入输出5.变种水仙花数 1.计算体重指数 题目描述: 问题&#xff1a;计算BMI指数&#xff08;身体质量指数&#xff09;。BMI指数&#xff08;即身体质量指数&#xff0c;简称体质指数又称体重&…