我们来回顾下在这个系列的第一篇 深刻理解高性能Redis的本质 中介绍过Redis的几种基本数据结构,
它服务于各种不同的业务场景而设计的,比如:
除了这些常见数据类型,还有一些不常用的数据类型,如 BitMap、Geo、HyperLogLog 等等,他们在各自的方向为不同的类型的数据统计给出解决方案。
这一篇我们来介绍下HyperLogLog,HyperLogLog 主要用于Redis基数的统计,比如IP统计,用户访问量,页面访问量。
HyperLogLog 主要用于Redis 的基数统计,它的数据结构专门设计用来做数据合并和计算,并能节省大量的空间。
基数计数( cardinality counting) 通常用来统计一个集合中不重复的元素个数 , 例如统计某个网站的UV、PV或者网站搜索的的关键词数量。
在各种应用领域基数统计被广泛应用,如数据分析、网络监控指标、存储性能优化等。
简单来说,基数计数就是记录集合中所有不重复的元素Su ,当新增元素Xa时,判断Su中是否包含,不包含则将其加入Su,包含则不加入,计数值就是Su 的元素数量总和。
当然这种做法也存在两个问题:
很多计数类场景,比如 每日注册 IP 数、每日访问 IP 数、页面实时访问数 PV、访问用户数 UV等。
因为主要的目标高效、巨量地进行计数,所以对存储的数据的内容并不关系。也就是说它只能用于统计数量,没办法知道具体的统计对象的内容。
如果我们使用普通集合,也能够实现对巨量数据的存储和统计么,但是存储量会大很多,性能也比较差。
以百度搜索为例,如果要做百度指数的计算,针对来访IP进行统计。那么如果每天 有 1000 万 IP,一个 IP 占位 15 字节,那么 1000 万个 IP 就是 143M。
10,000,000 * 15 /(1024 * 1024) = 143.05 M
如果使用 HyperLogLog ,那么在 Redis 中每个键占用的内容都是 12K,理论上能够存储 264 个值,即18446744073709551616,这个数是巨量,Java中long类型也只能计算到 262 。
无论存储何值,它一个基于基数估算的算法HyperLogLog Counting(简称HLLC),使用少量固定的内存去存储并识别集合中的唯一元素。
HLLC采用了分桶平均的思想来消减误差,在Redis中, 有16384个桶 。而HyperLogLog的标准偏差公式是1.04 / sqrt(m),m 为桶的个数。所以
1.04 / sqrt(16384) = 1.04 / 128 = 0.008125
所以这个计数的估算,是一个带有 0.81% 标准偏差的近似值。
HyperLogLog 算法原理参考这两篇,写的很清晰
HyperLogLog数据结构的命令有三个:PFADD、PFCOUNT、PFMERGE
Redis Pfadd 命令将所有元素添加到 HyperLogLog 数据结构中。