摘要
2013 年,Foursquare 的 MongoDB 工作集超过可用 RAM,触发频繁磁盘换页(thrashing)。其查询访问模式局部性差,数据难以留在内存,数据库响应急剧恶化直至 OOM 崩溃,主站宕机约 17 小时,跨越两个自然日。
# 数据长大了,内存装不下,磁盘跟不上——经典容量墙。
时间线
故障前数据集增长逼近内存上限
某日工作集超 RAM,换页剧增,延迟飙升
随后OOM 崩溃,服务不可用
~17h 后完成数据分片 / 扩容恢复
根因
Foursquare 当时采用单分片 MongoDB,所有热数据依赖一台机器的物理内存。随着用户与签到数据增长,数据库的「工作集」(频繁访问的数据页 + 索引)逐渐超过可用 RAM,MongoDB 被迫频繁从磁盘换页(page fault / thrashing),查询延迟急剧恶化;而业务的查询访问模式局部性差,数据难以驻留内存缓存,换页进一步加剧,最终触发 OOM 崩溃,主站不可用。
- 单分片架构无水平扩展能力,工作集上限被单机内存锁死。
- 内存是硬约束:工作集超 RAM 必触发换页 → 延迟雪崩 → OOM。
- 查询访问模式局部性差,缓存命中率低,加剧换页。
- 容量规划未随数据增长提前扩容 / 分片,监控也未对内存使用设阈值告警。
放大因素
单分片架构无水平扩展;读放大 + 换页形成正反馈;恢复需长时间数据平衡(分片 / 迁移),拖长 MTTR。
缓解措施
- 提前分片,保证工作集可放入内存。
- 容量监控与预测,设定内存使用阈值告警。
- 优化查询局部性 / 加缓存层。
经验教训
内存是数据库的硬约束,工作集超 RAM 必崩;容量规划必须前置,不能等宕机才分片。
检查清单
- 确认工作集 vs 可用内存
- 检查换页 / 磁盘 IO 是否异常
- 验证分片与扩容策略
- 复盘容量监控阈值
- 评估查询局部性优化空间