高基数、采样与遥测成本:一个标签可能乘上百万时序
100 万 user_id 加进 metric label 不是"多一列",而是潜在乘出一百万条时间序列。本页算清基数乘积、头/尾采样的隐藏成本,以及"错误全保留"为什么算不出真实错误率。
基数是乘法不是加法
请求 ID、用户 ID、对象 ID、原始 URL 和异常消息适合放在受控日志/trace 属性中,通常不适合无界 metric label。每个维度组合可能产生独立时间序列。假设100个服务、20个实例、10条路由、5个状态类、8个直方图桶,若这些组合都出现,仅桶时序上界为80万,另有sum/count等。再加入100万user_id不是"多一列",而是潜在乘上用户维度,采集、内存、查询与账单都可能失控。真实组合不一定全出现,仍需测活跃与历史基数。
指标标签用有限类别,业务ID留受控日志/trace或账本。删除标签也可能失去诊断能力,应记录以何种替代证据查个体。敏感内容、凭据和完整请求体不进入通用遥测,采样不等于脱敏。
头采样、尾采样与缓冲
头采样在追踪开始时快速决策,但无法根据最终错误结果精确保留;尾部采样可保留慢请求和错误,但需要缓存足够长时间的 span 并承担更多资源成本。假设每秒2万trace、等待30秒、每trace平均4KiB,仅payload暂存约2.29GiB,未计索引、对象和重复跨度。
跨进程采样决定、迟到span、trace过长与缓存驱逐都会影响完整性。保留所有错误也不代表能从抽样总体无偏估算成功/错误率,统计指标应由适当计数链提供。OpenTelemetry采样概念见官方说明,具体collector处理器与配置另固定版本。
采样策略不能破坏统计与恢复
假设真实每秒10万请求,其中100个错误;成功trace采1%,错误trace全保。留下999个成功和100个错误,直接相除会得到约9.1%的错误率,而真实为0.1%。这不是系统突然变差,而是选择偏差。若要从样本估算总体,必须知道各类纳入概率并适当加权,还要处理丢弃和迟到;用于SLO的请求计数通常应走具有明确完整性和分母的独立指标链。
尾采样节点重启、负载均衡把同trace分散到不同节点、迟到span超过等待期,都会让"错误全保"变成不完整承诺。部署需要让同trace到达可共同判断的处理域,限制等待和内存,并监控缓存逐出、未决trace、丢弃和导出失败。敏感字段应尽早脱敏,不把稍后采样丢弃作为防泄漏策略。
设业务导出每秒2万trace、每trace4KiB,而下游中断60秒,若全部缓存在本地,原始payload就约4.58GiB,未含运行对象。选择有界队列可保护业务,但必须承认观测损失;同步阻塞业务线程虽看似不丢span,却可能把监控故障放大为业务故障。需要按业务重要性决定丢弃、持久缓冲和限速,而非无限加内存。
实验和失效保护
用有限维度生成指标,再加入每请求唯一ID,比较series数、内存与查询时延;只在隔离监控实例运行。尾采样使用已知trace大小与持续时间,故意延迟部分span,检查缓存驱逐与误判。遥测过载不能阻塞关键业务线程,应有有界队列、丢弃计数和自监控。
方案A逐用户指标适合严格受限小集合但极易膨胀;方案B有限指标加索引化日志降低在线成本,检索个体延迟可能更高。按每次成功业务的观测成本、可诊断问题和保留期比较,而非比较压缩后的单文件大小。
保留预算与降级顺序:先降采样再降维度
本页前面算了基数乘积与尾采样缓冲,但预算决策通常发生在月底:观测账单超了,先砍什么?答案有顺序——先降采样率、再降保留期、最后才降维度,因为降维度会永久失去某类问题的诊断能力,而降采样至少保留统计口径。
先建一个可复算的预算模型。假设每秒 2 万 trace、每 trace 4KiB、月预算 30,000GiB。全量采样时月容量 20,000×86,400×4×30/1024/1024≈197,753.9GiB,是预算的 6.6 倍;允许的采样率 30,000/197,753.9≈0.1517,即约 15%。这个数字必须与尾采样缓冲一起看:等待 30 秒的缓冲仍是 20,000×30×4KiB≈2.29GiB,采样不改变缓冲(缓冲发生在采样判定之前),所以降采样能省钱但不省峰值内存。
默认降级顺序(可按诊断损失重新排序)的理由:采样率降低只影响单条 trace 的可获得性,聚合指标与计数链应独立于采样(本页第 3 篇的选择偏差已经说明"错误全保"不能算总体错误率);保留期缩短影响事后复盘的可得窗口;降维度(去掉某个标签或整个信号)会让"按租户/区域/工作类型"的筛诊直接失效。因此顺序是采样率 → 保留期 → 维度,且每步都要检查"降级后还能不能回答筛诊单上的问题"。
执行 python3 labs/observability_models.py retention_budget:预期输出 tail_buffer_gib=2.29、monthly_gib_at_full=197753.9、max_sample_rate=0.1517。脚本只做容量算术,不含索引、对象存储与查询成本;真实账单结构与采样实现归 U64 的 Collector 实验。
两个合理选择:A 对所有信号统一降采样,简单但可能把关键错误也采掉;B 按信号分级——指标全保、错误 trace 全保、成功 trace 降采样,并用独立计数链兜底统计。本例选 B,代价是规则更多、需要验证每类信号的纳入概率;收益是预算降下来的同时,筛诊与统计都不失效。
架构师变化条件
把等待期从 30 秒延到 5 分钟以覆盖慢请求:尾采样缓冲升到约 22.9GiB,需分片处理域与驱逐预算。若合规要求跨区遥测脱敏,采样决策前就要完成字段过滤。观测预算减半时,先砍高基数维度还是降低采样率?答案取决于哪种损失先破坏诊断能力——用"每次成功业务的观测成本"重算两个方案。每次变化重算基数乘积与缓冲上界。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。