doris 3.1.4 fe是否内存泄露问题(glm分析)

Viewed 37

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节点是否发现类似内存泄露反馈?

1 Answers

我们内部分析下的~
您可以加我主页微信我们一起看看


该PR修复OOM问题:https://github.com/apache/doris/pull/59535
需要升级版本,建议到最新4.x