前言

      开发中遇到了一个貌似很简单的需求,统计某个接口的日访问数量。貌似功能很简单的样子,数据库新增一个记录表,最后按照时间去重下即可。如果真是这样,这里阐述一个通过redis使用hyperloglog数据结构实现访问量统计,请大家参考。


一、问题思路

需求:实现某个接口每天调用了多少次,每个用户只记录一次。

1、数据库统计

      通过数据库记录,先查询是否有记录,如果有则返回,没有记录则插入访问记录。最后通过select查询当日数据总数。如果是这样,小心被炒鱿鱼哦。。

2、redis的set集合

      通过redis的set集合实现。创建set集合visit_{data}(data为当前日期)。将访问用户的id添加进set集合中。这个在数据量小的时候,确实是一个比较容易理解的解决思路。set集合可以自动的实现去重,最后查询set集合的总数即可。
      但是这个只适合集合中数据少的时候,随着数据量的增加,set集合会占用很多内存

3、redis的HyperLogLog

      Redis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog 不能像集合那样,返回输入的各个元素。比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
      简单的说HyperLogLog通过概率学统计访问数量,统计的时候存在误差,但是误差很小。所以适合特殊场景,例如日访问量统计。
操作指令如下:
用户001访问。如果 HyperLogLog 的内部被修改了,那么返回 1,否则返回 0 .

PFADD visit_{data} “001”

用户002访问。

PFADD visit_{data} “002”

查看访问数量。

PFCOUNT visit_{data}

官方说明
hyperloglog原理


总结

HyperLogLog只适合对数量的统计允许有误差的场景, 不适合数据敏感的场景——金钱统计等等。