t-digest
提示
来自deepseek解释
原文链接:https://redis.io/docs/latest/develop/data-types/probabilistic/t-digest/
t-digest 命令摘要
本组共 14 条命令:
| 命令 | 摘要 | 复杂度 | 起始版本 |
|---|---|---|---|
| TDIGEST.ADD | 向 t-digest 草图中添加一个或多个观测值 | O(N),其中 N 是要添加的样本数量 | 2.4.0 |
| TDIGEST.BYRANK | 对每个输入的排名,返回该排名对应的值(浮点数)的估计 | O(N),其中 N 是指定的排名数量 | 2.4.0 |
| TDIGEST.BYREVRANK | 对每个输入的逆排名,返回该逆排名对应的值(浮点数)的估计 | O(N),其中 N 是指定的逆排名数量 | 2.4.0 |
| TDIGEST.CDF | 对每个输入值,返回(小于给定值的观测值 + 等于给定值的观测值的一半)所占比例的估计(浮点数) | O(1) | 2.4.0 |
| TDIGEST.CREATE | 分配内存并初始化一个新的 t-digest 草图 | O(1) | 2.4.0 |
| TDIGEST.INFO | 返回 t-digest 草图的信息和统计信息 | O(1) | 2.4.0 |
| TDIGEST.MAX | 返回 t-digest 草图的最大观测值 | O(1) | 2.4.0 |
| TDIGEST.MERGE | 将多个 t-digest 草图合并为一个草图 | O(N*K),其中 N 是质心数量... | 2.4.0 |
| TDIGEST.MIN | 返回 t-digest 草图的最小观测值 | O(1) | 2.4.0 |
| TDIGEST.QUANTILE | 对每个输入的分位数,返回小于该分位数观测值的值(浮点数)的估计 | O(N),其中 N 是指定的分位数数量 | 2.4.0 |
| TDIGEST.RANK | 对每个输入值(浮点数),返回该值的估计排名(草图中小于该值的观测值数量 + 等于该值的观测值数量的一半) | O(N),其中 N 是指定的值数量 | 2.4.0 |
| TDIGEST.RESET | 重置 t-digest 草图:清空草图并重新初始化 | O(1) | 2.4.0 |
| TDIGEST.REVRANK | 对每个输入值(浮点数),返回该值的估计逆排名(草图中大于该值的观测值数量 + 等于该值的观测值数量的一半) | O(N),其中 N 是指定的值数量 | 2.4.0 |
| TDIGEST.TRIMMED_MEAN | 从草图中返回均值的估计,排除低于低截止分位数和高于高截止分位数的观测值 | O(N),其中 N 是质心数量 | 2.4.0 |
t-digest 是 Redis Open Source 中的一种草图数据结构,用于使用紧凑草图从数据流或大型数据集中估计百分位数。
它可以回答如下问题:
- 数据流中有多少比例的值小于给定值?
- 数据流中有多少个值小于给定值?
- 小于数据流中 p% 的值的最大值是多少?(第 p 百分位数的值是多少?)
什么是 t-digest?
t-digest 是一种数据结构,可以在不存储和排序集合中所有数据点的情况下估计百分位数点。例如:要回答“我的数据库操作中 99% 的平均延迟是多少”这个问题,我们需要存储每个用户的平均延迟,对值进行排序,剔除最后 1%,然后才找到其余所有值的平均值。这类过程不仅在对这些值进行排序所需的处理方面成本高昂,而且在存储这些值所需的空间方面也很昂贵。这正是 t-digest 要解决的问题。
t-digest 还可以用于估计与百分位数相关的其他值,如修剪均值(trimmed mean)。
修剪均值 是从草图中计算的平均值,排除低于低截止分位数和高于高截止分位数的观测值。例如,0.1 修剪均值是草图的平均值,排除最低的 10% 和最高的 10% 的值。
使用场景
硬件/软件监控
您测量在线服务器的响应延迟,并希望查询:
测量延迟的第 50、90 和 99 百分位数是多少?
测量延迟中低于 25 毫秒的比例是多少?
忽略异常值后的平均延迟是多少?或者第 10 百分位数和第 90 百分位数之间的平均延迟是多少?
在线游戏
数百万人正在您的在线游戏平台上玩游戏,您想向每位玩家提供以下信息:
您的分数优于 x% 的游戏会话。
大约有 y 个游戏会话的分数高于您。
要获得比 90% 游戏会话更高的分数,您的分数应为 z。
网络流量监控
您测量每秒通过网络传输的 IP 数据包,并通过以下问题检测拒绝服务攻击:
最后一秒的数据包数量是否超过先前观测值的 99%?
在正常网络条件下,我预计会看到多少数据包? (答案:介于 x 和 y 之间,其中 x 代表第 1 百分位数,y 代表第 99 百分位数。)
预测性维护
测量的参数(噪声水平、电流消耗等)是否异常?(不在 [第 1 百分位数……第 99 百分位数] 范围内?)
我应该将警报设置为哪些值?
示例
在以下示例中,您将创建一个压缩值为 100 的 t-digest 并向其中添加项目。COMPRESSION 参数用于指定精度和内存消耗之间的权衡。默认值为 100。值越高表示精度越高。注意:与其他一些概率数据结构不同,如果键不存在,TDIGEST.ADD 命令不会创建新结构。
t-digest 创建和数据添加:使用 TDIGEST.CREATE 初始化草图,使用 TDIGEST.ADD 插入值,用于构建百分位数估计数据结构
命令: TDIGEST.CREATE, TDIGEST.ADD
复杂度:
- TDIGEST.CREATE: O(1)
- TDIGEST.ADD: O(N)
Java 示例(同步 - Jedis):
String res1 = jedis.tdigestCreate("bikes:sales", 100);
System.out.println(res1); // >>> True
String res2 = jedis.tdigestAdd("bikes:sales", 21);
System.out.println(res2); // >>> OK
String res3 = jedis.tdigestAdd("bikes:sales", 150, 95, 75, 34);
System.out.println(res3); // >>> OK只要有新的观测值,您可以重复调用 TDIGEST.ADD。
按值估计分数或排名
t-digest 的另一个有用功能是 CDF(累积分布函数,即排名的定义),它给出了小于或等于某个值的观测值所占的比例。该命令对于回答“值小于或等于 X 的观测值占比是多少”这类问题非常有用。
更准确地说,
TDIGEST.CDF将返回草图中小于 X 的观测值的估计比例,加上等于 X 的观测值数量的一半。我们还可以使用TDIGEST.RANK命令,它非常相似。它不返回比例,而是返回值的估计排名。TDIGEST.RANK命令也是变参的,意味着您可以使用单个命令检索一个或多个值的估计值。
以下是一个示例。给定一组自行车手的年龄,您可以提出“小于 50 岁的自行车赛车手占比是多少?”这样的问题。
百分位排名估计:使用 TDIGEST.CDF 估计低于阈值的值所占比例,使用 TDIGEST.RANK 估计值的排名,用于确定百分位位置
命令: TDIGEST.CREATE, TDIGEST.ADD, TDIGEST.CDF, TDIGEST.RANK
复杂度:
- TDIGEST.CREATE: O(1)
- TDIGEST.ADD: O(N)
- TDIGEST.CDF: O(1)
- TDIGEST.RANK: O(N)
Java 示例(同步 - Jedis):
String res4 = jedis.tdigestCreate("racer_ages");
System.out.println(res4); // >>> True
String res5 = jedis.tdigestAdd("racer_ages", 45.88,
44.2,
58.03,
19.76,
39.84,
69.28,
50.97,
25.41,
19.27,
85.71,
42.63);
System.out.println(res5); // >>> OK
List<Long> res6 = jedis.tdigestRank("racer_ages", 50);
System.out.println(res6); // >>> [7]
List<Long> res7 = jedis.tdigestRank("racer_ages", 50, 40);
System.out.println(res7); // >>> [7, 4]最后,TDIGEST.REVRANK key value... 类似于 TDIGEST.RANK,但返回草图中大于给定值的观测值数量加上等于给定值的观测值数量的一半。
按分数或排名估计值
TDIGEST.QUANTILE key fraction... 对每个输入的分位数,返回小于该分位数观测值的值(浮点数)的估计。TDIGEST.BYRANK key rank... 对每个输入的排名,返回该排名对应的值(浮点数)的估计。
分位数和排名值估计:使用 TDIGEST.QUANTILE 查找特定百分位数的值,使用 TDIGEST.BYRANK 按排名查找值,用于从草图中检索百分位值
命令: TDIGEST.QUANTILE, TDIGEST.BYRANK
复杂度:
- TDIGEST.QUANTILE: O(N)
- TDIGEST.BYRANK: O(N)
Java 示例(同步 - Jedis):
List<Double> res8 = jedis.tdigestQuantile("racer_ages", 0.5);
System.out.println(res8); // >>> [44.2]
List<Double> res9 = jedis.tdigestByRank("racer_ages", 4);
System.out.println(res9); // >>> [42.63]TDIGEST.BYREVRANK key rank... 对每个输入的逆排名,返回该逆排名对应的值(浮点数)的估计。
估计修剪均值
使用 TDIGEST.TRIMMED_MEAN key lowFraction highFraction 检索指定分位数之间的均值估计。
这对于计算忽略异常值的平均值特别有用。例如——计算第 20 百分位数和第 80 百分位数之间的平均值。
合并草图
有时合并草图很有用。例如,假设我们测量了 3 台服务器的延迟,并且想要计算所有服务器合并后的第 90、95 和 99 百分位数延迟。
TDIGEST.MERGE destKey numKeys sourceKey... [COMPRESSION compression] [OVERRIDE] 将多个草图合并为一个草图。
如果 destKey 不存在——将创建一个新草图。
如果 destKey 是现有草图,其值将与源键的值合并。要覆盖目标键的内容,请使用 OVERRIDE。
检索草图信息
使用 TDIGEST.MIN 和 TDIGEST.MAX 分别检索草图中的最小值和最大值。
草图元数据检索:使用 TDIGEST.MIN 和 TDIGEST.MAX 检索草图中的最小值和最大值,用于检查数据边界
命令: TDIGEST.MIN, TDIGEST.MAX
复杂度:
- TDIGEST.MIN: O(1)
- TDIGEST.MAX: O(1)
Java 示例(同步 - Jedis):
double res10 = jedis.tdigestMin("racer_ages");
System.out.println(res10); // >>> 19.27
double res11 = jedis.tdigestMax("racer_ages");
System.out.println(res11); // >>> 85.71当草图为空时,两者都返回 nan。
这两个命令返回精确结果,分别等同于 TDIGEST.BYRANK racer_ages 0 和 TDIGEST.BYREVRANK racer_ages 0。
使用 TDIGEST.INFO racer_ages 检索有关草图的更多信息。
重置草图
草图重置:使用 TDIGEST.RESET 清除草图的所有数据,用于为新数据重用草图
命令: TDIGEST.RESET
复杂度:
- TDIGEST.RESET: O(1)
Java 示例(同步 - Jedis):
String res12 = jedis.tdigestReset("racer_ages");
System.out.println(res12); // >>> OK