瓦特 线上出现堆外内存溢出

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 絮叨本来打算是准备着一支烟 一杯咖啡 一个bug写一天的,但是一来公司,运维就把昨天生产线的日志怼过来说,线上报错了。。。

絮叨


本来打算是准备着一支烟 一杯咖啡 一个bug写一天的,但是一来公司,运维就把昨天生产线的日志怼过来说,线上报错了。。。


堆外内存报错

2020-03-24 03:35:39.486 ERROR --- [ForkJoinPool.commonPool-worker-0] com.hq.tiku.sync.bw.listener.ClassPlainListenter Line:101 - 同步消息队列push.userClassplan.tiku出现异常ClassPlanEntity(classplanId=2c7cc389822b4181a591c9890a2d3eeb, teacherId=276, teacherName=陈文文, teacherTeam=null, userId=18658702, className=2020年初级冲剌班, courseId=2900, courseNo=2020005CJ, courseName=2020年初级会计实务冲刺阶段, classplanName=2020年初级会计实务(冲刺阶段), classId=5864, tkUserId=null, courseTkNo=null, planNum=null)
org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.RedisException: io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 855638016 byte(s) of direct memory (used: 985661440, max: 1823473664)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:74)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
    at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:257)
    at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.convertLettuceAccessException(LettuceStringCommands.java:718)
    at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.set(LettuceStringCommands.java:143)
    at org.springframework.data.redis.connection.DefaultedRedisConnection.set(DefaultedRedisConnection.java:231)
    at org.springframework.data.redis.core.DefaultValueOperations$3.inRedis(DefaultValueOperations.java:202)
    at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:59)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
    at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
    at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:198)
    at com.hq.tiku.sync.bw.listener.ClassPlainListenter.lambda$synClassPlan$0(ClassPlainListenter.java:92)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.stream.Nodes$ArrayNode.forEach(Nodes.java:684)
    at java.util.stream.ForEachOps$ForEachOrderedTask.onCompletion(ForEachOps.java:490)
    at java.util.concurrent.CountedCompleter.tryComplete(CountedCompleter.java:577)
    at java.util.stream.ForEachOps$ForEachOrderedTask.onCompletion(ForEachOps.java:505)
    at java.util.concurrent.CountedCompleter.tryComplete(CountedCompleter.java:577)
    at java.util.stream.ForEachOps$ForEachOrderedTask.onCompletion(ForEachOps.java:505)
    at java.util.concurrent.CountedCompleter.tryComplete(CountedCompleter.java:577)
    at java.util.stream.ForEachOps$ForEachOrderedTask.doCompute(ForEachOps.java:483)
    at java.util.stream.ForEachOps$ForEachOrderedTask.compute(ForEachOps.java:400)
    at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: io.lettuce.core.RedisException: io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 855638016 byte(s) of direct memory (used: 985661440, max: 1823473664)
    at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:125)
    at io.lettuce.core.FutureSyncInvocationHandler.handleInvocation(FutureSyncInvocationHandler.java:62)
    at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)
    at com.sun.proxy.$Proxy227.set(Unknown Source)
    at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.set(LettuceStringCommands.java:141)
    ... 23 common frames omitted
复制代码


上面是报错的信息,这个模块是一个同步模块,代码同事写的,就是把一些数据通过mq同步到数据库去,上面报错的就是因为堆外内存不够了,failed to allocate 855638016 byte(s) of direct memory (used: 985661440, max: 1823473664)


分析事故原因


首先我定位到代码处,把代码拿出来康康


在Rediss操作的时间报错了,然后网上各种百度,还真没找到具体的原因,不过自己定位了个大概。觉得有以下可能

  • 第一就是因为它这个是循环set 然后用的redis spring data连的redis redis导致的,然后我想着用Pipeline批量拆入会不会好一点,把它改成批量插入。对netty不熟悉导致的
  • 第二个就是确实是堆外内存不够了,默认情况下堆外内存是和堆内存的是一样的,但是我这个报错刚好是不够了,但是我只能暂时给他加大一点点,因为我不知道具体为啥会变大了这个还没排查出来,然后重启之后也没再出现这个错误了。。真的是玄学,唉d
  • 或者是get的时候 从redis中拿得数据放到了直接内存中??
  • 下次叫运维dump一下堆栈信息看看吧,这次没得搞了,已经重现不来了
  • 可以通过 -XX:MaxDirectMemorySize调整大小,内存不足时抛出 OutOfMemoryError或者OutOfMemoryError:Direct buffer memory ,目前我已经让运维设置的大了一点了
  • 后面我又想是不是因为这个服务一直在写数据,但是写的话虽然会创建很多对象,但是是在堆里面的,最多youngGC的时候就会把它清除了,并不会导致堆外内存溢出呀,百思不得其解


Redis客户端Lettuce源码【二】Lettuce是如何基于Netty建立连接的


结尾


其实也没啥,就是自己记录一下一些东西,哈哈。不过有大佬碰到的可以下面留言哦。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
Java fastjson C++
JVM内存问题之JVM中元空间持续增长并且GC无法释放的原因可能是什么
JVM内存问题之JVM中元空间持续增长并且GC无法释放的原因可能是什么
188 2
|
4月前
|
Java Linux
JVM内存问题之在业务有损的情况下,遇到JAVA内存使用率高的问题,应该如何快速止损
JVM内存问题之在业务有损的情况下,遇到JAVA内存使用率高的问题,应该如何快速止损
|
4月前
|
监控 Java Linux
JVM内存问题之如果堆内存一直缓慢上涨,如何解决
JVM内存问题之如果堆内存一直缓慢上涨,如何解决
607 1
|
存储 Java 应用服务中间件
JVM各种情况内存溢出分析
JVM各种情况内存溢出分析
233 0
|
算法 Java 流计算
如何避免内存溢出和频繁的垃圾回收
代码明明简单,日常跑没问题,怎么一大促就卡死甚至进程挂掉?大多因为设计时,就没针对高并发、高吞吐量case考虑过内存管理。
171 0
|
Java fastjson 数据库
线上环境内存溢出-OutofMemoryError
公司线上环境,出现内存溢出异常,发生时,cpu占用360%。系统可用内存不足。
277 1
线上环境内存溢出-OutofMemoryError
|
监控 Java 数据安全/隐私保护
JVM频繁GC内存溢出排查
GC(Garbage collection)频繁和堆内存溢出原因简单来说是对象占用堆空间难以回收,新对象无法分配触发GC或者直接导致内存溢出,最终进程结束。
465 0
|
消息中间件 运维 监控
一次完整的JVM堆外内存泄漏故障排查记录
记录一次线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些JVM内存分配机制以及常用的JVM问题排查指令和工具分享,希望对大家有所帮助。 在整个排查过程中,我也走了不少弯路,但是在文章中我仍然会把完整的思路和想法写出来,当做一次经验教训,给后人参考,文章最后也总结了下内存泄漏问题快速排查的几个原则。
1243 0
|
Dubbo Java 应用服务中间件
线上报了内存溢出异常,又不完全是内存溢出
最近一直忙于对付即将上线的系统,期间也碰到了很多问题。最近印象比较深的是一个内存溢出的报错。测试告诉我最近某个功能总是没有效果,于是我就去线上看了一下错误日志,这不看不知道,一看吓一跳,满屏的OutOfMemoryError ,出于隐私保护,这里只展示其中的一点异常信息:
|
监控 前端开发 算法
全网最硬核 JVM TLAB 分析(额外加菜) 8. 通过 JFR 监控 TLAB
全网最硬核 JVM TLAB 分析(额外加菜) 8. 通过 JFR 监控 TLAB