Skip to content

Doris3.1.4 FE OOM Heap Dump 分析报告(glm) #67199

Description

@wangcool

Search before asking

  • I had searched in the issues and found no similar issues.

Version

Doris FE OOM Heap Dump 分析报告

一、宕机概况

项目 详情
FE版本 Doris 3.1.4
JVM配置 -Xmx32768m -Xms32768m(32GB堆)
Java版本 OpenJDK 17.0.12
宕机时间 2026-08-17 ~10:54
FE启动时间 2026-08-03 16:05(运行约14天)
宕机原因 java.lang.OutOfMemoryError: Java heap space
Heap Dump 30.46GB,545,178,838个对象
重启后堆配置 48GB(-Xmx49152m

fe.out 关键输出

java.lang.OutOfMemoryError: Java heap space
Dumping heap to /data01/doris/fe/log/java_pid72774.hprof ...
Heap dump file created [30463119875 bytes in 98.764 secs]
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 72774"...

二、MAT分析结果

使用 Eclipse Memory Analyzer (MAT) 对 29GB Heap Dump 进行自动化分析,识别出两个泄漏嫌疑点,均指向同一线程 all-fe-session-mgr-pool-0

2.1 Problem Suspect 1:String 对象堆积(17.3GB,57.64%)

  • 180,268,901java.lang.String 实例,占用 17,305,670,752 字节(17.3GB,57.64%)
  • 被一个 Object[180,221,098] 数组引用(1.44GB)
  • 该数组由线程 all-fe-session-mgr-pool-0 持有

2.2 Problem Suspect 2:ConcurrentHashMap 膨胀(10.8GB,35.97%)

  • 一个 ConcurrentHashMap$Node[268,435,456](2^28 个桶)占用 10,800,711,176 字节(10.8GB,35.97%)
  • 包含 180,239,068 个 Node 条目
  • 同样由线程 all-fe-session-mgr-pool-0 持有

2.3 OOM 触发时的线程栈

at java.lang.OutOfMemoryError.<init>() (OutOfMemoryError.java:48)
at java.util.Arrays.copyOf() (Arrays.java:3481)
at java.util.concurrent.ConcurrentHashMap$CollectionView.toArray() (ConcurrentHashMap.java:4471)
at java.util.ArrayList.<init>() (ArrayList.java:181)
at org.apache.doris.catalog.Env.getAllAliveSessionIds() (Env.java:7031)
at org.apache.doris.catalog.FESessionMgr$FEAliveSessionHandler.run() (FESessionMgr.java:94)
at java.util.concurrent.Executors$RunnableAdapter.call() (Executors.java:539)
at java.util.concurrent.FutureTask.run() (FutureTask.java:264)
at java.util.concurrent.ThreadPoolExecutor.runWorker() (ThreadPoolExecutor.java:1136)
at java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:635)
at java.lang.Thread.run() (Thread.java:842)

2.4 MAT Top Consumers(支配树最大对象)

对象类型 实例数 Shallow Heap Retained Heap 占比
ConcurrentHashMap$Node[] 5 2,147,483,672 10,806,532,600 35.99%
java.lang.Thread (all-fe-session-mgr-pool-0) 1 160 1,441,778,504 4.80%
java.lang.String 180,268,901 5,768,604,832 17,305,670,752 57.64%

2.5 MAT Class Histogram(Top 10)

类名 对象数 Shallow Heap Retained Heap
java.lang.String 180,549,648 5,777,588,736 >=17,339,850,056
byte[] 180,690,113 11,773,285,544 >=11,773,285,544
ConcurrentHashMap$Node[] 25,884 2,151,264,016 >=10,849,355,368
ConcurrentHashMap$Node 180,353,465 8,656,966,320 >=8,678,776,232
java.lang.Object[] 96,712 1,471,594,280 >=1,568,369,392
java.lang.Thread 448 71,680 >=1,447,339,640
com.sleepycat.je.tree.BIN 1,054 278,256 >=106,519,560
com.sleepycat.je.tree.IN 1,062 25,488 >=103,781,928
com.sleepycat.je.tree.Node[] 1,075 1,113,704 >=103,757,984
com.sleepycat.je.tree.LN 132,262 4,232,384 >=102,644,392

2.6 MAT 系统概览

项目
Heap Dump 大小 28 GB
对象总数 545,178,838
类总数 27,765
类加载器总数 309
GC Roots 4,316
不可达对象 170,284(仅21MB)

关键发现:545M 对象中仅有 170,284 个不可达对象(21MB),几乎所有对象都是存活且无法回收的泄漏对象。

三、根因分析

3.1 根本原因:FE Session ID 泄漏

FESessionMgr 中的 aliveSessionIds ConcurrentHashMap 持续累积了约 1.8 亿个 Session ID,从未被有效清理。

3.2 泄漏机制详解

客户端高频创建连接
    |
    v
每次连接产生一个 Session ID,存入 aliveSessionIds (ConcurrentHashMap)
    |
    v
连接关闭后 Session ID 仍留在 map 中,等待定期清理
    |
    v
清理线程 all-fe-session-mgr-pool 队列满,清理任务被拒绝 (RejectedExecutionException)
    |
    v
FE 间同步也失败 (Socket is closed by peer / Connection refused)
    |
    v
Session ID 只增不减,14天累积 1.8 亿条目
    |
    v
FEAliveSessionHandler 定期调用 Env.getAllAliveSessionIds()
    -> new ArrayList(sessionIds.keySet())  <-- 1.8亿条目全量拷贝
    -> OOM

3.3 内存分布

对象类型 实例数 内存占用 占比
String(Session ID) 180,549,648 17.3GB 57.64%
ConcurrentHashMap$Node[] 5 10.8GB 35.99%
ConcurrentHashMap$Node 180,353,465 8.7GB (含在上面)
合计 ~545M ~28GB 93.6%

3.4 清理机制失效时间线

日期 all-fe-session-mgr-pool 队列满次数 说明
8/12 0 正常
8/13 0 正常
8/14 8 首次出现清理任务被拒绝
8/15 6 持续恶化
8/16 4 持续恶化
8/17 27 密集爆发,最终OOM

3.5 完整事件时间线

时间 事件
8/3 16:05 FE启动,32GB堆
8/14 首次出现 RejectedExecutionException: queue size is full: all-fe-session-mgr-pool(8次)
8/15-16 队列满错误持续(6次、4次)
8/17 09:09 队列满错误密集爆发
8/17 09:18 Full GC后残留内存已达24GB,无法回收
8/17 10:42-10:55 连续 Full GC,每次耗时20+秒,GC后残留25-27GB
8/17 10:54:17 PUBLISH_VERSION_EXEC 写BDB耗时19305ms,锁持有18.4秒
8/17 ~10:54 Env.getAllAliveSessionIds() 触发 OOM
8/17 10:55:29 最后一次 Full GC:27GB存活对象,GC耗时21秒
8/17 10:57 Heap Dump 生成完毕(30.46GB)
8/17 10:57 kill -9 终止进程

3.6 GC 日志分析

8/17 10:42:45  Full GC: 32402M -> 24621M  (2572ms)   <- Full GC后仍残留24GB
8/17 10:43:37  Full GC: 31488M -> 25845M  (3236ms)
8/17 10:44:27  Full GC: 27244M -> 25830M  (3097ms)
...
8/17 10:54:48  Full GC前: 27134388088 bytes (~27GB)
8/17 10:54:56  Full GC后: 27145836592 bytes (~27GB)  <- 几乎无法回收
8/17 10:55:07  Full GC后: 27134575736 bytes (~27GB)
8/17 10:55:21  Full GC后: 27134388088 bytes (~27GB)  <- 最后一次,21秒

Full GC 后仅能回收几百MB,27GB为存活无法回收的泄漏对象。

四、业务负载分析

4.1 审计日志统计(8/17当天)

语句类型 数量
TRANSACTION 99,706
SELECT 80,998
SET 36,985
INSERT 8,290
SHOW 7,584
CREATE 1,817
DELETE 483

4.2 用户请求分布

用户 INSERT/TRANSACTION 数 占比
prod_qd_ab_wxh_w 101,911 95.5%
prod_cd_option_w 3,353 3.1%
test_cd_option_w 2,603 2.4%
admin 121 0.1%
prod_cd_raven_w 8 <0.1%

4.3 prod_qd_ab_wxh_w 语句分布

语句类型 数量
TRANSACTION 99,655
SELECT 51,982
SET 2,340
INSERT 2,256
CREATE 1,817
DELETE 441

4.4 典型业务SQL

崩溃前的主要负载为每分钟执行复杂 CTE 的 INSERT 语句:

INSERT INTO position_by_minute
WITH current_minute_changes AS (
    SELECT instrument_id, MAX(produce_time) as max_time
    FROM position
    WHERE produce_time > 1786934880000000000
      AND produce_time <= 1786934940000000000
      AND expiry_date >= date '20260817'
    GROUP BY instrument_id
),
current_records AS (
    SELECT base.*
    FROM position base
    JOIN current_minute_changes cmc
      ON base.instrument_id = cmc.instrument_id
      AND base.produce_time = cmc.max_time
),
previous_snapshot_max_time AS (
    SELECT prev.instrument_id, MAX(prev.produce_time) as prev_max_time
    FROM position_by_minute prev
    WHERE prev.snapshot_minute = '2026-08-17 10:48:00'
      AND prev.zs_trading_date = 20260817
      AND NOT EXISTS (
        SELECT 1 FROM current_minute_changes cmc
        WHERE prev.instrument_id = cmc.instrument_id
      )
    GROUP BY prev.instrument_id
),
...
SELECT '2026-08-17 10:49:00' as snapshot_minute, curr.*, 20260817 as zs_trading_date
FROM current_records curr
UNION ALL
SELECT '2026-08-17 10:49:00' as snapshot_minute, prev.*, 20260817 as zs_trading_date
FROM previous_base_records prev

查询特征:扫描 57M 行 / 62GB,峰值内存 752MB,CpuTimeMS 高达 329,538。

4.5 连接模式

  • 客户端:MySQL Connector/J 8.0.33
  • 来源:全部来自 172.24.16.108
  • 模式:高频创建/断开连接(每分钟INSERT + 连接验证 + SET操作)

4.6 group_commit 问题

日志中还发现 group_commit 相关的事务冲突:

AnalysisException: begin transaction failed.
  Label [group_commit_0a474c8412a331d3_cedb28f79ff3758e] has already been used,
  relate to txn [3116755], status [PREPARE]

五、客户端正常close能否避免OOM

结论:不能完全避免

5.1 原因一:aliveSessionIds 的清理与连接关闭是解耦的

MAT 堆栈显示泄漏发生在 FESessionMgr$FEAliveSessionHandler.run() -> Env.getAllAliveSessionIds()。这是一个定期守护线程,通过跨 FE 同步来清理过期 session ID,不是在连接 close 时触发的。

即使客户端正常 close 连接,session ID 仍然留在 aliveSessionIds map 中,等待下次定期清理。而清理机制本身已经失效了。

5.2 原因二:清理机制从8月14日就已失效

8/14 RejectedExecutionException: queue size is full: all-fe-session-mgr-pool (8次)
8/15 同上 (6次)
8/16 同上 (4次)
8/17 同上 (27次) <- 密集爆发

线程池队列满了,清理任务被拒绝执行。同时 FE 间同步也失败:

Error occurred when get alive session from 172.24.16.108, msg = Socket is closed by peer
Error occurred when get alive session from 172.24.16.109, msg = Socket is closed by peer

清理线程跑不起来 -> session ID 只增不减 -> 14天累积1.8亿条目 -> OOM

5.3 原因三:prod_qd_ab_wxh_w 是最大贡献者

该用户单日执行了近10万次 TRANSACTION + 2256次 INSERT,全部来自 172.24.16.108。按14天外推,产生了大量 session。

5.4 客户端正常close的效果

措施 效果
客户端正常close连接 减少session创建速率,延缓OOM发生
但无法阻止 清理机制失效后,即使close了,session ID仍在map中
OOM触发点 与连接关闭无关,是定期清理任务自身在拷贝时OOM

5.5 根本结论

这是 Doris 3.1.4 的服务端Bug,不是单纯的客户端问题:

  1. FESessionMgraliveSessionIds 缺少有效的过期清理机制 — 只依赖跨 FE 定期同步,一旦同步失败就只增不减
  2. all-fe-session-mgr-pool 线程池队列太小 — 高并发下队列满,清理任务被拒绝
  3. Env.getAllAliveSessionIds() 实现有缺陷 — 直接 new ArrayList(keySet()) 全量拷贝,session 数量大时必然 OOM

即使3个用户全部正常close,只要清理机制失效,session ID仍会累积到OOM。 正常close只能减缓累积速度,不能根本解决问题。
我的问题是,目前Doris3.1.4 fe节点是否发现类似内存泄露反馈?

What's Wrong?

我的问题是,目前Doris3.1.4 fe节点是否发现类似内存泄露反馈?

What You Expected?

确认Doris3.1.4 fe节点是否存在内存泄露问题

How to Reproduce?

No response

Anything Else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions