系统吃swap问题排查

news2024/9/24 19:22:23

目录

背景

问题

分析并解决

1.控制线程数

2.更换IO组件

3.Linux进程信息文件分析

总结加餐

参考文档

背景

隔壁业务组系统是简单的主从结构,写索引的服务(主)叫primary, 读索引并提供搜索功能的服务(从)叫replica。业务线同步数据并不是平滑的,在同步数据时primary瞬间负载上升,磁盘写IO增加,这是合理的。

primary 写完索引,会马上触发索引的同步操作,因此,瞬间的磁盘读IO增加以及网络流量的增加都是合理的。

问题

在节假日高峰期前期,团队增加了50%的replica服务器,这造成了primary的同步压力进一步增加,观测系统监控,发现了“吃swap”的现象,这就不合理了,需要分析优化。

这里简单解释下“吃swap”:

在计算机系统中,"吃swap"指的是系统开始使用交换空间(swap space)来补充物理内存(RAM)的不足。交换空间是一块预留在磁盘上的区域,用于存储那些当前不常用的内存数据。当物理内存不足时,操作系统会将一些数据从内存中移到交换空间,以腾出内存给其他需要的进程。

具体来说,“吃swap”通常表示以下几种情况:

  1. 内存不足:系统的物理内存已经被用完,导致操作系统不得不使用交换空间来存储数据。
  2. 性能下降:因为磁盘的读写速度远低于内存的读写速度,当系统频繁访问交换空间时,性能会显著下降。用户可能会注意到系统变得响应缓慢。
  3. 高负载场景:在高负载场景下,如大量的索引写入和同步操作,内存需求突然增加,导致系统不得不使用swap。

以上描述的情况下,primary服务器在索引写入和同步操作的高负载下,内存不足,导致操作系统开始频繁使用swap,从而出现“吃swap”的现象。这是不合理的,因为频繁使用swap会显著降低系统性能,影响整体服务的响应速度和稳定性。因此,需要通过优化措施来减少对swap的依赖,提高系统的性能。

分析并解决

1.控制线程数

参考以前的经验,replica 有个索引备份功能,在晚上4点会备份本地索引文件(30G)到指定目录
这个操作就会造成瞬间IO的增加以及负载的升高,因此最初我们判断这是索引复制太快,导致的内存耗尽和负载增加。我们尝试通过控制primary服务线程池的大小,来放慢索引复制的速度。

经过压测发现,线程很小(5个)的情况,载峰值有所降低,但是吃swap的问题仍然存在。

结论:primary采用的gRPC框架,通过控制线程池大小来放慢索引复制的速度在gRPC框架中并不奏效,因为gRPC的异步调用机制允许高并发执行,独立于线程数量。有效的优化策略需要针对异步调用特性和具体负载情况进行调整,而不仅仅是控制线程数。

2.更换IO组件

Lucene提供了两种磁盘访问方式MMapDirectory和NIODirectory,因为mmap方式会大量使用堆外内存,因此我们怀疑是堆外内存失控导致的系统内存不足,经过更换Directory,发现吃swap问题仍然存在。

Apache Lucene 是一个高性能、可伸缩的信息检索库,用于全文搜索和索引。Lucene 提供了多种方式来访问磁盘存储的索引数据,主要包括 MMapDirectoryNIODirectory

结论:mmap虽然会使用堆外内存,但是linux应该是可以控制好堆外内存的回收的。

3.Linux进程信息文件分析

我们分析了linux下的 /proc/$pid/status文件,VmSwap是swap占用情况,VmHWM是历史内存占用。以及java进程当前的内存占用情况 sudo -u tomcat jhsdb jmap --heap --pid $pid

发现java进程的历史内存占用很高,而当前内存占用并不高(所以排除了内存泄漏),各个进程都有占用swap的现象,说明是java进程在某个时刻(文件传输)耗尽了内存,导致其他进程吃swap,而那个时刻过后,java进程是可以回收内存的。所以推测是索引文件传输过程中,某些buffer设置不合理导致的。

经过代码排查 ,发现gRPG(高度异步)在读取索引文件时需要多次判断serverCallStreamObserver.isReady(),如果只判断一次isReady,就把所以数据写入响应流,就会占用大量系统缓冲区。官方推荐的是一种callback机制,示例代码如下:

final InputStream input = ...

serverCallStreamObserver.setOnReadyHandler(new Runnable() {

    int upto = 0// 传输偏移,需要反复使用

    final long size = file.length();

    public void run() { // 这里会根据缓冲区状态多次被触发执行,因此这个Runnable是有状态的

        while (upto < size && serverCallStreamObserver.isReady()) {

             response.onNext(...); //写入缓冲区

             upto += chunk;

        }

    }

});

serverCallStreamObserver.setOnCancelHandler(() -> input.close());

serverCallStreamObserver.setOnCloseHandler(() -> input.close());

  • 缓冲区管理不当:原始代码在判断 serverCallStreamObserver.isReady() 一次后,立即写入所有数据,导致系统缓冲区被大量占用,内存迅速耗尽。
  • 回调机制:通过设置 serverCallStreamObserver.setOnReadyHandler 回调函数,确保只有在缓冲区准备好时才写入数据。这样可以避免一次性写入过多数据,导致内存占用过高。
  • 状态管理:使用 upto 变量跟踪传输偏移量,每次 isReady 时仅写入一部分数据,缓解系统缓冲区的压力。
  • 资源释放:通过 setOnCancelHandlersetOnCloseHandler 确保在取消或关闭时正确关闭输入流,避免资源泄漏。

这种写法会比较反直觉,通过回调函数关闭InputStream看上去没有finally去关闭安全,好处是缓冲区压力小,最终问题解决。

总结加餐

以上描述的问题的根本原因在于 gRPC 在文件传输过程中缓冲区管理不当,导致内存占用过高。通过引入官方推荐的回调机制和合理的状态管理,成功解决了该问题。因此在日常开发中,涉及到文件写入与读取时,还是需要多关注一下流的关闭与打开与缓冲区buffer的使用是否合理。

Linux将物理内存分为内存段,叫做页面。交换是指内存页面被复制到预先设定好的硬盘空间(叫做交换空间)的过程,目的是释放这份内存页面。物理内存和交换空间的总大小是可用的虚拟内存的总量。我们知道swap space是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者以它们的组合方式出现。简单点说,当系统物理内存吃紧时,Linux系统会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为其他进程服务,而当系统需要访问swap上存储的内容时,系统会再将 swap 上的数据加载到内存中,这就是我们常说的swap outswap in了。那么配置多大的 Swap 比较合适?

  • 当物理内存小于1G且不需要休眠时,设置和内存同样大小的swap空间即可;当需要休眠时,建议配置两倍物理内存的大小,但最大值不要超过两倍内存大小。
  • 当物理内存大于1G且不需要休眠时,建议大小为sqrt(RAM),其中RAM为物理内存大小;当需要休眠时,建议大小是RAM+round(sqrt(RAM)),但最大值不要超过两倍内存大小。
  • 如果两倍物理内存大小的swap空间还不够用,建议增加内存而不是增加swap

此外,在一篇参考文献中看到如下这段话:

 如果频繁的访问 swap 的话,怎么优化 swap 都没用,跟内存比还是低几个数量级,性能还是下降的厉害,如果不频繁访问 swap 的话,优化 swap 又有啥意义呢?所以其实优化 swap 性能的实际意义不大。

参考文档

https://zhuanlan.zhihu.com/p/467976849

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

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

相关文章

DIF-Gaussian 代码讲解

这篇论文的标题是《Learning 3D Gaussians for Extremely Sparse-View Cone-Beam CT Reconstruction》&#xff0c;作者是Yiqun Lin, Hualiang Wang, Jixiang Chen和Xiaomeng Li&#xff0c;来自香港科技大学以及HKUST深圳-香港协同创新研究院。 这篇论文主要探讨了一种新的锥…

关于MySQL mvcc

innodb mvcc mvcc 多版本并发控制 在RR isolution 情况下 trx在启动的时候就拍了个快照。这个快照是基于整个数据库的。 其实这个快照并不是说拷贝整个数据库。并不是说要拷贝出这100个G的数据。 innodb里面每个trx有一个唯一的trxID 叫做trx id .在trx 开始的时候向innodb系…

录音的内容怎么做二维码?支持多种音频格式使用的制作技巧

怎么把录制的音频文件做成二维码呢&#xff1f;现在用二维码来存储内容是一种很常用的方式&#xff0c;让其他人扫描二维码来查看内容&#xff0c;从而提升内容传输的速度。比如现在很多人会将音频生成二维码&#xff0c;其他人可以通过扫码在手机上播放音频内容&#xff0c;那…

kafka的副本replica

指定topic的分区和副本 通过kafka命令行工具 kafka-topics.sh --create --topic myTopic --partitions 3 --replication-factor 1 --bootstrap-server localhost:9092 执行代码时指定分区个数

谈大语言模型动态思维流编排

尽管大语言模型已经呈现出了强大的威力&#xff0c;但是如何让它完美地完成一个大的问题&#xff0c;仍然是一个巨大的挑战。 需要精心地给予大模型许多的提示&#xff08;Prompt&#xff09;。对于一个复杂的应用场景&#xff0c;编写一套完整的&#xff0c;准确无误的提示&am…

JavaWeb__正则表达式

目录 1. 正则表达式简介2. 正则表达式体验2.1 验证2.2 匹配2.3 替换2.4 全文查找2.5 忽略大小写2.6 元字符使用2.7 字符集合的使用2.8 常用正则表达式 1. 正则表达式简介 正则表达式是描述字符模式的对象。正则表达式用于对字符串模式匹配及检索替换&#xff0c;是对字符串执行…

如何让 3D 数字孪生场景闪闪发光

今日图扑软件功能分享&#xff1a;我们将探讨 HT 系统如何通过分组管理灯光、裁切体和流光&#xff0c;以提高场景光影效果的精准度和整体可控性。 HT 中的灯光、裁切体、流光是会影响它所在区域一定范围内的其他节点的表现&#xff0c;如 场景中有个 A 灯光&#xff0c;默认情…

微信小程序引入自定义子组件报错,在 C:/Users/***/WeChatProjects/miniprogram-1/components/路径下***

使用原生小程序开发时候&#xff0c;会报下面的错误&#xff0c; [ pages/button/button.json 文件内容错误] pages/button/button.json: [“usingComponents”][“second-component”]: “…/…/components/second-child/index”&#xff0c;在 C:/Users/***/WeChatProjects/m…

布隆过滤器 redis

一.为什么要用到布隆过滤器&#xff1f; 缓存穿透&#xff1a;查询一条不存在的数据&#xff0c;缓存中没有&#xff0c;则每次请求都打到数据库中&#xff0c;导致数据库瞬时请求压力过大&#xff0c;多见于爬虫恶性攻击因为布隆过滤器是二进制的数组&#xff0c;如果使用了它…

小米手机短信怎么恢复?不用求人,3个技巧一网打尽

当你突然发现安卓手机里的重要短信不见了&#xff0c;是不是感到一阵心慌意乱&#xff1f;别急&#xff0c;不用求人&#xff0c;更不用焦虑。作为基本的社交功能&#xff0c;短信是我们与外界沟通的重要桥梁&#xff0c;当删除后&#xff0c;短信怎么恢复呢&#xff1f;今天&a…

Halcon 模糊圆边的找圆案例

Halcon 模糊圆边的找圆案例 基本思路 1.将图像转成灰度图像 2.再观察要找到的区域的灰度值变化&#xff0c;找到前景与背景的具体数值。 3.根据找到的前景与背景的具体数值&#xff0c;增强图像对比度。&#xff08;使图像变成黑白图片&#xff09; 4.使用灰度直图工具进行阈值…

ChatTTS使用

ChatTTS是一款适用于日常对话的生成式语音模型。 克隆仓库 git clone https://github.com/2noise/ChatTTS cd ChatTTS 使用 conda 安装 conda create -n chattts conda activate chattts pip install -r requirements.txt 安装完成后运行 下载模型并运行 python exampl…

android13 固定U盘链接 SD卡链接 TF卡链接 硬盘链接

1.前言 有些客户使用的应用并不带有自动监听U盘 sd卡广播的代码,使用的代码是固定的地址,这样的话,就需要我们将系统的挂载目录固定了。 原始路径 /storage/3123-19FA 增加链接 /storage/upan_000 -> /storage/3123-19FA 2. 首先如果是应用本身监听的话,使用的是 /…

美容美发在线预约小程序源码系统 前后端完整分离 带完整的安装代码包以及搭建教程

系统概述 在当今这个快节奏的社会&#xff0c;美容美发服务已经成为人们日常生活中不可或缺的一部分。为了满足广大消费者的便捷预约需求&#xff0c;以及美容美发行业的数字化转型趋势&#xff0c;一款高效、易用、功能全面的在线预约小程序显得尤为重要。今天&#xff0c;我…

纷享销客荣获CDIE“2024优秀数字化技术服务商”

近日&#xff0c;在第十届数字化创新博览会&#xff08;CDIE 2024&#xff09;上&#xff0c;CRM品牌领导者纷享销客凭借其卓越的技术实力和创新的解决方案&#xff0c;荣获“2024 优秀数字化技术服务商”奖项。 作为国内领先的CRM数字化解决方案服务商&#xff0c;纷享销客一直…

白盒测试的概念、特点、应用阶段、实施流程、现状与前景

文章目录 前言一、白盒测试的应用阶段二、白盒测试的特点三、白盒测试的流程四、白盒测试的现状与前景总结 前言 白盒测试&#xff08;White Box Testing&#xff09;&#xff0c;又称为结构测试&#xff08;Structural Testing&#xff09;、透明盒测试&#xff08;Glass Box…

循环练习 while

public static void main(String[] args) {double money100000;int count0;while(money>1000){if (money>50000){moneymoney-money*0.05;count;}else if (money>1000){money-1000;count;}else {break;}}System.out.println(count);} 结果为&#xff1a;

ggplot2绘图点的形状不够用怎么办?

群里有这么一个问题&#xff1a; 请问老师&#xff0c;fviz_pca_ind 做pca&#xff0c;当设置geom.ind “point”&#xff0c;group>6时&#xff0c;就不能显示第7&#xff0c;8组的点&#xff0c;应该如何处理&#xff08;在不设置为文本的情况下&#xff09;&#xff0c;…

如何为IP申请SSL证书

目录 以下是如何轻松为IP地址申请SSL证书的详细步骤&#xff1a; 申请IP证书的基本条件&#xff1a; 申请IP SSL证书的方式&#xff1a; 确保网络通信安全的核心要素之一&#xff0c;是有效利用SSL证书来加密数据传输&#xff0c;特别是对于那些直接通过IP地址访问的资源。I…

部署Harbor镜像仓库并在k8s配置使用

文章目录 一、下载所需软件包1.docker-compose2.harbor 二、安装docker-compose1.安装docker2.配置docker-compose 三、安装harbor1.编辑harbor配置文件2.加载harbor配置&#xff08;重新加载配置文件&#xff0c;只要修改配置文件就需要执行&#xff09;3.开始安装harbor4.doc…