一、Trace 采样基础概念
1.1 什么是 Trace 与 Span
在分布式系统中,一次用户请求往往需要经过多个微服务、中间件和数据库才能完成。为了完整记录这次请求的调用链路,业界引入了 Trace 和 Span 两个核心概念。
- Trace:代表一次完整的请求或事务在分布式系统中的端到端调用路径。一个 Trace 由多个 Span 组成,通过全局唯一的 TraceID 串联。
- Span:代表 Trace 中的一个独立工作单元,通常对应一次 RPC 调用、数据库查询或消息发送。每个 Span 记录开始时间、结束时间、状态、标签等元数据,并通过 SpanID 和 ParentSpanID 形成父子关系。
关键关系: Trace = 多个 Span 构成的树形结构。根 Span 是整个请求的入口,子 Span 是后续的逐级调用。
1.2 什么是采样率
采样率(Sampling Rate)是指系统决定保留并上报的 Trace 数量占全部产生 Trace 数量的比例。例如,采样率设为 0.1(10%),意味着每 10 个请求中只有 1 个的完整链路数据会被采集和存储。
| 采样率 | 含义 | 典型场景 |
|---|---|---|
| 100% (1.0) | 全量采样,所有 Trace 都保留 | 开发环境、低流量系统、安全审计 |
| 10% (0.1) | 每 10 个请求保留 1 个 | 中等流量生产环境 |
| 1% (0.01) | 每 100 个请求保留 1 个 | 高流量核心服务 |
| 0.1% (0.001) | 每 1000 个请求保留 1 个 | 极高吞吐量网关或边缘服务 |
实践建议:采样率不是越高越好。全量采样在每秒数万请求的场景下,存储成本和网络带宽会迅速失控。合理的采样策略需要在数据完整性和成本控制之间找到平衡点。
1.3 为什么需要采样
在分布式可观测性实践中,采样不是可选项,而是必选项。以下是驱动采样的四个核心原因:
- 存储成本控制:一个完整的 Trace 可能包含几十到上百个 Span,每个 Span 携带时间戳、标签、日志等元数据。全量存储会导致存储系统(如 Elasticsearch、ClickHouse)容量爆炸,运维成本急剧上升。
- 网络带宽限制:Agent 或 SDK 需要将 Trace 数据上报到后端 Collector。在高并发场景下,全量上报会占用大量内网带宽,甚至影响业务请求的响应时间。
- 后端处理压力:Collector、Query Service 和 UI 需要实时处理、索引和查询 Trace 数据。采样可以显著降低后端组件的 CPU 和内存负载,保证系统稳定性。
- 数据价值密度:在大量正常请求中,真正需要关注的异常、慢请求、错误链路占比通常很低。采样可以保留高价值数据(如错误 Trace),同时丢弃大量重复的正常 Trace,提高数据信噪比。
1.4 采样带来的挑战
采样虽然解决了成本和性能问题,但也引入了新的挑战——数据不完整。如果采样策略设计不当,会导致以下问题:
- 关键链路丢失:错误或慢请求恰好未被采样,导致问题排查时缺少关键证据。
- 统计偏差:基于采样数据计算的延迟、错误率等指标与真实值存在偏差,影响 SLO 评估准确性。
- 复盘口径不一致:不同团队(如开发、运维、QA)使用不同的采样策略,导致对同一问题的结论产生分歧——这正是本课程后续要重点解决的复盘口径校准问题。
注意:采样不是简单的“丢数据”,而是有策略地保留高价值数据。错误的采样策略比不采样更危险——它给你一种“数据还在”的错觉,但实际上关键信息可能已经被丢弃。
1.5 常见采样策略概览
| 策略名称 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 固定比率采样 | 按固定概率(如 10%)随机决定是否采样 | 实现简单,开销低 | 无法保证错误链路被捕获 |
| 基于头部采样 | 在 Trace 入口处决定是否采样,后续 Span 跟随 | 决策点单一,一致性高 | 无法根据 Span 内部状态动态调整 |
| 基于尾部采样 | 先收集所有 Span,在 Trace 完成后根据规则决定是否保留 | 可以精准保留错误/慢 Trace | 需要缓冲,内存开销大 |
| 概率+错误混合 | 错误 Trace 全量保留,正常 Trace 按概率采样 | 兼顾成本与关键数据 | 实现复杂度较高 |