Redis-HyperLogLog与BitMap

四两拨千斤——HyperLogLog

因为在项目中,用到了这个高级数据结构来统计UV数据。所以,今天特来总结一下。

日UV(Unique Visitor,独立访客),即统计同一个用户一天之内的访问请求,并且同一个用户的多次请求只能统计一次。这就要求每一个网页请求都需要带上用户ID,无论是登录用户还是未登录用户都需要一个唯一ID来标识。

当然,第一个想到的是用set集合来存储,既能去重又能统计用户ID总数。但是,如果网站页面有几百万、甚至上千万的数据时,就需要一个很大的set集合来统计,这样非常浪费空间。况且,对于UV统计来说,并不需要百分之百的准确,那么,Redis中的HyperLogLog 就成了不二之选!在我的项目中,我选择统计用户的IP地址来区分用户。

在HLL中,只需要不到1K内存就能做到;Redis中实现的 HyperLogLog,只需要 12K 内存,在标准误差 0.81% 的前提下,能够统计2^{64}个数据。

HyperLogLog 实现原理——简单理解

Redis-HyperLogLog与BitMap_第1张图片

在项目中,从request中获取IP地址字符串,HLL算法会将字符串计算哈希值。

这张图的意思是,给定一系列的随机整数,我们记录下低位连续零位的最大长度K,这个参数就是图中的maxbit,通过这个K值可以估算出随机数的数量N。

在Redis中的 HyperLogLog 实现中用的是 16384 个桶,也就是 2的14次方,每个桶的 maxbit 需要 6个bit 来存储,最大可以表示maxbits=63,于是总共占用内存就是:

总共占用内存就是   {\color{Red} (2^{14}) \cdot 6 / 8}.

总结:HyperLogLog 在使用非常小内存的情况下,可以做到统计去重海量的数据,并且准确率非常高。

节衣缩食——位图(BitMap)

 在项目中,为了统计网站的日活跃用户数量,即 DAU(Daily Active User,日活跃用户数量)。使用到了另外一个高级数据结构位图。

在开发过程中,我们为了统计用户一年的签到记录,假设签了是 1 ,没签是 0 ,要记录365天。如果使用普通的 key/value ,每个用户要记录365个,当用户数成千上万时,需要的空间是惊人的!

为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位,365天就是365个位,46个字节(相当于一个稍长一点的字符串而已)就可以完全容纳下,这样就大大节约了存储空间。位图的最小单位是比特(bit),每个bit的取值只能是0或1。

位图不是什么特殊的数据结构,其实它的内容就是普通的字符串,也就是 byte 数组

记住:Redis 中的位数组是自动扩展的,如果设置了某个偏移位置超出了现有的内容范围,就会自动将位数组进行零扩充。

统计和查找

Redis 提供了位图统计指令 bitcount 和位图查找命令 bitops。bitcount 用来统计指定位置范围内1的个数,bitpos 用来查找指定范围内出现的第一个 0 或 1。

项目中的应用

Redis-HyperLogLog与BitMap_第2张图片

 

总结:看来Redis远比我们想象的要强大的多,加油吧!

 

 

 

 

 

 

 

 

你可能感兴趣的:(Redis)