HyperLogLog计算PV/UV

 

Redis HyperLogLog

      Redis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

      在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

 

 

HyperLogLog

        Hyper LogLog计数器就是估算Nmax为基数的数据集仅需使用loglog(Nmax)+O(1) bits就可以。如线性计数器的Hyper LogLog计数器允许设计人员指定所需的精度值,在Hyper LogLog的情况下,这是通过定义所需的相对标准差和预期要计数的最大基数。大部分计数器通过一个输入数据流M,并应用一个哈希函数设置h(M)来工作。这将产生一个S = h(M) of {0,1}^∞字符串的可观测结果。通过分割哈希输入流成m个子字符串,并对每个子输入流保持m的值可观测 ,这就是相当一个新Hyper LogLog(一个子m就是一个新的Hyper LogLog)。利用额外的观测值的平均值,产生一个计数器,其精度随着m的增长而提高,这只需要对输入集合中的每个元素执行几步操作就可以完成。其结果是,这个计数器可以仅使用1.5 kb的空间计算精度为2%的十亿个不同的数据元素。与执行 HashSet所需的120 兆字节进行比较,这种算法的效率很明显。

 

 

 

误差率 

HyperLogLog计算PV/UV_第1张图片

 

 

测试代码

package com.javagc.hyperloglog;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

import com.clearspring.analytics.stream.cardinality.HyperLogLog;

public class TestHyperLogLog {

	public static void main(String[] args) throws IOException {
		
		HyperLogLog hyperLogLog1 = new HyperLogLog(12);
		for(int i=0;i<10000000;i++) {
        	hyperLogLog1.offer(i+"haperloglog");
        }
		//输出统计结果,会有3%误差
		System.out.println(hyperLogLog1.cardinality());
		
		//计算对象大小
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream ooo = new ObjectOutputStream(baos);
        ooo.writeObject(hyperLogLog1);
        byte[] bys = baos.toByteArray();
        // 长度需要减去 4 个字节:AC ED 00 05
        // AC ED -- 魔法数字
        // 00 05 -- 版本号
        System.out.println((bys.length - 4)/1024+" kb");

	}

}

 

 

资料

http://www.redis.net.cn/tutorial/3513.html

https://github.com/addthis/stream-lib 

http://blog.csdn.net/hguisu/article/details/8433731 

http://highscalability.com/blog/2012/4/5/big-data-counting-how-to-count-a-billion-distinct-objects-us.html

你可能感兴趣的:(HyperLogLog计算PV/UV)