topk 与 bottomk 是什么
topk(n, v) 返回分组内数值靠前的 n 条序列,bottomk 相反;常用于找出错误数偏多的服务、耗时最长的接口或容量最紧的实例。它可以对整个结果集取 Top,也可以用 by 子句对每个分组分别取前 n 条。返回的是原始序列及其数值,而不是排名序号或计数,理解这一点才能正确阅读图形。
基本信息
| 函数签名 | topk(n, instant-vector) / bottomk(n, instant-vector) |
|---|---|
| 分组写法 | topk(...) by (label) 每组各取 n 条 |
| 输入类型 | 瞬时向量(不能直接吃区间向量) |
| 返回内容 | 原值序列,不是序号或计数 |
| 参数 n | 每组保留的序列条数 |
| 适用版本 | Prometheus 全版本通用 |
典型使用场景
- 值班看板找出当前错误数最多的 5 个服务或实例
- 定位耗时最长的接口,配合 P99 面板下钻
- 按机房或集群分组,各自取 Top 排查本地异常
- 容量巡检挑出磁盘或内存水位最紧的若干节点
- 搭配阈值过滤,先筛异常再排名,缩小展示范围避免噪声
- 排障时对比 topk 与全量阈值命中,判断是全局问题还是局部问题
全局 Top 与分组 Top
全局 Top 与分组 Top
# 全局:错误数前 5 的序列
topk(5, sum by (instance, service) (rate(http_requests_total{code=~"5.."}[5m])))
# 分组:每个服务内错误数前 3 的实例
topk(3, sum by (service, instance) (rate(http_requests_total{code=~"5.."}[5m]))) by (service)
# 负向:找出内存余量最少的 5 个实例
bottomk(5, node_memory_MemAvailable_bytes)
# 先过阈值再排名,减少无关曲线
bottomk(5, node_filesystem_avail_bytes < 1e10)常见误读
| 现象 | 原因 | 正确理解 |
|---|---|---|
| 曲线来回跳 | topk 是瞬时快照,排名逐点变化 | 属正常,图上看排名更替 |
| 条数多于 n | 按分组后每组各取 n 条 | 总条数 = 分组数 × n |
| 空空无数据 | 底层选择器本身无数据 | 先单独跑内层表达式 |
| 值不是整数 | 返回的是原值而非排名序号 | 需要序号得另想办法 |
topk 是瞬时快照:序列排名会跳变,图形上曲线来回替换属于正常现象,不要当成数据抖动去排查。
要对区间数据排名,先把它聚合成瞬时向量:topk 只能作用于瞬时向量,直接套 [5m] 会报错,通常写成 topk(5, sum by (...) (rate(...[5m])))。
topk 与 sum 的组合顺序会改变结果:先 sum 再 topk 得到聚合后的排名,先 topk 再 sum 语义完全不同,按业务问题决定顺序。