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

这篇具有很好参考价值的文章主要介绍了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%。

Redis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

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

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

Redis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

Redis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

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

Redis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

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

Redis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

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内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,javaRedis内存使用率高,内存不足问题排查和解决,Redis,redis,数据库,java

总结

在使用redis的对象或者list队列等实例时,要记得给key设置过期时间,避免数据一直堆积无法释放。对于重要的异常数据队列的数据,要进行业务处理:重回队列或数据持久化。文章来源地址https://www.toymoban.com/news/detail-771558.html

到了这里,关于Redis内存使用率高,内存不足问题排查和解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • qt使用QCustomplot绘制cpu和内存使用率图

                QCustomPlot是一个开源的Qt C++图表库,用于可视化数据。该库提供了多种类型的可定制的图表,包括散点图、线图、柱状图和等高线图等。它还支持自定义绘制,可以创建任意形状和大小的元素,并使其与其他元素交互。QCustomPlot易于集成到现有的Qt应用程序中

    2024年02月09日
    浏览(52)
  • Linux-提高CPU、内存使用率shell脚本

    目录 1、提升CPU利用率 (1)构造CPU达到100% (2) 结束命令 2、提高内存利用率 可以申请的内存 申请内存空间: 完成后释放内存: 3、 使用ChaosBlade工具 cpu注入: 内存注入: (1)构造CPU达到100% for i in `seq 1 $(cat /proc/cpuinfo |grep \\\"physical id\\\" |wc -l)`; do dd if=/dev/zero of=/dev/null done (

    2024年02月04日
    浏览(71)
  • Linux提高CPU及内存使用率的脚本

    测试或运维中,有时会特意提高CPU及内存使用率,观察运行情况,以下脚本供参考。 链接1: Linux tmpfs及消耗内存脚本 链接2: Linux 中的 /dev/null 和 /dev/zero 链接3: Linux 提高CPU占用率的脚本

    2024年02月13日
    浏览(50)
  • Golang 简单的数据对齐可提高程序速度和内存使用率

    Golang 中的结构或 struct 是用户定义的类型,允许将可能不同类型的项分组/组合为单一类型。 可以说是一个不支持继承但支持组合的轻量级类。 我们使用 Golang 编写代码的时候,你肯定使用过 struct 。 但是,你可能不知道的是,通过简单地重新排序结构中的字段,可以极大地

    2024年02月11日
    浏览(47)
  • java获取系统CPU和内存使用率的三种方法

    获取系统CPU和内存的三种方法: 1、使用OperatingSystemMXBean获取 2、使用sigar方法获取 3、使用oshi方法获取 以下是我在我的机子上对三种方法测试的比较 方法    准确率 OperatingSystemMXBean    获取的内存数据准确,CPU差距有点大 sigar    获取的内存数据稍微有点差距,CPU相对

    2024年04月13日
    浏览(51)
  • STM32 CubeMX (第四步Freertos内存管理和CPU使用率)

    学习使用Freertos第四步 在 FreeRTOS 中,中断管理和软件定时: · taskENTER_CRITICAL() ·; 是一个函数在 FreeRTOS 中使用的,用于进入临界区(critical section)。在临界区内,中断会被禁用,这样可以确保在多任务环境下共享资源的安全性。你可以在需要保护共享资源的代码段中使用 ·

    2024年02月12日
    浏览(49)
  • 基于WebRTC构建的程序因虚拟内存不足导致闪退问题的排查以及解决办法的探究

    目录 1、WebRTC简介 2、问题现象描述 3、将Windbg附加到目标进程上分析

    2024年02月08日
    浏览(52)
  • linux获取内存与cpu使用率(附有C语言源码与shell脚本)

    linux内核提供了一种通过/proc文件系统来在运行时访问内核内部数据结构,改变内核设置的机制,各种硬件平台上的linux系统的/proc文件系统的基本概念都是相同的。 /proc文件系统是一种内核和内核模块用来向进程发送信息的机制。这个伪文件系统可以和内核内部的数据结构进

    2024年02月06日
    浏览(46)
  • k8s 检测node节点内存使用率平衡调度脚本 —— 筑梦之路

    直接上脚本: 参考资料: 一招完美解决k8s调度不均问题

    2024年01月16日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包