redis8.0新特性:t-digest计算数据百分位
文章目录
- 一、写在前面
- 1、什么是 t-digest?
- 2、使用场景
- 二、使用
- 1、TDIGEST.CREATE 创建
- 2、TDIGEST.ADD 添加元素
- 3、TDIGEST.BYRANK 根据排名获取值
- 4、TDIGEST.BYREVRANK 根据倒排名获取值
- 5、TDIGEST.CDF 根据值获取比例
- 6、TDIGEST.INFO 获取t-digest信息
- 7、TDIGEST.MAX 获取最大值
- 8、TDIGEST.MIN 获取最小值
- 9、TDIGEST.MERGE合并
- 10、TDIGEST.QUANTILE 根据比例获取元素
- 11、TDIGEST.RANK 根据值获取排名
- 12、TDIGEST.REVRANK 根据值获取倒排名
- 13、TDIGEST.RESET清空数据
- 14、TDIGEST.TRIMMED_MEAN 求平均
一、写在前面
官方中文文档:https://redis.ac.cn/docs/latest/develop/data-types/probabilistic/t-digest/
命令文档:https://redis.ac.cn/docs/latest/commands/?group=tdigest
t-digest 是一种概率型数据结构,用于估计数据流的百分位数。
t-digest 是 Redis 开源版中的一种 sketch 数据结构,用于使用紧凑的 sketch 估计数据流或大型数据集的百分位数。
它可以回答以下问题:
数据流中有多大比例的值小于给定值?
数据流中有多少值小于给定值?
数据流中小于 p 百分比值的最高值是什么?(即 p 百分位数值是多少?)
1、什么是 t-digest?
t-digest 是一种数据结构,它可以在无需存储和排序集合中的所有数据点的情况下估计百分位点。例如:要回答“我的数据库操作中 99% 的平均延迟是多少?”这个问题,我们必须存储每个用户的平均延迟,对值进行排序,去掉最后 1%,然后才能找到其余所有值的平均值。这种过程不仅在排序这些值所需的处理方面成本高昂,而且在存储这些值所需的空间方面也成本高昂。这正是 t-digest 解决的问题。
t-digest 还可以用于估计与百分位数相关的其他值,例如截断均值(trimmed means)。
截断均值是 sketch 中的平均值,不包括低于和高于截止百分位数的观测值。例如,0.1 截断均值是 sketch 中的平均值,不包括最低的 10% 和最高的 10% 的值。
2、使用场景
硬件/软件监控
您测量在线服务器响应延迟,并希望查询:
测得延迟的第 50、90 和 99 百分位数是多少?
测得延迟中有多大比例小于 25 毫秒?
忽略异常值后的平均延迟是多少?或者,第 10 和第 90 百分位数之间的平均延迟是多少?
在线游戏
数百万人在您的在线游戏平台上玩游戏,您想向每位玩家提供以下信息?
您的分数高于 x% 的游戏会话分数。
约有 y 个游戏会话中,人们的得分高于您。
要获得比 90% 的游戏玩家更高的分数,您的分数应为 z。
网络流量监控
您测量每秒网络传输的 IP 数据包,并尝试通过询问以下问题来检测拒绝服务攻击:
最后一秒的数据包数量是否超过之前观察到的值的 99%?
在正常网络条件下,我预计会看到多少数据包?(答案:介于 x 和 y 之间,其中 x 代表第 1 百分位数,y 代表第 99 百分位数)。
预测性维护
测量的参数(噪声水平、电流消耗等)是否异常?(不在 [第 1 百分位数…第 99 百分位数] 范围内)?
我应该将警报设置为哪些值?
二、使用
1、TDIGEST.CREATE 创建
# 语法
# COMPRESSION compression:是精度和内存消耗之间可控制的权衡。对于一般用途,100 是一个常见值。1000 的精度更高。如果未传递值,默认压缩为 100。
TDIGEST.CREATE key [COMPRESSION compression]# 示例
127.0.0.1:6379> TDIGEST.CREATE t COMPRESSION 100
OK
2、TDIGEST.ADD 添加元素
# 语法
# value:是观察值(浮点数)。
TDIGEST.ADD key value [value ...]# 示例,只能存放浮点数,不能存字符串
127.0.0.1:6379> TDIGEST.ADD t 1 2 3
OK
127.0.0.1:6379> TDIGEST.ADD t 1.1 2.123 3.324
OK
127.0.0.1:6379> TDIGEST.ADD t string
(error) ERR T-Digest: error parsing val parameter
3、TDIGEST.BYRANK 根据排名获取值
对于每个输入的排名,返回该排名对应值的估计值(浮点数)
。
单次调用中可以检索多个估计值。
# 语法# rank
#排名,应检索该排名对应的值。
#0 是最小观测值的排名。
#n-1 是最大观测值的排名;n 表示添加到 sketch 的观测值数量。# 返回值
#数组 - 包含 value_1, value_2, ..., value_R 的浮点数组
#当 rank 为 0 时返回精确结果(最小观测值)
#当 rank 为 n-1 时返回精确结果(最大观测值),其中 n 表示添加到 sketch 的观测值数量。
#当 rank 等于 n 或大于 n 时返回 'inf'
#如果 sketch 为空,所有值都为 'nan'。TDIGEST.BYRANK key rank [rank ...]
127.0.0.1:6379> TDIGEST.CREATE t COMPRESSION 1000
OK
127.0.0.1:6379> TDIGEST.ADD t 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
OK
# 排行第0 就是第一,从小到大排
# 获取排行时,如果超过元素数量,返回inf
127.0.0.1:6379> TDIGEST.BYRANK t 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 151) "1"2) "2"3) "2"4) "3"5) "3"6) "3"7) "4"8) "4"9) "4"
10) "4"
11) "5"
12) "5"
13) "5"
14) "5"
15) "5"
16) "inf"
4、TDIGEST.BYREVRANK 根据倒排名获取值
# 语法# revrank
#要检索其值的反向排名。
#0 是最大观测值的值的反向排名。
#n-1 是最小观测值的值的反向排名;n 表示添加到摘要中的观测值数量。# 返回值为数组 - 一个由 value_1, value_2, ..., value_R 等浮点数填充的数组
#当 revrank 为 0 时(最大观测值的值),返回准确结果
#当 revrank 为 n-1 时(最小观测值的值),返回准确结果,其中 n 表示添加到摘要中的观测值数量。
#当 revrank 等于或大于 n 时,返回 '-inf'
#如果摘要为空,则所有值均为 'nan'。TDIGEST.BYREVRANK key reverse_rank [reverse_rank ...]
redis> TDIGEST.CREATE t COMPRESSION 1000
OK
redis> TDIGEST.ADD t 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
OK
# 获取倒排名,从大到小排
redis> TDIGEST.BYREVRANK t 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 151) "5"2) "5"3) "5"4) "5"5) "5"6) "4"7) "4"8) "4"9) "4"
10) "3"
11) "3"
12) "3"
13) "2"
14) "2"
15) "1"
16) "-inf"
5、TDIGEST.CDF 根据值获取比例
对于每个输入值,返回小于给定值(加上等于给定值的一半观测值)的观测值所占比例(浮点数)的估计值。
(听起来有点拗口,具体看例子)
# 语法
TDIGEST.CDF key value [value ...]
redis> TDIGEST.CREATE t COMPRESSION 1000
OK
redis> TDIGEST.ADD t 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
OK
# 小于观测数的比例+等于观测数的比例/2
redis> TDIGEST.CDF t 0 1 2 3 4 5 6
1) "0"
2) "0.033333333333333333"
3) "0.13333333333333333"
4) "0.29999999999999999"
5) "0.53333333333333333"
6) "0.83333333333333337"
7) "1"
# 如下例子,元素总数为15,小于5的元素有10个,所以小于5的元素比例为0.6666666667
# 等于5的元素有5个,所以等于5的元素比例为0.3333333333333333
# 所以结果为0.6666666667 + 0.3333333333333333/2 = 0.8333333333333334
# 相当于结果为(10+5/2) / 15 = 12.5/15 = 0.8333333333333334
127.0.0.1:6379> TDIGEST.CDF t 5
1) "0.8333333333333334"
6、TDIGEST.INFO 获取t-digest信息
# 语法
TDIGEST.INFO key# 返回值
压缩 整数回复
sketch 的压缩率(可在准确性和内存消耗之间进行权衡控制)容量 整数回复
用于存储质心和传入的未合并观察值的缓冲大小已合并节点 整数回复
已合并观察值的数量未合并节点 整数回复
缓冲节点(未压缩观察值)的数量已合并权重 整数回复
已合并节点值的权重未合并权重 整数回复
未合并节点(未压缩观察值)值的权重观察值 整数回复
添加到 sketch 的观察值数量总压缩次数 整数回复
此 sketch 对数据进行压缩的次数内存使用量 整数回复
为 sketch 分配的字节数
redis> TDIGEST.CREATE t
OK
redis> TDIGEST.ADD t 1 2 3 4 5
OK
redis> TDIGEST.INFO t1) Compression2) (integer) 1003) Capacity4) (integer) 6105) Merged nodes6) (integer) 07) Unmerged nodes8) (integer) 59) Merged weight
10) (integer) 0
11) Unmerged weight
12) (integer) 5
13) Observations
14) (integer) 5
15) Total compressions
16) (integer) 0
17) Memory usage
18) (integer) 9768
7、TDIGEST.MAX 获取最大值
# 语法
TDIGEST.MAX key# 示例
redis> TDIGEST.CREATE t
OK
redis> TDIGEST.MAX t
"nan"
redis> TDIGEST.ADD t 3 4 1 2 5
OK
redis>TDIGEST.MAX t
"5"
8、TDIGEST.MIN 获取最小值
# 语法
TDIGEST.MIN key# 示例
redis> TDIGEST.CREATE t
OK
redis> TDIGEST.MIN t
"nan"
redis> TDIGEST.ADD t 3 4 1 2 5
OK
redis> TDIGEST.MIN t
"1"
9、TDIGEST.MERGE合并
# 语法# destination-key
#是用于合并观察值的 t-digest 草图的键名。
#如果 destination-key 不存在,则创建一个新的草图。
#如果 destination-key 是现有草图,其值将与源键的值合并。要覆盖目标键的内容,请使用 OVERRIDE。# numkeys
#要合并观察值来源的草图数量(1 个或更多)。#source-key
#每个都是要合并观察值来源的 t-digest 草图的键名。# COMPRESSION compression
#是准确性和内存消耗之间可控的权衡。100 是常见的值,适用于一般用途。1000 更准确。如果未传递值,默认压缩值为 100。
#未指定 COMPRESSION 时
#如果 destination-key 不存在或指定了 OVERRIDE,则压缩值设置为所有源草图中的最大值。
#如果 destination-key 已存在且未指定 OVERRIDE,则其压缩值不会改变。#OVERRIDE
#指定时,如果 `destination-key` 已存在,则会覆盖它。TDIGEST.MERGE destination-key numkeys source-key [source-key ...] [COMPRESSION compression] [OVERRIDE]
redis> TDIGEST.CREATE s1
OK
redis> TDIGEST.CREATE s2
OK
redis> TDIGEST.ADD s1 10.0 20.0
OK
redis> TDIGEST.ADD s2 30.0 40.0
OK
# 将s1、s2这两个 合并到sM
redis> TDIGEST.MERGE sM 2 s1 s2
OK
redis> TDIGEST.BYRANK sM 0 1 2 3 4
1) "10"
2) "20"
3) "30"
4) "40"
5) "inf"
10、TDIGEST.QUANTILE 根据比例获取元素
对于每个输入的比例,返回小于该比例观测值的估算值(浮点数)。
# 语法# quantile
#输入比例(0 到 1 之间,包含 0 和 1)# 返回值为数组 - 一个包含估算值(浮点数)的数组,形如 value_1, value_2, ..., value_N。
#当 quantile 为 0 时(最小观测值),返回准确结果
#当 quantile 为 1 时(最大观测值),返回准确结果
#如果摘要为空,则所有值为 'nan'。TDIGEST.QUANTILE key quantile [quantile ...]
redis> TDIGEST.CREATE t COMPRESSION 1000
OK
redis> TDIGEST.ADD t 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
OK
redis> TDIGEST.QUANTILE t 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 11) "1"2) "2"3) "3"4) "3"5) "4"6) "4"7) "4"8) "5"9) "5"
10) "5"
11) "5"
11、TDIGEST.RANK 根据值获取排名
对于每个输入值(浮点数),返回该值的估计排名(草图中小于该值的观测数 + 等于该值的观测数的一半)。
# 语法#value
#需要估计排名的输入值。# 返回值
#数组回复 - 一个由 rank_1, rank_2, ..., rank_V 填充的整数数组
#-1 - 当 value 小于最小观测值时。
#观测值数量 - 当 value 大于最大观测值时。
#否则:对(小于 value 的观测数 + 等于 value 的观测数的一半)的估计值。#0 是最小观测值的排名。
#n-1 是最大观测值的排名;n 表示添加到草图中的观测数。
#如果草图为空,则所有值均为 -2。
TDIGEST.RANK key value [value ...]
redis> TDIGEST.CREATE s COMPRESSION 1000
OK
redis> TDIGEST.ADD s 10 20 30 40 50 60
OK
# 根据值获取排名
redis> TDIGEST.RANK s 0 10 20 30 40 50 60 70
1) (integer) -1
2) (integer) 0
3) (integer) 1
4) (integer) 2
5) (integer) 3
6) (integer) 4
7) (integer) 5
8) (integer) 6
# 根据值获取倒排名
redis> TDIGEST.REVRANK s 0 10 20 30 40 50 60 70
1) (integer) 6
2) (integer) 5
3) (integer) 4
4) (integer) 3
5) (integer) 2
6) (integer) 1
7) (integer) 0
8) (integer) -1
redis> TDIGEST.CREATE s COMPRESSION 1000
OK
redis> TDIGEST.ADD s 10 10 10 10 20 20
OK
# 对于每个输入值(浮点数),返回该值的估计排名(草图中小于该值的观测数 + 等于该值的观测数的一半)。
redis> TDIGEST.RANK s 10 20
1) (integer) 2
2) (integer) 5
redis> TDIGEST.REVRANK s 10 20
1) (integer) 4
2) (integer) 1
12、TDIGEST.REVRANK 根据值获取倒排名
对于每个输入值(浮点数),返回该值的估计逆向排名(草图中的观察值中大于该值的数量 + 等于该值的观察值数量的一半)。
# 语法# value
#需要估计逆向排名的输入值。#返回值
#Array reply - 包含 revrank_1, revrank_2, ..., revrank_V 的整数数组
#-1 - 当 value 大于最大观察值时。
#观察值数量 - 当 value 小于最小观察值时。
#否则:估计的数量(大于 value 的观察值 + 等于 value 的观察值的一半)。
#0 是最大观察值的逆向排名。
#n-1 是最小观察值的逆向排名;n 表示添加到草图中的观察值数量。
#如果草图为空,则所有值均为 -2。TDIGEST.REVRANK key value [value ...]
redis> TDIGEST.CREATE s COMPRESSION 1000
OK
redis> TDIGEST.ADD s 10 20 30 40 50 60
OK
redis> TDIGEST.RANK s 0 10 20 30 40 50 60 70
1) (integer) -1
2) (integer) 0
3) (integer) 1
4) (integer) 2
5) (integer) 3
6) (integer) 4
7) (integer) 5
8) (integer) 6
redis> TDIGEST.REVRANK s 0 10 20 30 40 50 60 70
1) (integer) 6
2) (integer) 5
3) (integer) 4
4) (integer) 3
5) (integer) 2
6) (integer) 1
7) (integer) 0
8) (integer) -1
redis> TDIGEST.CREATE s COMPRESSION 1000
OK
redis> TDIGEST.ADD s 10 10 10 10 20 20
OK
redis> TDIGEST.RANK s 10 20
1) (integer) 2
2) (integer) 5
redis> TDIGEST.REVRANK s 10 20
1) (integer) 4
2) (integer) 1
13、TDIGEST.RESET清空数据
# 语法
TDIGEST.RESET key# 示例
redis> TDIGEST.RESET t
OK
14、TDIGEST.TRIMMED_MEAN 求平均
返回草图均值的估计值,排除低于或高于截断分位数阈值的观测值。
# 语法# low_cut_quantile
#范围 [0..1] 的浮点数值,应小于 high_cut_quantile
#当等于 0 时:无低位截断。
#当大于 0 时:排除低于此分位数的观测值。# high_cut_quantile
#范围 [0..1] 的浮点数值,应大于 low_cut_quantile
#当小于 1 时:排除大于或等于此分位数的观测值。
#当等于 1 时:无高位截断。TDIGEST.TRIMMED_MEAN key low_cut_quantile high_cut_quantile
redis> TDIGEST.CREATE t COMPRESSION 1000
OK
redis> TDIGEST.ADD t 1 2 3 4 5 6 7 8 9 10
OK
redis> TDIGEST.TRIMMED_MEAN t 0.1 0.6
"4"
redis> TDIGEST.TRIMMED_MEAN t 0.3 0.9
"6.5"
redis> TDIGEST.TRIMMED_MEAN t 0 1
"5.5"