数据库
首页 > 数据库> > Redis高级数据结构——Redis深度历险笔记5

Redis高级数据结构——Redis深度历险笔记5

作者:互联网

说实在的HyperLogLog这个数据结构我感觉挺神奇的。

什么是HyperLogLog,有啥用

简而言之,是一个粗略的专为大数据使用的,求set内有多少个元素的另一种表现形式。大家都知道set的作用是去重。。。术语叫统计基数,举例,数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}。

一般情况下,怎么去重,当然是把所有的出现过的数据,都存下来,当新的数据来的时候,跟老的数据都比较一遍(计算hash值,去对应链表查询),才知道是否存在。不存在的话,就对基数n加一。

用set的缺点很明显。要存储所有的数据,是一笔不小的开销。

那用bitmap?

这种只能对数字这种有效吧。
将下标当值用,将是否是1表示是否存在。
这种缺点也很明显啊,值很大,却只有一个的时候,就很浪费啊。
bitmap参考图

hyperloglog怎么做的?

而HyperLogLog根本没有去重的操作好么,就很神奇的。

它是利用了 n个随机值的最长连续0的值K,与n的关系,去估算n。
关系大概为n=2^k;
多计算几个k,取调和平均值,就能比较接近的估算出n,标准误差大概在0.81%。确实比较神奇。

一个记录hyperloglog大概要占用12kb,还是比较恐怖的耗用,但是比起构造set来说,已经不错了。

我们只要求n不是么。

为啥要占用12kb

我们不是要多计算几个k么。

redis实际使用16384个桶,也就是2^14次方,每个桶占用6bit,也就是,12KB。
当然redis不是

布隆过滤器

用处:判断一个值是否已经出现过

是不是又想到用set了,当然肯定不是用set了,set一个很大的问题是要存储记录,如果记录非常多,性能就很差了,但是我们就是有判断这个记录存在过的需求呢,可以不是很精确。

布隆过滤器比hyperloglog结构好理解的多了。
就是每增加一个字符串,就对这个字符串取多个hash函数的值。为了取的均匀一点,然后将对应的大型位数组的长度取模,得到一个位置,将0置为1。

判断该记录是否存在,则进行一遍上述操作,去查看那个大型位数组的位置是否全为1,如果有为0的话,那肯定是不存在的。

当然,因为有重复位置,有的字符串其实不存在的,但是我们计算出来它存在,这就是误差点。

简单限流

比如对一个操作做一个限制,1分钟只能执行5次怎么办?
用一个zset维护一个用户的一个行为,score就是时间戳(value无所谓,用时间戳吧)。
那么每次执行这个动作的时候,清除一下这个zset里面时间戳小于一分钟前的数据,然后数个数,在范围内的话,则新增一个数据,不再的话,则不做处理。

这个的局限性在于需要记录所有在时间范围内的动作,动作范围如果非常大的话,比如60s内不超过100万次,那么,就不太合适了。

redis-cell插件,解决这个限流的问题

其实限流这个问题,用令牌桶这个方法解决比较经典。

桶有大小,表示一次性最多能存放多少张令牌。

流速表示一段时间内,允许失去令牌的速度。

127.0.0.1:6379> CL.THROTTLE test1 10 5 60 3
//命令行解析
127.0.0.1:6379> CL.THROTTLE test1(漏斗名字) 10(桶大小) 5(一段时间内允许的流速) 60(一段时间,单位为s) 3(这次想要取的令牌数量)
//根据返回值就可以看到是否取令牌成功
1(是否获取成功) 10 7 -1 x(多长时间后,漏斗完全空出来)

标签:令牌,set,记录,是否,Redis,限流,历险,数据结构,数据
来源: https://blog.csdn.net/rgbhi/article/details/114836673