登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis TDIGEST.TRIMMED_MEAN 怎样计算指定分位区间的均值

来源:17golang原创

时间:2026-10-27 08:48:04 137浏览 收藏

我第一次把延迟数据放进 TDigest,是为了避免每次统计都把原始样本全部取回应用层。后来遇到一个更具体的问题:平均响应时间不想被最低端和最高端的长尾牵着走,但又不想为了算一个区间均值重新读取明细。这正是 TDIGEST.TRIMMED_MEAN 的用处。

官方地址:https://redis.io/

TDIGEST.TRIMMED_MEAN key low_cut_quantile high_cut_quantile 会按照两个分位点保留中间区间,并从 TDigest 摘要中估算该区间的均值。比如传入 0.05 0.95,就是排除最低约 5% 和最高约 5% 的观测后计算截尾均值。

先把边界说清楚:它返回的是摘要上的估算值,不是重新扫描原始样本得到的精确算术平均值;两个参数表达的是分位点位置,不是要删除的百分比整数。

一、先确认你要的是哪一种均值

同一批延迟数据可以有三种不同问题。全量均值回答“所有观测的平均水平是多少”;中位数回答“中间位置在哪里”;截尾均值则回答“去掉两端指定分位区间后,中间这段数据的平均水平是多少”。如果偶发超长请求会把全量均值明显抬高,截尾均值通常更适合用来观察常态表现。

统计目标区间参数适用问题
全量均值不裁剪两端需要所有观测的总体平均
5%~95% 截尾均值0.05 0.95降低两端长尾对平均值的影响
中间一半均值0.25 0.75只观察更稳定的中心区间

参数应当从业务含义出发,而不是看到异常值就随意加大裁剪比例。线上报表最好同时保留样本量、P95 或 P99 与截尾均值,否则一个看起来更稳定的数字可能掩盖了长尾已经恶化。

Redis TDIGEST.TRIMMED_MEAN 低高分位点与保留区间的原创说明图
图1:两个分位点把观测值切成左尾、保留区间和右尾,命令只对中间区间做摘要估算。

二、先创建 TDigest,再把数据写入摘要

命令的第一个参数是已经存在的 TDigest key。下面用一组抽象的请求延迟做最小演示;真实项目中通常会在采集到一次观测时执行 TDIGEST.ADD,而不是把明细长期保存在 Redis 里。

# 创建一个保存延迟摘要的 key;重复创建同一个 key 时不要覆盖已有统计
TDIGEST.CREATE latency:api

# 将一批延迟观测加入摘要,单位统一使用毫秒
TDIGEST.ADD latency:api 42 48 51 55 60 63 71 85 96 120 180 420

# 查看摘要的最小信息,确认 key 已经有数据和可用的压缩摘要
TDIGEST.INFO latency:api

TDIGEST.ADD 接收的是观测值,后续命令使用的是摘要 key。两者不要混淆:low_cut_quantile 和 high_cut_quantile 不是延迟数值 50、500 这样的毫秒阈值,而是 0 到 1 之间的分位点。

三、用两个分位点计算指定区间的均值

如果目标是排除最低约 5% 和最高约 5% 的观测,可以这样调用:

# 保留 P05 到 P95 的中间区间,降低两端观测对均值的影响
TDIGEST.TRIMMED_MEAN latency:api 0.05 0.95

这里的 0.05 是 low_cut_quantile,表示保留范围的下边界;0.95 是 high_cut_quantile,表示保留范围的上边界。命令返回一个数值,即摘要对该分位区间均值的估算。

如果想把区间收窄到中间 50%,就把边界改为 0.25 0.75:

# 只估算 P25 到 P75 之间的中心区间均值
TDIGEST.TRIMMED_MEAN latency:api 0.25 0.75

我在报表里会把参数和结果一起记录,例如“P05-P95 trimmed mean”,而不只写一个孤立的平均值。这样下次调整裁剪范围时,读者能知道数字为什么变化。

四、参数顺序和返回值最容易误读的地方

调用时至少要满足 0 。顺序写反会让“保留区间”没有明确意义;把 5、95 直接传进去也不是 5% 和 95%,正确写法是 0.05、0.95。

# 正确:分位点使用 0 到 1 的小数,且下界在前
TDIGEST.TRIMMED_MEAN latency:api 0.05 0.95

# 错误示例:不要把百分数整数当成分位点,也不要颠倒上下界
# TDIGEST.TRIMMED_MEAN latency:api 5 95
# TDIGEST.TRIMMED_MEAN latency:api 0.95 0.05

另一个误区是把返回值当成精确均值。TDigest 是压缩摘要,命令根据摘要中的 centroids 估算区间均值;摘要越小、数据分布越复杂,估算与明细精确计算之间就可能有差异。因此,截尾均值适合趋势、看板和比较,不应在需要逐条审计的结算场景里替代明细计算。

Redis TDigest key、分位参数、截尾均值结果与 O(N) 成本的原创结构图
图2:从 TDigest key、两个分位参数到截尾均值结果的调用链,并标出参数边界和 centroids 数量。

五、按 centroids 数量理解性能成本

官方命令说明给出的复杂度是 O(N),其中 N 是摘要中的 centroids 数量。它不是按原始观测总数逐条扫描,但也不是固定 O(1)。当摘要包含更多中心点时,一次截尾均值查询需要处理的摘要内容也会增加。

# 先查看摘要状态,再决定是否把该指标放进高频看板
TDIGEST.INFO latency:api

# 以固定的分位区间读取估算值,避免每个请求都重复改变统计口径
TDIGEST.TRIMMED_MEAN latency:api 0.05 0.95

工程上我会把“写入摘要”和“读取统计”分开:采集链路持续加入观测,定时任务或看板刷新时读取均值、P95 和 P99。对于高频查询,缓存一小段时间的结果通常比每个页面请求都重新执行统计命令更容易控制负载。

六、把它放进延迟报表时的取舍

如果目标是观察服务的典型响应水平,我会优先记录三列:全量均值、P95/P99 和 P05-P95 截尾均值。全量均值显示整体代价,尾部分位点显示风险,截尾均值则帮助判断中间大多数请求有没有变慢。

现象优先关注解释
全量均值升高,截尾均值稳定P95/P99问题可能集中在少量长尾请求
全量均值和截尾均值一起升高摘要写入与发布变更中间大多数请求都在变慢
截尾均值明显低于全量均值异常值来源极端慢请求对全量均值影响较大

这也是我比较喜欢这个命令的原因:它没有假装替你定义“异常值”,只是允许报表明确写出要观察的分位区间。裁剪比例由业务负责,摘要只负责用已有信息给出估算。

常见问题

TDIGEST.TRIMMED_MEAN 能返回精确均值吗?

不能把它当成明细精确计算。它从 TDigest 摘要估算指定区间的均值,适合趋势分析和监控报表;需要精确审计时仍应保留原始数据或使用专门的离线计算。

low_cut_quantile 和 high_cut_quantile 传的是百分比吗?

传的是 0 到 1 之间的分位点小数。P05-P95 应写成 0.05 0.95,不是 5 95。

为什么不直接用 TDIGEST.QUANTILE?

TDIGEST.QUANTILE 返回某个位置的分位点,而 TDIGEST.TRIMMED_MEAN 返回两个分位点之间的均值估算。一个回答“边界在哪里”,另一个回答“边界内平均水平如何”。

应该选多大的截尾区间?

没有对所有业务都适用的固定比例。可以从 0.05 0.95 开始,同时保留 P95/P99 和样本量,再根据异常值是否确实干扰均值来调整。

最后可以用一句话记住它:TDIGEST.TRIMMED_MEAN 不是“把 Redis 里的明细平均一次”,而是“给 TDigest 两个分位边界,让摘要估算中间区间的均值”。只要参数顺序、比例写法和估算性质都说清楚,这个命令就能稳定地服务于延迟、容量和业务指标的长尾分析。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>