关于HyperLogLog去重优化


点击箭头处“蓝色字”,关注我们哦!!

推荐阅读

1

Flink去重第一弹:  MapState去重 

2

Flink去重第二弹:SQL方式 

3

Flink去重第三弹:HyperLogLog去重

在HyperLogLog去重实现中,如果要求误差在0.001以内,那么就需要1048576个int, 也就是会消耗4M的存储空间,但是在实际使用中有很多的维度的统计是达不到这个数据量,那么可以在这里做一个优化,优化方式是:初始HyperLogLog内部使用存储是一个set集合,当set大小达到了指定大小(1048576)就转换为HyperLogLog存储方式。这种方式可以有效减小内存消耗。

实现代码:

public class OptimizationHyperLogLog {
    //hyperloglog结构
    private HyperLogLog hyperLogLog;
    //初始的一个set
    private Set<Integer> set;
     
    private double rsd;
    
    //hyperloglog的桶个数,主要内存占用
    private int bucket;


    public OptimizationHyperLogLog(double rsd){
        this.rsd=rsd;
        this.bucket=1 << HyperLogLog.log2m(rsd);
        set=new HashSet<>();      
       }


   //插入一条数据
    public void offer(Object object){
        final int x = MurmurHash.hash(object);
        int currSize=set.size();
        if(hyperLogLog==null && currSize+1>bucket){ 
           //升级为hyperloglog
           hyperLogLog=new HyperLogLog(rsd);
           for(int d: set){
               hyperLogLog.offerHashed(d);
           }
           set.clear();
        }


        if(hyperLogLog!=null){
            hyperLogLog.offerHashed(x);
        }else {
            set.add(x);
        }
    }


    //获取大小
    public long cardinality() {
      if(hyperLogLog!=null) return hyperLogLog.cardinality();
      return set.size();
    }
}

初始化:入参同样是一个允许的误差范围值rsd,计算出hyperloglog需要桶的个数bucket,也就需要是int数组大小,并且初始化一个set集合hashset;

数据插入:使用与hyperloglog同样的方式将插入数据转hash, 判断当前集合的大小+1是否达到了bucket,不满足则直接添加到set中,满足则将set里面数据转移到hyperloglog对象中并且清空set, 后续数据将会被添加到hyperloglog中;

这种写法没有考虑并发情况,在实际使用情况中也不会存在并发问题。

—END—

关注回复Flink

获取更多系列

好看,就要点个"在看"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值