简介:
Redis有一些特殊的数据结构,在特定的业务场景具有奇效,能起到减少存储空间、且功能实现简单快捷的作用。
Bitmap
位图,在我们平时开发过程中,会有一些 bool 型数据需要存取,比如用户一年的签到记录, 签了是 1,没签是 0,要记录 365 天。如果使用普通的 key/value,每个用户要记录 365 个,当用户上亿的时候,需要的存储空间是惊人的。
为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位, 365 天就是 365 个位,46 个字节 (一个稍长一点的字符串) 就可以完全容纳下,这就大大 节约了存储空间。

HyperLogLog
如果你负责开发维护一个大型的 网站,有一天老板找产品经理要网站每个网页每天的 UV 数据,然后让你来开发这个统计模块,你会如何实现?很容易想到的就是利用set这个数据结构,但当用户量达到上万、上亿级别,那么此时统计这个UV就会消耗很大的内存。如何减少内存的消耗呢?这就不得不提到HyperLogLog,它损耗不到1%的精准度,空间损耗只会到达12K!
HyperLogLog适用于海量数据,"大概数一下"的场景,也就是数据不是一定精确的场景。
需要引起注意的是,少量数据情况下(例如10条),HyperLogLog的误差率有30%~40%,上千数据以上,误差达到0.81%,数据越大误差率越小。因此,其适用于大量数据统计的情况。
布隆过滤器
有没有一种结构,消耗空间比hashmap小,同时又能起到去重的效果?这就是布隆过滤器起到的功效。布隆过滤器适合判断一个元素是否不在一个集合。但其并不能判断元素在一个集合,这是为什么?下面看一下布隆过滤器的底层结构。

看上去是不是很熟悉?是的,布隆过滤器底层就是一个bitmap,并且在这个基础上进行了hash的运算操作。
添加key时,使用多个hash函数计算多个索引,然后在bitmap的对应索引置为1。
查询key时,使用多个hash函数计算多个索引,只要多个索引都为0,此时可以百分百判断元素一定不在集合。
从原理上可以看出来,bloom过滤器也并不是非常精准的,这也是个适用于海量数据去重,并且不是非常精准的场景。