项目 | 场景 | 实现原理 | 缺陷 | 误差分析 | 内存分析 | 实践应用 |
位图 | 有一些bool型数据需要存取,比如用户一年的签到记录,签了是1,没签是0,要记录365天。如果使用普通的key/value,每个用户要记录365个,当用户数上亿时,需要相当大的存储空间。 Redis提供了位图数据结构,每天的签到记录只占据一个位,365天就是365个位,46个字节(一个稍长的字符串)就可以完全容纳下,大大节约了存储空间。 位图的最小单位是bit,每个bit的取值只能是0或1. | 1.注意setbit时的偏移量,当偏移量很大时,可能会有较大耗时。 2.数据稀疏。比如要存入(10,8887983,93452134)这三个数据,我们需要建立一个 99999999 长度的 BitMap ,但是实际上只存了3个数据,这时候就有很大的空间浪费。 | - | 假设要存储[0,99999999]共一亿个数据,每一个数据需要1个bit位,总共需要100000000bit,大概是12M。 限制: redis中bit映射被限制在512MB之内,所以最大是2^32位。 | 适用于不光需要记录数据,还需要对数据进行验证。 | |
hyperloglog | 比如需要统计一个网站的UV(独立访客数),同一个用户一天之内的多次请求只能计数一次,如果使用set集合来统计的话,会非常浪费存储空间。 HyperLogLog提供不精确的去重计数方案,虽然不精确但是也不是非常不精确,标准误差是0.81%。 | 1.计数误差 2.不适合统计单个用户相关的数据,因为它需要占据12KB的空间。 | 标准误差是0.81%,因为Redis中用了16384个桶,HyperLogLog的标准误差公式是1.04/sqrt(m), m是桶的个数,所以在Redis中,m=16384,标准误差则为0.81%。 | Redis采用了16384个桶来存储计算HyperLogLog,那所占的内存会是多少? Redis最大可以统计2^64个数据,也就是说每个桶的最大maxbits需要 6 个bit来存储(2^6=64)。那么所占内存就是 16384 * 6 / 8 = 12kb。 相比 BitMap 1亿数据就需要 12M,如果 2^64个数据,粗略计算需要 1500 TB,而 HyperLogLog 只需要12kb。 如果元素个数不多时,Redis会采用稀疏存储结构,其大小会少于12kb,采用密集存储结构,大小固定为12kb,存储的实现采用Redis的字符串位图bitmap实现,即连续个16384个桶,每个桶占6个Bits。 | HyperLoglog用于只记录的时候,可以用于解决很多精确度要求不高的统计问题,如统计每个网页每天的访问UV。 需要redis版本:2.8.9以上 | |
布隆过滤器 | 比如我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,而它每次推荐时都要去重,以去掉那些我们已经看过的内容。 布隆过滤器是专门用来解决这种去重问题的,它在起到去重作用的同时,在空间上还能节省90%以上,但是会有一定的误判概率。当布隆过滤器说某个值存在时,这个值可能不存在;当它说某个值不存在时,那就肯定不存在。 用在推送去重的场景中,布隆过滤器可以准确地过滤掉那些用户已经看过的内容,用户没有看过的内容,它也会过滤掉一小部分(误判),这样就可以保证推荐给用户的内容都是无重复的。 | 1.误算率,随着数据量增加,误差逐渐增大 2.很难删除数据 | 误判率可以使用公式计算,要求误判率越低,所需要的空间越大。如果一千万的数据,误判率允许 1%, 大概需要11M左右;如果要求误判率为 0.1%,则大概需要 17 M左右。 可以使用bloom filter calculator计算。 | 要求的误判率越低,占用空间越大,但和set相比空间占用小太多了。 | 判断某一个值是不是已经存在。 业务场景中判断用户是否阅读过某视频或文章,比如抖音或头条,当然会导致一定的误判,但不会让用户看到重复的内容。 缓存宕机、缓存击穿场景,一般判断用户是否在缓存中,如果在则直接返回结果,不在则查询db,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应,这时候可以用布隆过滤器当缓存的索引,只有在布隆过滤器中,才去查询缓存,如果没查询到,则穿透到db。如果不在布隆器中,则直接返回。 需要redis版本:4.0以上安装redisbloom插件使用 |
位图,Hyperloglog和布隆过滤器对比
最新推荐文章于 2024-06-05 10:30:51 发布