BE 因导入内存过高接近 OOM,运维把 Load 内存比例砍半。进程稳定了两小时,随后小文件增多、Compaction Score 上涨、查询变慢,最终又出现导入拒绝。
内存没有消失,它被换成了更频繁的 Flush 和更长的后台合并账单。
降低 MemTable 内存是止血动作,不是免费优化。Flush 提前发生时,内存压力会转化为文件数量、写放大和 Compaction 压力。
三种动作解决的是三个不同问题
下面的对比固定总写入量和目标吞吐,只改变内存阈值、并发与批次形态。
| 动作 | 直接效果 | 隐藏代价 | 适用条件 |
|---|---|---|---|
| 降低 Load 内存阈值 | 更早触发 Flush,降低峰值 | 更多小 Segment 和 Rowset | OOM 紧急止血 |
| 降低导入并发 | 同时存在的 MemTable 更少 | 吞吐下降、上游积压 | 多任务并发导致峰值 |
| 增大有效批次 | 每次 Flush 数据更充实 | 可见延迟与客户端缓存增加 | 高频小批造成碎片 |
只调内存阈值,相当于把内存不足改写成存储引擎持续还债。
写入内存的关键链路
Load Memory Analysis 将导入内存分为执行 Fragment 和 Channel 写入两部分。数据进入 Channel 后构建 MemTable,随后由 Delta Writer 压缩并落盘。
Load Fragment 读取与转换 → Tablet Channel 分发 → 每个活跃 Tablet 构建 MemTable → 达到阈值或全局压力后 Flush → Segment/Rowset 落盘 → 后台 Compaction 合并一次导入同时触达大量分区和 Bucket,会创建更多活跃 MemTable。即使单表数据量不大,宽表、并发任务和分散 Tablet 也能把总内存推高。
先证明内存究竟在哪
BE Web 页面/mem_tracker?type=global中,AllMemTableMemory代表 MemTable 构建与 Flush 使用的总内存。/mem_tracker?type=load可继续定位到具体 LoadID 和 TabletID。
判断分支很简单:
AllMemTableMemory高:查活跃 MemTable、导入并发、批次和 Flush;AllMemTableMemory低但 Load Tracker 高:查解析、表达式、排序或其他 Fragment 内存;- 进程 RSS 高但 Tracker 不高:不要盲调 Load 参数,继续查缓存和非跟踪内存。
没有这一步,降低 Load 比例可能完全没有命中真正的内存来源。
用一个实验看见压力转移
固定同一份数据、同一表和相同总吞吐,只改变内存阈值与并发。每组运行至少覆盖一个完整 Compaction 周期,记录:
| 指标 | 预期观察 |
|---|---|
AllMemTableMemory峰值 | 降阈值后下降 |
| Flush 次数与平均 Flush 大小 | 次数上升、单次变小 |
| Segment/Rowset 增速 | 小文件增多 |
| Compaction Score | 延迟上涨则说明债务累积 |
| 导入可见延迟与查询 P99 | 判断压力是否转移给前台 |
如果只看到内存下降就宣布成功,测试实际上只完成了一半。
真正有效的处理顺序
立即止血
降低导入并发或暂停最重任务,必要时小幅降低 Load 内存阈值。动作目标是避免 BE 被 OOM Killer 终止,不追求此时吞吐最大化。
修正形态
- 合并小批次,减少每分钟事务数;
- 避免单批同时打散到过多分区和 Tablet;
- 宽表保持 Vertical Compaction,降低后台合并内存;
- 观察 Flush 线程是否跟不上,而不是只调
write_buffer_size; - 将导入与重查询错峰或隔离资源。
验证闭环
恢复目标吞吐后,要求 BE 内存有余量、Flush 平均大小稳定、Compaction Score 不呈单调上涨、查询 P99 不退化。任何一个不成立,都只是换了一种事故。
源码值得追的是触发 Flush 的三个入口
固定 Doris4.0.8后,源码只追:单 MemTable 达到写缓冲阈值、全局 Load 内存压力触发 Hook Flush、Flush 线程池把内存结构写成 Segment。再向后接 Compaction 输入 Rowset 数,才能看到调小阈值的完整副作用。
4.0 系列还引入了更自适应的写缓冲和动态 Flush 能力,但自动机制不能修复无限并发、极端小批和热点 Tablet。
内存参数决定何时落盘,批次与并发决定落盘多少次。只改前者,通常是在用未来的 Compaction 换眼前的安全。
官方资料
- Load Memory Analysis
- BE Configuration
- Vertical Compaction
- Data Compaction