UV 统计- HLL算法(JAVA实现)

article/2025/10/8 15:49:19

HLL是什么

HyperLogLog(HLL)算法经常在数据库中被用来统计某一字段的Distinct Value,比如Redis的HyperLogLog结构。目前在我们项目中用于UV统计。
网上有一篇大佬博文十分深入:
https://www.jianshu.com/p/55defda6dcd2
注意:
1.此算法是近似估算值,该算法能在一定误差内近似统计去重数,可以输出空间内去重数大小,若要求UV详细数据则该方法不适用。
2.需要在空间与准确性中取舍。若要求准确性较高,则HLL生成的空间就会较大。

基本流程

统计基本流程:
请添加图片描述

说明:

  • hll空间处理时一般使用的是对象字节,而存储时一般不会将对象字节存入,所以这里我们可以将空间对象转换为base64再存储。
  • 这里涉及到对放入对象的hash处理,这里的hash方法值十分重要,直接影响到基数准确与否,目前我们使用的Guava工具包: com.google.common.hash.HashFunction#hashString

具体实现(Java)

HLL我们使用的工具包为java-hll
地址:java-hll

     /*** 根据value向指定key空间进行基数整合* @param ea* @param moduleKey 模块key* @param key 模块中物料 key* @param value 新增value*/public void incrementUV(String ea, String moduleKey, String key, String value){Preconditions.checkArgument(!Strings.isNullOrEmpty(ea));Preconditions.checkArgument(!Strings.isNullOrEmpty(moduleKey));Preconditions.checkArgument(!Strings.isNullOrEmpty(key));Preconditions.checkArgument(!Strings.isNullOrEmpty(value));SerializableHLL existedHLL;// 从库中获取是否有对应hll_valueString existedHllBytesBase64 = uvHllStatisticDao.getHllValue(ea, moduleKey, key);if(existedHllBytesBase64 == null){// 创建一个新的空间existedHLL = HLLUtil.newHLL();}else{// 将已有的数据转换为空间existedHLL = HLLUtil.newHLLFromBytesBase64(existedHllBytesBase64);}// 在空间中添加数据existedHLL.addRaw(HLLUtil.hash(value));// 计算空间内数据总数long newCount = existedHLL.cardinality();uvHllStatisticDao.upsertHllValuesAndCount(ea, moduleKey, key, existedHLL.toBytesBase64(), (int)newCount);}

上面方法是其中一个使用案例,在这里封装了一个HLLUtil的工具包

public class HLLUtil {/*** log2m 桶数的log-base-2 比如桶数为64,则log2m=6,该参数应在4-30之间*/private static final int LOG2M = 8;/*** 每个桶的位数,在1-8之间(最大为一个字节)*/private static final int REG_WIDTH = 8;/*** 当EXPLICIT提升为SPARSE的阈值,取值为1-18*/private static final int EXP_THRESH = 5;private static final HashFunction HASH_FUNCTION = Hashing.murmur3_128(1853);public static SerializableHLL newHLL(){/*** 第三个参数:标识SPARSE是否被使用* 第四个参数:计算的类型* EXPLICIT 进准存储,基于Long的Hashset* SPARSE 稀疏计算,数据量不大时为节省空间,只保存有值的桶* FULL 大部分桶有值时,用位向量存储桶内内容*/HLL hll = new HLL(LOG2M, REG_WIDTH, EXP_THRESH, false, HLLType.EXPLICIT);return new SerializableHLL(hll);}public static SerializableHLL newHLL(byte[] hllSpace){HLL hll = HLL.fromBytes(hllSpace);return new SerializableHLL(hll);}public static SerializableHLL newHLLFromBytesBase64(String base64){return new SerializableHLL(HLL.fromBytes(Base64.getDecoder().decode(base64)));}/*** 使用的是EXPLICIT计算方式所以需要计算Hash这里使用的是Guava 工具包* @return hash值*/public static long hash(CharSequence charSequence){return HASH_FUNCTION.hashString(charSequence, Charset.forName("UTF-8")).asLong();}
}

HLL 序列化对象类

public class SerializableHLL implements Serializable {private static final long serialVersionUID = 1L;private transient HLL targetHLL;public SerializableHLL(HLL targetHLL) {this.targetHLL = targetHLL;}public synchronized void addRaw(final long rawValue) {targetHLL.addRaw(rawValue);}public synchronized long cardinality() {return targetHLL.cardinality();}public synchronized byte[] toBytes(){return targetHLL.toBytes();}public synchronized String toBytesBase64(){return Base64.getEncoder().encodeToString(targetHLL.toBytes());}public synchronized void merge(SerializableHLL hll){this.targetHLL.union(hll.targetHLL);}public synchronized void merge(byte[] hllSpace){this.targetHLL.union(HLL.fromBytes(hllSpace));}private void writeObject(ObjectOutputStream oos) throws IOException{oos.defaultWriteObject();byte[] bs = targetHLL.toBytes();oos.writeInt(bs.length);oos.write(bs);}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{ois.defaultReadObject();int byteLength = ois.readInt();byte[] bs = new byte[byteLength];ois.read(bs);targetHLL = HLL.fromBytes(bs);}
}

http://chatgpt.dhexx.cn/article/UKHPnEmS.shtml

相关文章

HTTP的Referrer Policy

客户端通过设置Referrer Policy来控制是否在请求头中告知服务端请求来源。来源信息写在生成的请求头的referer中。 注意 Referer 实际上是单词 “referrer” 的错误拼写。Referrer-Policy 这个首部并没有延续这个错误拼写。 Referrer Policy的取值: no-referrer 整…

接口基础-HTTP请求中的referrer和Referrer-Policy

本文将介绍一个涉及安全和隐私的http请求头中的字段—referrer,以及如何通过Referrer Policy去修改referrer的值或者是显示与否。 什么是referrer 当一个用户点击当前页面中的一个链接,然后跳转到目标页面时,目标页面会收到一个信息&#x…

Referrer还是Referer? 一个迷人的错误

诗人郑愁予曾经在一首诗中写道:我达达的马蹄是个美丽的错误,我不是归人,是个过客。而对我来说,十九岁之前的我,一样是个沉浸在诗歌中的文艺少年。十九岁之后的我,作为一名程序员,更多的是邂逅各…

HTTP系列之Referer和Referrer policy简介

文章目录 1、前言摘要2、Referer简介3、Referer安全性4、相关术语5、Referrer Policy5.1、no-referrer5.2、no-referrer-when-downgrade5.3、same-origin5.4、origin5.5、strict-origin5.6、origin-when-cross-origin5.7、strict-origin-when-cross-origin5.8、unsafe-url5.9、…

浅析HTTP请求中的referrer和Referrer-Policy

本文将介绍一个涉及安全和隐私的http请求头中的字段—referrer,以及如何通过Referrer Policy去修改referrer的值或者是显示与否。 什么是referrer 当一个用户点击当前页面中的一个链接,然后跳转到目标页面时,目标页面会收到一个信息&#xff…

document.referrer之隐藏来源

document.referrer document.referrer是用来获取跳转链接的来源,正规的解释是:referrer 属性可返回载入当前文档的文档的 URL。 实际中使用在广告相关业务中较多,包括推广等。 举个例子: 比如我们从百度中跳转到w3c,那我们从w3…

java referrer_JavaScript中document.referrer的用法详解

前言 在JavaScript中,document对象有很多属性,其中有3个与对网页的请求有关的属性,它们分别是URL、domain和referrer。 URL属性包含页面完整的URL,domain属性中只包含页面的域名,而referrer属性中则保存着链接到当前页…

meta标签的 referrer

首先&#xff0c;我先不解释&#xff0c;先看下我下面的请求数据图。 1.默认 (<meta name"referrer" content"origin"/>不写 也不 指定时) 2.origin时 3.no-referrer时 实验了这三个&#xff0c;就知道referrer的默认值和请求头的参数键值数据&…

设置referrer

1.全界面设置 所有界面挑战时携带地址origin&#xff0c;所有请求不携带地址never&#xff08;修改后记得从新启动&#xff09; <meta name"referrer" content"origin"> 2.单页面设置 vue的话可以设置一个vue-meta的插件&#xff08;暂不介绍&…

php referrer policy,Referrer Policy介绍

referer的写法是错的&#xff0c;正确的是referrer。大概是早期http规范的拼写错误&#xff0c;然后为了保持向下兼容&#xff0c;就将错就错了。 一、九种policy enum ReferrerPolicy { "", "no-referrer", "no-referrer-when-downgrade", &quo…

Referer和Referrer Policy详解

最近换了个负责网络安全的leader&#xff0c;整个部门开始网络安全整顿&#xff0c;我们负责WEB的接到通知要求防御CSRF攻击&#xff0c;设置referer白名单。之前看过一点referer相关的&#xff0c;但是了解不够深入&#xff0c;趁这次机会好好了解了一下。 1. 什么是 Referer…

Referer  是什么?

版权所属&#xff1a;SO JSON在线解析 原文地址&#xff1a;https&#xff1a;//www.sojson.com/blog/58.html 转载时必须以链接形式注明原始出处及本声明。 Referer 是 HTTP 请求header 的一部分&#xff0c;当浏览器&#xff08;或者模拟浏览器行为&#xff09;向web 服…

响应式网页设计

目录 Responsive Web Design响应式网页设计流体网格&#xff08;Fluid grid&#xff09;弹性图片&#xff08;Flexible image&#xff09;srcset和sizes属性 SVGbackground-size CSS3媒体查询&#xff08;CSS3 media query&#xff09;和断点 meta渐进增强过时控制工具Moderniz…

css 与 html5

折叠隐藏文字 快捷键&#xff1a;span*6&#xff0c;然后敲一个tap键&#xff0c;会生成6个span标签写业务style之前&#xff0c;需要先清除style的内置样式也就是在style里面写上* {margin: 0;padding: 0;}注意body的height:100vh;不要写100%弹性盒子能使子元素垂直居中的条件…

前端Vue书籍翻页功能利用turn.js来完成以及知识点(源码)

目录 下载文档开始构造方法可配置项 方法语法 事件两种方式添加事件 自动翻页loading加载功能 案例CSSbasic.css源码如下 JS里面代码太多了,直接官网下载index.html源码如下 最终效果如下 下载 下载完里面有源码,好几种翻页效果,很不错~ 官网 文档 接口文档 开始 构造方法 …

html局部翻页效果,基于Turn.js 实现翻书效果实例解析

最近项目经理我个项目练练手,其项目需求是要实现翻书效果,看到这个需求后,我真是懵了,这咋整,我可是java出身的啊,这个问题真是难住我了,后来有同事的指导,之前他曾经做过PC版的翻书效果,当时使用的是Turn.js ,查过其相关API后,整个人突然豁然开朗呀,使用Turn.js 完…

用Modernizr和Yepnope进行递归增强

Alex Sexton的yepnope.js脚本加载程序的1.0版已于上周发布&#xff0c;因此我认为这是一个向您展示如何将Yepnope与Modernizr结合使用HTML5功能而又不招致最新用户下载的绝佳时机。 -划痕的浏览器。 什么是回归增强&#xff1f; 您可能已经熟悉渐进增强的概念&#xff1a;设计…

modernizr_使用Modernizr和Yepnope进行递归增强

modernizr Alex Sexton的yepnope.js脚本加载程序的1.0版已于上周发布&#xff0c;因此我认为这是向您展示如何将Yepnope与Modernizr结合起来以利用HTML5功能而又不招致最新用户的最佳时机。 -划痕的浏览器。 什么是回归增强&#xff1f; 您可能已经熟悉渐进增强的概念&#x…

Modernizr YepNope Tips

<style> <!-- p {text-indent:2em; line-height:24px; font-size:14px} h1, img {margin:0.6em 0} --> </style> 本文由前端开发whqet翻译自WDL&#xff0c;Rochester Oliveira2013年5月2日写的文章Modernizr & YepNope Tips。 每天都有新的更好的浏览…

教你如何申请注册微软邮箱【快速接收发送国外邮件】

如果要收发国内的邮件。网易和QQ不错的选择&#xff0c;如果接受国外邮件&#xff0c;还是国际性的公司&#xff0c;微软的outlook据说用户体验感比较好&#xff0c;先申请着&#xff0c;以备不时之需&#xff01; 申请地址&#xff1a;https://outlook.live.com/owa/ 点击创…