4. FTDC诊断数据深度利用

FTDC(Full Time Diagnostic Data Capture)是 MongoDB 3.2 之后内置的“黑匣子”式诊断数据采集机制。它不依赖外部监控代理,由 mongod/mongos 进程自身以固定周期采样运行状态,把结果压缩写入诊断目录。相比 serverStatus 的瞬时快照,FTDC 的价值在于“连续、低开销、可回溯”:当生产环境出现一次持续 90 秒的慢查询风暴或一次主从切换抖动时,事后仍能从 FTDC 中还原当时的连接数、队列、锁、WiredTiger 缓存、复制延迟等指标的变化曲线。

采集内容:FTDC 到底记录了什么

FTDC 的采样源主要是 serverStatus 及其子文档,并叠加部分 replSetGetStatus、collStats 摘要与主机指标。采样周期默认约 1 秒,但并非所有指标都每秒采集:部分较重的指标(如集合级统计)会以更低频率轮转采集,以控制开销。典型采集内容包括:

  • 连接与网络:current、available、totalCreated 连接数,以及 network 的 bytesIn/bytesOut、numRequests。
  • 操作与队列:opcounters 的 insert/query/update/delete/getmore/command,以及 globalLock 的 currentQueue(total、readers、writers)。
  • WiredTiger 缓存:cache 的 bytes currently in cache、maximum bytes configured、tracked dirty bytes、eviction 相关计数。
  • 存储引擎与磁盘:WT 的 concurrentTransactions(read/write available、out)、checkpoint 时间,以及磁盘空间使用。
  • 复制:replSetGetStatus 中的成员状态、optime、复制延迟(replication lag)。
  • 主机资源:CPU 使用率、内存、磁盘 IOPS/吞吐等由进程采集的主机侧指标。

这些指标共同构成一条时间序列。理解“哪些指标属于同一因果链”是后续分析的关键:例如连接数突增 → 队列积压 → 操作延迟上升 → 复制延迟扩大,往往是一条可被 FTDC 完整记录的故障传导路径。

存储机制:文件结构与轮转

FTDC 数据默认存放在 dbPath/diagnostic.data 目录下,文件名形如 metrics.2024-06-01T10-00-00Z-00000。每个文件内部由若干“块”组成,块内是经过压缩的 BSON 文档序列,并带有元数据描述字段的层级路径与类型。文件按大小和时间轮转,默认单文件约 100MB 左右,保留策略由 diagnosticDataCollectionDirectorySizeMB(默认约 200MB)和 diagnosticDataCollectionFileSizeMB 控制。当目录达到上限时,最旧的文件会被删除,因此 FTDC 只能保留最近一段时间的窗口——这正是容量规划中需要关注“诊断数据保留时长”的原因。

FTDC 的采样开销通常很低(约 1% 以内 CPU),但在极端高并发场景下仍建议观察其对 IO 的影响。可通过 setParameter diagnosticDataCollectionEnabled 临时关闭,但生产环境不建议长期关闭。

解析方法:从二进制到可读时间序列

FTDC 文件不能直接用文本编辑器打开,官方提供了 mongodump 之外的专用工具 mongod --ftdc 或 mongos 的 ftdc 子命令进行解码。常用方式有两种:

# 方式一:使用 mongod 解码为 JSON 行
mongod --ftdc --ftdcPath /data/db/diagnostic.data --ftdcOutput /tmp/ftdc.json

# 方式二:使用 mongodump 的 ftdc 模式(部分版本)
mongodump --ftdc --dbpath /data/db --out /tmp/ftdc_dump

解码后得到的是按时间戳排列的 JSON 文档。由于字段层级很深,直接阅读效率低,通常需要借助脚本提取关键路径。例如用 Python 读取并抽取连接数、队列和复制延迟:

import json, datetime

def load_ftdc(path):
    with open(path) as f:
        for line in f:
            yield json.loads(line)

for doc in load_ftdc('/tmp/ftdc.json'):
    ts = doc.get('start')
    ss = doc.get('serverStatus', {})
    conn = ss.get('connections', {}).get('current')
    q = ss.get('globalLock', {}).get('currentQueue', {}).get('total')
    print(ts, conn, q)

实际分析中,更推荐把解码结果导入时序数据库或直接生成 CSV,再用图表工具绘制曲线。关键字段路径需要提前确认,因为不同 MongoDB 版本的字段命名可能略有差异。

故障回溯:用 FTDC 还原一次慢查询风暴

假设某生产集群在 14:32 出现应用超时告警。运维人员事后从 FTDC 中提取 14:25–14:40 的数据,观察到以下变化:14:30 连接数从 800 快速升至 2200;14:31 全局队列 total 从 0 升至 47,其中 writers 占 40;14:32 WiredTiger 缓存中 dirty bytes 从 1.2GB 升至 3.8GB,eviction 次数明显增加;14:33 复制延迟从 0.2s 扩大到 12s。结合这些曲线可以判断:大量写操作导致缓存脏页堆积,eviction 压力上升,写队列积压,进而拖慢复制。进一步排查发现是某业务批量写入未加限流。FTDC 在这里的作用不是直接给出“根因”,而是提供了一条可验证的因果链证据。

趋势分析:从诊断数据到容量规划

FTDC 的另一类用途是长期趋势观察。虽然单文件保留窗口有限,但可以定期把解码后的关键指标归档到外部存储,形成跨周、跨月的数据集。容量规划中常关注的趋势包括:连接数峰值是否持续逼近 available 上限;WiredTiger 缓存使用率是否长期高于 80%;磁盘增长速率是否与业务增长匹配;复制延迟是否在业务高峰呈现周期性上升。把这些指标按天聚合后绘制趋势线,就能在资源耗尽前做出扩容或参数调整决策。

FTDC 采集 → 存储 → 解析 → 回溯/趋势 全链路 采集源 serverStatus replSetGetStatus collStats 摘要 主机 CPU/内存/IO 周期 ≈ 1s 存储 diagnostic.data/ metrics.<时间戳> 压缩 BSON 块 按大小/时间轮转 默认上限 ≈ 200MB 解析 mongod --ftdc → JSON 行 脚本提取字段 → CSV / 时序库 字段路径需版本确认 应用 故障回溯 趋势分析 容量规划 参数调优 典型故障传导链(FTDC 可完整记录) 连接数突增 connections.current 写队列积压 currentQueue.writers 缓存脏页升高 tracked dirty bytes eviction 压力 eviction 计数 复制延迟 replication lag 14:30 14:31 14:32 14:33 14:34 时间轴:FTDC 按秒采样,可还原每个节点的变化时刻

实操要点与判断依据

要让 FTDC 真正可用,需要建立一套固定的分析流程。首先确认诊断目录位置和保留窗口:db.adminCommand({getParameter:1, diagnosticDataCollectionDirectorySizeMB:1}) 可查看当前上限。其次,定期归档解码后的关键指标,避免轮转后数据丢失。分析时优先关注“变化率”而非绝对值:连接数从 800 到 2200 的斜率、队列从 0 到 47 的持续时间、缓存脏页的增长速度,这些比单点数值更能说明问题。

判断是否达到容量瓶颈时,可参考以下经验阈值(示例,需结合业务调整):连接数持续超过 available 的 70%;WiredTiger 缓存使用率长期高于 80%;全局写队列持续大于 10;复制延迟在业务高峰超过 5 秒。当这些条件同时出现两项以上,就应启动扩容或参数优化评估。FTDC 提供的是证据,最终决策仍需结合业务负载特征和压测结果。

FTDC 文件包含大量运行时细节,可能涉及敏感信息(如集合名、主机名)。归档和共享前应确认合规要求,必要时脱敏处理。

总结来说,FTDC 是 MongoDB 生产运维中成本最低、信息密度最高的诊断数据源之一。掌握它的采集范围、存储轮转规则、解码方法和分析思路,就能在故障发生后快速还原现场,并在日常趋势观察中提前发现容量风险。