You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis实例遭OOM Killer终止:如何排查内存溢出问题?

问题描述

使用bun-redis存储数百个WebSocket连接的实时数据,数据淘汰策略设为10天,近期遇到OOM Killer终止进程的问题:

A process of this unit has been killed by the OOM killer.
Killing process 77506 (HeapHelper) with signal SIGKILL.
Failed with result 'oom-kill'.
Consumed 1d 22h 10min 6.378s CPU time.

系统内存状态(OOM发生后):

~ ❯ free -h
               total        used        free      shared  buff/cache   available
Mem:            27Gi       7.4Gi        18Gi        11Mi       1.1Gi        19Gi

Redis内存统计:

127.0.0.1:6379> MEMORY STATS
 1) "peak.allocated"
 2) (integer) 4547468208
 3) "total.allocated"
 4) (integer) 4547247816
 5) "startup.allocated"
 6) (integer) 1069176
 7) "replication.backlog"
 8) (integer) 0
 9) "clients.slaves"
10) (integer) 0
11) "clients.normal"
12) (integer) 1928
13) "cluster.links"
14) (integer) 0
15) "aof.buffer"
16) (integer) 0
17) "lua.caches"
18) (integer) 0
19) "functions.caches"
20) (integer) 184
21) "db.0"
22) 1) "overhead.hashtable.main"
    2) (integer) 241912
    3) "overhead.hashtable.expires"
    4) (integer) 88
23) "overhead.total"
24) (integer) 1313288
25) "keys.count"
26) (integer) 4408
27) "keys.bytes-per-key"
28) (integer) 1031347
29) "dataset.bytes"
30) (integer) 4545934528
31) "dataset.percentage"
32) "99.99462890625"
33) "peak.percentage"
34) "99.99514770507813"
35) "allocator.allocated"
36) (integer) 4547537240
37) "allocator.active"
38) (integer) 4547805184
39) "allocator.resident"
40) (integer) 4695977984
41) "allocator-fragmentation.ratio"
42) "1.000058889389038"
43) "allocator-fragmentation.bytes"
44) (integer) 267944
45) "allocator-rss.ratio"
46) "1.0325812101364136"
47) "allocator-rss.bytes"
48) (integer) 148172800
49) "rss-overhead.ratio"
50) "1.0022660493850708"
51) "rss-overhead.bytes"
52) (integer) 10641408
53) "fragmentation"
54) "1.0350526571273804"
55) "fragmentation.bytes"
56) (integer) 159392128

可见Redis峰值内存仅约4.5GB,系统仍有大量剩余内存。重启Redis时的加载信息显示,RDB文件创建时内存占用达23946.19 Mb(约23.4GB):

5:09:46.782 * <search> Loading event starts
5:09:46.782 * Loading RDB produced by version 255.255.255
5:09:46.782 * RDB age 53411 seconds
5:09:46.782 * RDB memory usage when created 23946.19 Mb
5:09:53.947 * Done loading RDB, keys loaded: 4408, keys expired: 0.
5:09:53.947 # <search> Skip background reindex scan, redis version contains loaded event.
5:09:53.947 * <search> Loading event ends
5:09:53.947 * DB loaded from disk: 7.166 seconds
排查方向
  • 重点监控HeapHelper进程的内存变化
    HeapHelper是bun runtime负责内存管理的子进程,OOM Killer终止的是它而非Redis主进程,需确认:

    • 用top/htop或ps aux | grep HeapHelper实时追踪该进程的内存占用,看是否存在持续增长的泄漏情况。
    • 检查当前使用的bun版本,是否存在已知的HeapHelper内存泄漏bug(比如WebSocket连接、Redis客户端操作相关的内存未释放问题)。
  • 验证Redis数据淘汰策略的有效性
    重启时RDB创建时内存达23.4GB,但运行时Redis仅用4.5GB,说明数据集曾远大于当前规模,需排查:

    • 执行CONFIG GET maxmemory-policy确认淘汰策略是否正确配置为volatile-lru(对应带过期时间的key),同时检查maxmemory是否设置合理(若未设置,Redis会无限制占用内存)。
    • 随机抽样key执行TTL key,确认是否都正确设置了10天左右的过期时间,是否存在大量未设置过期的key导致数据堆积。
  • 排查WebSocket与bun-redis的内存泄漏
    数百个WebSocket连接可能存在资源未释放的情况:

    • 检查WebSocket连接断开时的清理逻辑,是否正确释放了关联的Redis客户端、缓存数据及相关对象,避免全局容器(如数组、Map)持续持有无效连接或消息数据。
    • 使用bun --inspect启动服务,通过Chrome DevTools的内存快照功能,分析是否有大量未释放的WebSocket实例、Redis客户端或消息对象堆积。
  • 分析OOM Killer的触发逻辑
    OOM Killer杀进程并非只看总内存,需确认:

    • 查看HeapHelper进程的OOM得分:cat /proc/[pid]/oom_score_adj,是否被设置为较高值导致优先被选中。
    • 查看系统日志dmesg | grep -i oom,获取OOM触发时的详细内存状态,确认是否有其他进程突发占用内存,或Redis开启了mlockall(执行CONFIG GET mlockall)锁定内存,导致系统可用内存被压缩。
  • 优化bun-redis客户端的使用
    Redis统计显示有1928个普通客户端,远超WebSocket连接数,需排查:

    • 检查bun-redis的连接池配置,是否复用了客户端连接,避免每个WebSocket连接创建新的Redis客户端导致连接泄漏。
    • 尽量使用批量操作(如MSET、HMSET)代替单个操作,减少客户端交互的内存开销。
    • 检查是否有大量未处理的Redis响应堆积在客户端缓冲区,导致HeapHelper内存占用上升。

内容的提问来源于stack exchange,提问作者xtyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:49:54