Redis数据类型HyperLogLog

205 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

本篇文章一起来学习下redis的数据类型HyperLogLog。相信做互联网行业的同学们应该都听说过PVUV等词汇吧。PV我们可以通过上一章节学习的bitmaps来实现,或者redis的自增等等技术趋实现。那么UV(独立访客)这种我们需要如何进行统计?此类数据通常需要对数据进行去重,此处,我们就可使用本篇的主角HyperLogLog

一、HyperLogLog简介

在开篇提到的问题,对于需要处理去重的数据,我们可以概括为基数问题

1.1 什么是基数?

举个例子,有一个马棚M,其中有三匹马;有一个客栈房间N,住了三位旅客。则我就可以说M集合和N集合具有相同的基数,都是3。

又如,有一个集合,其中有7个元素{1,3,5,6,6,7,9},我们对它去重,得到新的集合{1,3,5,6,7,9},剩余6个元素,则得到它的基数(不重复的元素)是6。

我们前面提到的UV与求基数恰好相同,所以就是基数问题。

1.2 基数问题的解决方案

我们常见的处理基数的接解决方案有:

  • 关系型数据库,如mysql、oracle等,使用distinct关键字。
  • java当中的Set
  • 前面学的redis的set,甚至hash(key不重复)

上面的方案都可以处理基数问题,但是存在的问题很明显,如果网站有上千万的用户访问量,那么以上结构可能会占用大量的空间。

Redis的HyperLogLog专门用来做基数统计

其特点是:当元素的数量非常大时,其所需的空间固定的,每个 HyperLogLog 键只需要花费 12 KB 内存,可以计算接近 2^64 个不同元素的基数。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。

二、命令介绍

pfadd

添加元素到HyperLogLog。

其格式:pfadd <key> < element>

使用方式如下,比如20220526这一天,记录同学们访问的数量,小明和小芳来访问过:

122.112.181.245:0>pfadd 20220526 xiaoming
"1"
122.112.181.245:0>pfadd 20220526 xiaofang
"1"
122.112.181.245:0>pfadd 20220526 xiaoming
"0"

如上所示,经过计算,首次发小小明没来过,返回1,小芳没来过,返回1,当小明再次来过,则返回0.

pfcount

计算key的基数,可以计算多个key

格式如下:pfcount <key>

如下,在20220525这天,小明,小红,小芳都来过,在20220526这天,小明,小芳,小红也都来过:

122.112.181.245:0>pfadd 20220526 xiaohong
"1"
122.112.181.245:0>pfadd 20220526 xiaoming
"1"
122.112.181.245:0>pfadd 20220526 xiaofang
"1"
122.112.181.245:0>pfadd 20220525 xiaofang
"1"
122.112.181.245:0>pfadd 20220525 xiaohong
"1"
122.112.181.245:0>pfadd 20220525 xiaoming
"1"

分别统计25号、26号、25和26两天的:

122.112.181.245:0>pfcount 20220525
"3"
122.112.181.245:0>pfcount 20220526
"3"
122.112.181.245:0>pfcount 20220525 20220526
"3"

如上所示都是3,可见已经帮我们对同一个人进行去重了。

pfmerge

将指定key的基数值,存储到另外一个指定的key当中

格式:pfmerge <destkey> <sourcekey>

将前面的两天数据汇总到5月的key当中:

122.112.181.245:0>pfmerge 202205 20220525 20220526
"OK"
122.112.181.245:0>pfcount 202205
"3"

由上可见,可用于将天访问量汇总成月访问量。