4.3 Elasticsearch-百分比、采样、移动平均、季节分解

在这里插入图片描述

4.3 Elasticsearch-百分比、采样、移动平均、季节分解

4.3.1 百分比(Percentiles)

在监控与告警场景里,平均值往往掩盖长尾延迟。Elasticsearch 通过 percentiles 聚合把整条延迟分布切成 100 份,常用 P50、P90、P99、P99.9 四档即可看清“最慢 1 % 请求”到底慢到什么程度。

语法要点

GET latency-*/_search?size=0
{
  "aggs": {
    "latency_percentiles": {
      "percentiles": {
        "field": "duration",
        "percents": [50, 90, 99, 99.9],
        "keyed": true,
        "tdigest": { "compression": 200 }   // 精度 vs 内存权衡,默认 100
      }
    }
  }
}
  • tdigest 是 ES 7.x 默认算法,单分片误差 < 1 %,内存占用与 compression 成正比;
  • 若需精确值,可在索引映射里把 duration 设为 histogramscaled_float + ignore_malformed,再用 percentile_ranks 反查“超过某阈值的请求占比”。

实战技巧

  1. 做 SLA 看板时,把 P99 与 P50 的差值命名为“长尾抖动”,差值突然放大即可触发告警;
  2. 对比灰度版本:用 filters 子聚合把流量按 version 字段拆成 A/B 两组,再分别算 P99,一眼看出新版本是否把尾巴拖长。

4.3.2 采样(Sampler & Diversified Sampler)

全量聚合在十亿级文档上跑 P99 会直接把 data node 打爆。ES 提供两种采样聚合,用少量数据换 95 % 的精度。

1. Sampler

"aggs": {
  "sample": {
    "sampler": { "shard_size": 10000 },   // 每个分片最多取 1 w 条
    "aggs": {
      "significant_errors": {
        "significant_terms": { "field": "error.message" }
      }
    }
  }
}
  • 先随机采样,再跑子聚合,显著降低内存;
  • 适合日志关键词突增、错误码聚类等 exploratory 场景。

2. Diversified Sampler
在采样时再加“去重”规则,保证同一用户、同一session不会被过度代表:

"diversified_sampler": {
  "shard_size": 5000,
  "field": "user_id",          // 每个 user_id 最多取 1 条
  "max_docs_per_value": 1
}
  • 做 A/B 实验时,用该聚合抽取“独立用户”延迟,可消除重度用户带来的偏差。

4.3.3 移动平均(Moving Average & Moving Function)

时序面板里最常见的降噪手段。ES 从 2.x 起内置 moving_avg 管道聚合,6.4 以后又加入更灵活的 moving_fn,支持自定义脚本。

1. 简单线性平滑

"moving_avg": {
  "buckets_path": "avg_latency",
  "window": 10,
  "model": "linear",
  "minimize": false
}
  • window=10 表示用前后 10 个桶做滑动窗口;
  • model 可选 linearewmaholt_winters,后者可叠加趋势与季节性。

2. 脚本化窗口(moving_fn)

"moving_fn": {
  "buckets_path": "avg_latency",
  "window": 7,
  "script": "MovingFunctions.unweightedAvg(values)"   // 也可写标准差、中位数
}
  • 支持 values.length 动态判断边缘桶,避免头尾缺值造成的陡降;
  • 若想写“环比上周同期”,可在脚本里用 values[values.length-8] 做跨周期对比。

可视化落地
Kibana Lens 里把指标拖到 Y 轴 → 添加“移动平均”层,窗口大小直接下拉选择;或者 TSVB 里用 “Series Agg → Moving Average” 并勾选 “Treat gaps as zeros”,即可在 5 秒内完成平滑曲线。


4.3.4 季节分解(Seasonal Decompose & ML Forecast)

移动平均只能降噪,无法把趋势、周期、残差拆开。ES 官方推荐两条路线:

  1. transform + pivot 把数据按“周×小时” 24×7 矩阵重聚合,再手写脚本算同期平均,做减法拿到残差;
  2. 直接上 Machine Learning 模块,一条 API 完成趋势+周期+异常检测。

方案 A:纯聚合手写分解
步骤:

  1. date_histogram 把 metrics 聚合成 1 h 桶;
  2. bucket_script 计算“同期历史平均值”:
"seasonal_baseline": {
  "bucket_script": {
    "buckets_path": {
      "hist": "history_avg",      // 过去 4 周同一小时平均值
      "real": "current_avg"
    },
    "script": "params.real - params.hist"
  }
}
  1. 残差 > 3 σ 即认为异常。
    优点:零依赖、轻量;缺点:只能处理单周期(周),且需自己维护历史基线索引。

方案 B:ML Forecast(开箱即用)

PUT _ml/anomaly-detector/service_latency
{
  "analysis_config": {
    "bucket_span": "1h",
    "detectors": [{
      "function": "mean",
      "field_name": "duration",
      "by_field_name": "service"
    }],
    "influencers": ["service", "az"]
  },
  "data_description": {
    "time_field": "@timestamp"
  },
  "model_plot_config": { "enabled": true }
}
  • 自动识别每日、每周、每月多重季节;
  • 实时输出 lower, upper, prediction 三列,残差超出边界即告警;
  • 支持 forecast=7d 一键生成未来 7 天容量预测,直接把曲线拖进 Kibana Dashboard 即可给老板汇报。

性能调优

  • bucket_span 设为采集周期的整数倍,避免边界抖动;
  • 对超大数据量启用 summary_count_field,把 1 min 原始点预聚合成 1 h 计数,模型训练提速 10 倍;
  • calendars 排除大促、节假日,否则模型会把人为峰值当成新的季节分量。

4.3.5 小结

百分比让你看到“最慢的 1 %”;采样让你用 1 % 的算力看清趋势;移动平均帮你把锯齿变平滑;季节分解则告诉你锯齿里哪些是周期、哪些是异常。四板斧组合起来,足以把 Elasticsearch 从“搜索引擎”升级成“轻量级时序分析平台”,而无需额外引入 Spark、Flink 这类重型框架。
更多技术文章见公众号: 大城市小农民

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔丹搞IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值