服务异常跟踪

1、业务表现

服务不可用,转圈圈

2、上日志

Redisson + Netty 堆内存溢出(OOM)问题完整解决方案

你遇到的核心错误是:Java 堆内存不足,且溢出发生在 Redisson 编码发送 Redis 命令 的阶段(Netty 编码器),这是典型的大对象 / 大批量命令 / 内存配置不足导致的 OOM。

先给你最关键的结论:

这个 OOM 不是普通的内存泄漏,90% 是因为你一次性往 Redis 发送了超大数据 / 批量命令,或者 JVM 堆内存配置太小,Redisson 编码时直接撑爆了堆。

一、快速定位根因(3 个最常见原因)

结合你的日志(CommandEncoder/CommandBatchEncoder),问题来源只有这几种:

  1. 批量操作过大(最常见)使用 RBatch 批量执行几千 / 几万条 Redis 命令,Redisson 编码时会一次性加载所有命令到内存,直接溢出。
  2. 存储超大 Value往 Redis 塞超大对象 / 超大集合(比如 100MB + 的 JSON、List),序列化 + 编码时内存暴涨。
  3. JVM 堆内存默认配置太小生产环境 JVM 默认堆只有几百 MB,稍微大一点的操作就溢出。

二、立即生效的修复方案(按优先级执行)

1. 第一步:增大 JVM 堆内存(最快解决)

直接修改 Java 启动参数,这是最立竿见影的方案

# 推荐配置(根据服务器内存调整,最小给 2G 堆)
java -Xms2g -Xmx4g -jar your-app.jar

参数说明:

  • -Xms2g:初始堆内存 2GB
  • -Xmx4g:最大堆内存 4GB

服务器内存≥8G → 推荐 -Xmx4g -Xms4g;服务器内存≥16G → 推荐 -Xmx8g -Xms8g

2. 第二步:修复 Redisson 批量操作(核心问题)

如果你代码里用了 RBatch(批量命令),绝对不能一次性提交大量命令

❌ 错误写法(会 OOM):

RBatch batch = redisson.createBatch();
// 循环10万条命令,直接撑爆内存
for (int i = 0; i < 100000; i++) {
    batch.getMap("test").putAsync("key"+i, "value");
}
batch.execute();

✅ 正确写法(分批提交,每 1000 条执行一次):

// 每1000条命令提交一次,避免内存堆积
int batchSize = 1000; 
RBatch batch = redisson.createBatch();

for (int i = 0; i < 100000; i++) {
    batch.getMap("test").putAsync("key"+i, "value");
    
    // 达到阈值立即执行,清空内存
    if ((i + 1) % batchSize == 0) {
        batch.execute();
        batch = redisson.createBatch();
    }
}

// 执行剩余命令
if (batch.isActive()) {
    batch.execute();
}

3. 第三步:禁止存储超大 Value 到 Redis

❌ 不要存:

  • 10MB 以上的单个对象
  • 包含 10 万条数据的 List/Set
  • 超大 JSON 字符串

✅ 优化方案:

  1. 大对象拆分(分多个 key 存储)
  2. 大集合分页存储
  3. 使用二进制压缩(Redisson 支持 snappy 压缩)

Redisson 开启数据压缩(降低内存占用)

redisson.yml配置中添加:

threads: 16
nettyThreads: 32
codec: !<org.redisson.codec.SnappyCodec> {} # 开启压缩

4. 第四步:优化 Redisson 连接配置(防止堆积)

修改 Redisson 配置,限制命令队列大小,避免无限堆积撑爆内存:

singleServerConfig:
  address: "redis://127.0.0.1:6379"
  connectionMinimumIdleSize: 10
  connectionPoolSize: 64
  retryAttempts: 3
  retryInterval: 1000
  # 关键配置:限制每个连接的等待命令队列,防止无限堆积
  pendingQueueSize: 2000

三、高级排查:确认到底是什么占了内存

如果上面方案还没解决,你需要抓堆 dump分析:

  1. 添加 JVM 参数,自动生成内存溢出快照:shell
  2. JProfiler / Eclipse MAT 工具打开 dump 文件
  3. 直接查看:org.redisson相关对象占用的内存大小

你会直接看到:

  • 超大的CommandBatch对象
  • 超大的待发送 Redis 命令队列

四、总结:必做的 3 件事

  1. 加大 JVM 堆内存-Xms2g -Xmx4g 起步
  2. 拆分批量操作:RBatch 每 1000 条命令执行一次,不要无限累加
  3. 禁止超大 Value:拆分大对象、开启数据压缩

#牛客AI配图神器#

#面试时最害怕被问到的问题##机械人面试中的常问题##春招至今,你收到几个面试了?#
全部评论

相关推荐

昨天 16:57
Python
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务