Redis高级数据结构——Redis深度历险笔记5
作者:互联网
说实在的HyperLogLog这个数据结构我感觉挺神奇的。
什么是HyperLogLog,有啥用
简而言之,是一个粗略的,专为大数据使用的,求set内有多少个元素的另一种表现形式。大家都知道set的作用是去重。。。术语叫统计基数,举例,数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}。
一般情况下,怎么去重,当然是把所有的出现过的数据,都存下来,当新的数据来的时候,跟老的数据都比较一遍(计算hash值,去对应链表查询),才知道是否存在。不存在的话,就对基数n加一。
用set的缺点很明显。要存储所有的数据,是一笔不小的开销。
那用bitmap?
这种只能对数字这种有效吧。
将下标当值用,将是否是1表示是否存在。
这种缺点也很明显啊,值很大,却只有一个的时候,就很浪费啊。
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