Redis高级数据结构(hyperloglog,布隆过滤器,漏斗限流)——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(多长时间后,漏斗完全空出来)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rgbhi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值