Redis内存使用率高,内存不足问题排查和解决

问题现象

表面现象是系统登录突然失效,排查原因发现,使用redis查询用户信息异常,从而定位到redis问题

if (PassWord.equals(dbPassWord)) {map.put("rtn", 1);map.put("value", validUser);session.setAttribute("username", user.getUsername());                                       redisWarehouseControlUtil.addObjectData(user.getUsername(),user.getUsername(),30);
}

排查原因

我的redis使用的是华为云的redis分布式缓存服务,所以在问题排查方面,我们可以结合华为云提供的丰富的分析诊断工具来辅助排查解决问题。

1、问题定位到redis上,登陆redis服务器,发现服务器内存使用率100%。

2、使用华为云的性能监控功能,查询指定时段的内存使用率信息。发现“内存利用率”指标持续接近100%。查询内存使用率超过95%的时间段内,“已逐出的键数量”和“命令最大时延”,均呈现显著上升趋势,表明存在内存不足的问题。

当内存不足时,可能导致Key频繁被逐出、响应时间上升、QPS(每秒访问次数)不稳定等问题,基本上redis服务已经瘫痪。

3、先使用实例诊断功能,大体分析一下可能得问题原因:主要还是内存占用过高问题。

4、使用华为云的缓存分析功能,执行大Key扫描,发现另一个项目的ErrorMeterData key,他是一个list队列,竟然存储数据占了2.6G,还有两个key存储数据占用了几百M,就是这三个key把服务器的内存占满了。

5、分析查找原因:去代码中查找ErrorMeterData key对应的功能,找到了问题所在,这个key存储的是解析出现异常的数据队列,但问题是,开发这个功能的同事,并没有给这个key设置过期时间也没有对这个异常数据队列的数据进行其他处理就一直存在这个队列中,随着时间的增长,以及异常数据的日复一日的不断累加,会导致存储数据太多,终于内存被占满。这是一个非常严重的bug。

问题就出在:redisMeterDataUtil.AddErrorMeterDataList(baseMessage);这一步

private void MeterDataExtractProcess()  {boolean rtn = false;while (!needClose) {// 普通表数据的解析try {BaseMessage baseMessage = redisMeterDataUtil.getMeterData();if (baseMessage != null) {if (!baseMessage.getFunctionCode().equals("") && baseMessage.getFunctionCode() != null) {switch (baseMessage.getFunctionCode()) {// 温控面板解析 --主动上传 批量case FunctionCode.UploadTcStateData:UploadTcStateDataMessage tcStateDataMessage =new UploadTcStateDataMessage(baseMessage);rtn = tcStateDataService.addUploadTcStateDataDataMessage(tcStateDataMessage);break;//  //根据表号读取,单条    温控面板解析case FunctionCode.getTcStateData:ReplyTcStateDataMessage replyTcStateDataMessage =new ReplyTcStateDataMessage(baseMessage);rtn = tcStateDataService.addTcStateDataMessage(replyTcStateDataMessage);break;default:break;}if (rtn == false) {// 解析方法存储失败,将数据添加到错误队列redisMeterDataUtil.AddErrorMeterDataList(baseMessage);}} else {// 若队列数据为空,则线程休眠1s后继续执行ThreadSleep(1000);continue;}}} catch (Exception e) {logger.error("MeterDataExtractServer--表数据redis解析出错"+e.getMessage());ThreadSleep(1000);}
public void AddErrorMeterDataList(BaseMessage baseMessage) {addData(ErrorMeterDataListSign, baseMessage);}private void addData(String type, Object data) {String key = type;redisTemplate.opsForList().leftPush(key, data);}

6、如果你没有使用华为云或者阿里云的专门的redis服务,而是自己在服务器搭建的Redis服务。那么排查问题的步骤和方法,大体可以分为几步:

  1. 查询诊断服务的CPU、内存、硬盘、网络等是否正常
  2. 查看日志分析异常问题
  3. 如果是内存占满问题,则可以在Redis-cli客户端连接实例后,执行大key扫描命令或者执行过期key扫描(过期key扫描会对键空间进行Redis的scan扫描,释放内存中已过期但是由于惰性删除机制而没有释放的内存空间),并查看key的内存占用情况。并对内存占用过大的key进行处理。

如果你想扫描Redis实例中的大key,你可以使用SCAN命令结合TYPE命令来获取每个键的类型,并根据键的类型获取其大小。

以下是一个示例的命令:

bash复制代码

redis-cli SCAN 0 MATCH * COUNT 1000 | while read key; do type=$(redis-cli TYPE $key); size=$(redis-cli -c GET $key | wc -c); echo "$key: $type, Size: $size"; done

这个命令将使用SCAN命令迭代整个数据库,并对每个键执行TYPE命令来获取键的类型。然后,对于字符串类型的键,使用GET命令获取其值,并使用wc -c命令计算其长度。最后,将键、类型和大小输出到终端。

另外,如果你想查看Redis实例的output buffer占用情况,你可以使用CONFIG GET output-buffer-limit命令来获取output buffer的配置信息。该命令将返回output buffer的配置参数,包括类型、大小和阈值。

请注意,上述命令中的redis-cli -c GET $key是用于获取字符串类型的键的大小。对于其他类型的键,你可能需要使用其他命令或方法来获取其大小。

处理措施

1、为内存占用过大的key设置过期时间,这样数据就不会一直存储在队列中

(1)比较紧急想要恢复redis,且队列中的数据不重要,则可以直接链接redis,执行命令

EXPIRE key seconds:设置键的过期时间(以秒为单位),过期后键将被自动删除。

或者

DEL key:删除指定键

(2)在代码中为key设置过期时间

/*** 设置设备缓存过期时间(分钟)* @param type 设备分类*/private void setExpireTime(String type,int cacheTime) {String key = type;redisTemplate.expire(key,cacheTime,TimeUnit.MINUTES);}/*** 设置表数据缓存失效时间list集合*/public void setMeterInfoExpire() {setExpireTime(MeterDataListSign,deviceCacheTime);}

2、业务逻辑上将这个异常数据队列的数据,重新返回处理队列,设置返回次数,如果超过三次以上,还是没有被正常队列处理掉,则将异常数据持久化,并删除redis中的该异常数据。

我的实际业务中,异常数据没有重回队列处理的必要了,所以我的业务代码中,直接不在用redis队列存储异常数据,而是直接将异常数据持久化存储到mongodb中。

if (rtn == false) {// 解析方法存储失败,将数据添加到错误队列----不再存在redis,直接持久化存储到mongodb//redisMeterDataUtil.AddErrorMeterDataList(baseMessage);tcErrorMessageHistoryUtil.addMessage(baseMessage);
}

3、设置key的过期时间后,过了一段时间内存恢复正常

总结

在使用redis的对象或者list队列等实例时,要记得给key设置过期时间,避免数据一直堆积无法释放。对于重要的异常数据队列的数据,要进行业务处理:重回队列或数据持久化。

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

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

相关文章

【产品经理】用户研究与需求分析

笔记为课程学习笔记,若有错误欢迎指出哟~ 【产品经理】用户研究与需求分析 需求收集1.需求定义2.需求来源3.需求收集方法 需求池SWOT分析SWOT分析——道斯矩阵(TOWS)用户体验五要素应用场景层次结构用户体验五要素产出物 用户角色与用户画像经…

二叉树简单实现(C语言版)

一.简单建二叉树 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二 叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树 …

SQL注入【ByPass有点难的靶场实战】(九)

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与学习之用,读者将信息做其他用途,由Ta承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 0、总体思路 先确认是否可以SQL注入,使用单…

2023年03月20日_对李开复3月20日线下媒体会的解读

最近这个AI大模型 因为GPT4.0 ChatGPT 文心一言等等这些事情呢 一下子就被推到了风口浪尖 我们也做了来介绍相关的进展 国内呢也不断有一些大佬开始下场 包括王慧文、张朝阳、李彦宏什么的 都开始说自己要搞AI大模型 就在昨天呢 创新工厂的董事长兼CEO李开复 也发朋友…

2022年全球运维大会(GOPS深圳站)-核心PPT资料下载

一、峰会简介 GOPS 主要面向运维行业的中高端技术人员,包括运维、开发、测试、架构师等群体。目的在于帮助IT技术从业者系统学习了解相关知识体系,让创新技术推动社会进步。您将会看到国内外知名企业的相关技术案例,也能与国内顶尖的技术专家…

【C++】STL 容器 - set 集合容器 ⑦ ( 查找元素 - set#find 函数 | 获取元素个数 - set#count 函数 )

文章目录 一、查找元素 - set#find 函数1、函数原型 简介2、代码示例 - set#find 函数 二、获取元素个数 - set#count 函数1、函数原型 简介2、代码示例 - set#find 函数 一、查找元素 - set#find 函数 1、函数原型 简介 在 C 语言的 STL 标准模板库 , std::set 集合容器 是一个…

HCIP:rip综合实验

实验要求: 【R1-R2-R3-R4-R5运行RIPV2】 【R6-R7运行RIPV1】 1.使用合理IP地址规划网络,各自创建环回接口 2.R1创建环回 172.16.1.1/24 172.16.2.1/24 172.16.3.1/24 3.要求R3使用R2访问R1环回 4.加快网络收敛,减少路由条目数量,增…

2024年【R1快开门式压力容器操作】试题及解析及R1快开门式压力容器操作复审考试

题库来源:安全生产模拟考试一点通公众号小程序 R1快开门式压力容器操作试题及解析根据新R1快开门式压力容器操作考试大纲要求,安全生产模拟考试一点通将R1快开门式压力容器操作模拟考试试题进行汇编,组成一套R1快开门式压力容器操作全真模拟…

RHCE9学习指南 第12章 ssh远程登录系统和远程拷贝

很多时候服务器并没有显示器,我们也不可能每次都通过控制台去管理服务器,这时就需要远程登录。远程登录到服务器可以通过Telnet或ssh的方式。但是用Telnet登录,整个过程都是以明文的方式传输的,不安全。所以,建议使用s…

Java基础语法(注释,关键字,字面量,变量,数据类型,标识符,键盘录入,IDEA安装,类,模块,项目)

文章目录 day02 - Java基础语法1. 注释使用的技巧注意点 2. 关键字2.1 概念2.2 第一个关键字class 3. 字面量区分技巧 4. 变量4.1 什么是变量?4.2 变量的定义格式4.2.1 格式详解4.2.2 常用的数据类型4.2.3 变量的注意事项 4.3 变量的练习 5. 数据类型5.1 Java语言数…

Vue3-30-路由-嵌套路由的基本使用

什么是嵌套路由 嵌套路由 &#xff1a;就是一个组件内部还希望展示其他的组件&#xff0c;使用嵌套的方式实现页面组件的渲染。 就像 根组件 通过路由渲染 普通组件一样&#xff0c;嵌套路由也是一样的道理。 嵌套路由的相关关键配置 1、<router-view> 标签 声明 被嵌套组…

MendelianRandomization | 孟德尔随机化神包更新啦!~(一)(小试牛刀)

1写在前面 今天发现MendelianRandomization包更新v0.9了。&#x1f61c; 其实也算不上更新。&#x1fae0; 跟大家一起分享一下这个包做MR的用法吧。&#x1f929; 还有一个包就是TwoSampleMR&#xff0c;大家有兴趣可以去学一下。&#x1f605; 2用到的包 rm(list ls())# ins…

探索效率与可扩展性:MinIO图片服 VS FastDFS图片服

目录 1、前言 2、背景知识 2.1 Minio图片服的概述 2.2 FastDFS图片服的概述 3、性能比较 3.1 存储性能比较 3.1.1 对比上传速度和下载速度 3.1.2 比较两者的读写性能 3.2 负载均衡性能比较 4、可扩展性比较 4.1 横向扩展性性能比较 4.2 纵向扩展性性能比较 5、结语…

CCNP课程实验-Route_Path_Control_CFG

目录 实验条件网络拓朴需求 配置实现基础配置需求实现1.A---F所有区用Loopback模拟&#xff0c;地址格式为&#xff1a;XX.XX.XX.XX/32&#xff0c;其中X为路由器编号。根据拓扑宣告进对应协议。A1和A2区为特例&#xff0c;A1&#xff1a;55.55.55.0/24&#xff0c;A2&#xff…

ArkTS基本概念装饰器

目录 ArkTS基本概念 装饰器汇总 ArkTS基本概念 ArkTS是HarmonyOS的主力应用开发语言。 它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;匹配ArkUI框架&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发者以更简洁、更自然的方式开发跨…

Python变量与常量

第三章、变量与常量 一、标识符 1、定义 在 Python 中&#xff0c;标识符是用来标识变量、函数、类、模块或其他用户定义的对象的名称。标识符是程序员自定义的名称&#xff0c;用于在代码中标识不同的实体&#xff0c;使得代码可读性更强&#xff0c;更易于理解和维护。标识…

汽配订货系统 助力汽配行业数字化转型升级

一个汽配订货系统可以助力汽配行业数字化转型升级&#xff0c;提供以下功能和优势&#xff1a; 1. 订单管理&#xff1a;订货系统可以记录每笔订单的详细信息&#xff0c;包括客户信息、产品信息、价格、数量等&#xff0c;方便汽配商进行订单统计和分析。 2. 库存管理&#x…

mxxWechatBot微信机器人V2版本文档说明

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 先看这里 一、前言二、mxxWechatBot流程图三、怎么使用&#xff1f; 一、前言 经过不断地探索与研究&#xff0c;mxxWechatBot正式上线&#xff0c;届时全面开放使用。 mxxWechatBot&am…

59. 螺旋矩阵 II

给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&#xff1a;n 1 输出&…

OSPF的DR与BDR-新版(16)

目录 整体拓扑 操作步骤 1.基本配置 1.1 配置R1的IP 1.2 配置R2的IP 1.3 配置R3的IP 1.4 配置R4的IP 1.5 检测R1与R4连通性 1.6 检测R1与R2连通性 1.7 检测R1与R3连通性 2.搭建基本的OSPF网络 2.1 配置R1 OSPF 2.2 配置R2 OSPF 2.3 配置R3 OSPF 2.4 配置R4 OSPF…