博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3.6 HyperLogLog
阅读量:6264 次
发布时间:2019-06-22

本文共 2793 字,大约阅读时间需要 9 分钟。

3.6 HyperLogLog

HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等。HyperLogLog提供了3个命令:pfadd、pfcount、pfmerge。例如2016-03-06的访问用户是uuid-1、uuid-2、uuid-3、uuid-4,2016-03-05的访问用户是uuid-4、uuid-5、uuid-6、uuid-7,如图3-15所示。

 

图3-15 2016-03-05和2016-03-06的访问用户

HyperLogLog的算法是由Philippe Flajolet(https://en.wikipedia.org/wiki/Philippe_Flajolet)在The analysis of a near-optimal cardinality estimation algorithm这篇论文中提出,读者如果有兴趣可以自行阅读。

1.?添加

pfadd key element [element …]

pfadd用于向HyperLogLog添加元素,如果添加成功返回1:

127.0.0.1:6379> pfadd 2016_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4"

(integer) 1

2.?计算独立用户数

pfcount key [key …]

pfcount用于计算一个或多个HyperLogLog的独立总数,例如2016_03_06:

unique:ids的独立总数为4:

127.0.0.1:6379> pfcount 2016_03_06:unique:ids

(integer) 4

如果此时向2016_03_06:unique:ids插入uuid-1、uuid-2、uuid-3、uuid-90,结果是5(新增uuid-90):

127.0.0.1:6379> pfadd 2016_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-90"

(integer) 1

127.0.0.1:6379> pfcount 2016_03_06:unique:ids

(integer) 5

当前这个例子内存节省的效果还不是很明显,下面使用脚本向HyperLogLog插入100万个id,插入前记录一下info memory:

127.0.0.1:6379> info memory

# Memory

used_memory:835144

used_memory_human:815.57K

...

向2016_05_01:unique:ids插入100万个用户,每次插入1000条:

elements=""

key="2016_05_01:unique:ids"

for i in `seq 1 1000000`

do

    elements="${elements} uuid-"${i}

    if [[ $((i%1000))  == 0 ]];

    then

        redis-cli pfadd ${key} ${elements}

        elements=""

    fi

done

当上述代码执行完成后,可以看到内存只增加了15K左右:

127.0.0.1:6379> info memory

# Memory

used_memory:850616

used_memory_human:830.68K

但是,同时可以看到pfcount的执行结果并不是100万:

127.0.0.1:6379> pfcount 2016_05_01:unique:ids

(integer) 1009838

可以对100万个uuid使用集合类型进行测试,代码如下:

elements=""

key="2016_05_01:unique:ids:set"

for i in `seq 1 1000000`

do

    elements="${elements} "${i}

    if [[ $((i%1000))  == 0 ]];

    then

        redis-cli sadd ${key} ${elements}

        elements=""

    fi

done

可以看到内存使用了84MB:

127.0.0.1:6379> info memory

# Memory

used_memory:88702680

used_memory_human:84.59M

但独立用户数为100万:

127.0.0.1:6379> scard 2016_05_01:unique:ids:set

(integer) 1000000

表3-6列出了使用集合类型和HperLogLog统计百万级用户的占用空间对比。

表3-6 集合类型和HyperLogLog占用空间对比

数据类型         1天 1个月      1年

集合类型         80M 2.4G          28G

HyperLogLog   15k   450k          5M

 

可以看到,HyperLogLog内存占用量小得惊人,但是用如此小空间来估算如此巨大的数据,必然不是100%的正确,其中一定存在误差率。Redis官方给出的数字是0.81%的失误率。

3.?合并

pfmerge destkey sourcekey [sourcekey ...]

pfmerge可以求出多个HyperLogLog的并集并赋值给destkey,例如要计算2016年3月5日和3月6日的访问独立用户数,可以按照如下方式来执行,可以看到最终独立用户数是7:

127.0.0.1:6379> pfadd 2016_03_06:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4"

(integer) 1

127.0.0.1:6379> pfadd 2016_03_05:unique:ids "uuid-4" "uuid-5" "uuid-6" "uuid-7"

(integer) 1

127.0.0.1:6379> pfmerge 2016_03_05_06:unique:ids 2016_03_05:unique:ids

    2016_03_06:unique:ids

OK

127.0.0.1:6379> pfcount 2016_03_05_06:unique:ids

(integer) 7?

HyperLogLog内存占用量非常小,但是存在错误率,开发者在进行数据结构选型时只需要确认如下两条即可:

只为了计算独立总数,不需要获取单条数据。

可以容忍一定误差率,毕竟HyperLogLog在内存的占用量上有很大的优势。

转载地址:http://vyupa.baihongyu.com/

你可能感兴趣的文章
用PROCEDURE ANALYSE优化MYSQL表结构
查看>>
从4个方面提高用户体验
查看>>
【10-25】OOP基础-飞机游戏知识点
查看>>
HTC仅限拨打紧急电话
查看>>
c#小软件(SaveClassic)开发手记--(3)基础类(注册表操作类RegEdit)
查看>>
Linux下开发常用 模拟 Http get和post请求
查看>>
除法(暴力)
查看>>
Sql中的Exists和in
查看>>
如何修改Entity Framework Db Frist模式下的Entity继承关系?
查看>>
redis实现区间查询
查看>>
azkaban使用
查看>>
ajax请求的异步嵌套问题分析
查看>>
CSS样式学习笔记『W3School』
查看>>
maven热部署
查看>>
HTTP协议 请求篇
查看>>
redis的订阅和发布
查看>>
直接插入排序法
查看>>
1. Git-2.12.0-64-bit .exe下载
查看>>
35.使用拦截器实现权限验证
查看>>
嵌套类&内部类
查看>>