可观测性系统如何控制高基数?
简化版
高基数是标签组合产生大量时间序列,典型来源是 userId、requestId、URL 原始路径和无界错误文本。应在埋点、采集器和后端三层限制标签集合,把单实体明细放入日志或 Trace,而不是指标。
详细版
上线前估算组合基数,使用 route template、错误码和受控枚举;Collector 删除、归一或把无界值映射到受控集合,后端设置每指标/租户序列预算和拒绝告警。哈希不会减少唯一值数量,只能在日志/Trace 等明细信号中用于受控关联。持续监控活跃序列、新序列速率、每标签 top-N 与查询成本。
需要从指标下钻单请求时用 exemplar 关联采样 Trace。不能简单全局 drop 标签,否则会丢失故障维度;应按价值保留 region、status、release 等有限标签,并给例外设置 owner 与到期时间。
完整版教学
一、基数怎样相乘
一个指标有 100 个 endpoint、20 个 status、10 个 region、50 个 release,理论组合达 100×20×10×50=1,000,000 条序列。每加入一个无界标签,成本不是加法而是乘法。
易错点:高基数来自标签组合,不只是某一个标签值很多。
二、危险标签
| 标签 | 风险 | 替代 |
|---|---|---|
| userId/orderId | 无界增长 | 日志/Trace 字段 |
/orders/123 | 每资源一条 | /orders/:id |
| exception.message | 文本无界 | error_code |
| release | 有限但累积 | 只保活跃版本 |
哈希 userId 仍然保持原基数,不能解决时间序列数量问题。
三、埋点端治理
指标 API 只允许注册过的标签键和值域,HTTP 中间件使用路由模板而非原始 URL。未知错误归一为 OTHER,同时把具体堆栈写入日志。
代码评审和静态检查可阻止 requestId 等字段进入标签,比后端爆炸后清理便宜。
四、Collector 防线
Collector 可删除、重命名、聚合标签,并按租户应用策略。对于紧急异常,可临时丢弃产生爆炸的新序列,但要发告警并保留样例证据。
if label in [request_id,user_id]: drop label
if route unknown: route="OTHER"
五、后端预算
设置活跃序列上限、新序列每秒速率、查询扫描量和保留期。预算触发时优先保护平台稳定,同时返回明确拒绝指标,不能静默丢数据。
多租户按配额隔离,避免一个团队的新标签拖垮整个监控集群。
六、如何保留排障能力
低基数指标发现异常,exemplar 携带 traceId 指向代表性 Trace,再从 Trace 进入结构化日志。这样无需为每个请求建立时间序列,仍能看到具体样本。
采样策略需对错误和长尾保留更高概率,否则 exemplar 可能只指向健康请求。
序列预算还要考虑 churn:活跃序列总数暂时不高,但每分钟大量新旧 series 替换,同样会给索引和压缩带来压力。
清理历史高基数数据与阻止新数据是两件事,前者按存储生命周期执行,后者必须先修埋点或采集规则。
七、常见误区与追问
- 误区:标签值做哈希就不是高基数。 唯一值数量没有减少。
- 误区:存储便宜可以无限加标签。 索引、查询和内存仍会失控。
- 误区:删除所有标签最安全。 会失去定位区域和版本的能力。
- 误区:高基数只影响成本。 还会拖慢查询甚至使监控失效。
- 追问:如何估算基数? 计算各标签有效组合,并结合新序列速率实测。
- 追问:单用户问题怎么查? 用日志/Trace 字段和受控索引,不用指标标签。
- 追问:预算超限怎么办? 限制新序列、通知 owner、保留样本并修正埋点。
八、加强记忆
高基数治理按“埋点有限值域—Collector 清洗—后端配额—持续归因”分层。指标保留聚合维度,实体明细进入日志和 Trace,并用 exemplar 串联;预算超限要显式告警,既保护平台也保留故障证据。