文章目录

  • 引言
  • HyperLogLog 工作原理
  • Spring Boot 集成 Redis
    • 1. 添加依赖
    • 2. 配置 Redis 连接
    • 3. Redis 配置类
  • HyperLogLog 实战应用
    • 1. 基础操作服务类
    • 2. 网站日活跃用户统计
    • 3. 性能测试与误差分析
  • 应用场景分析
    • 适用场景
    • 不适用场景
  • 性能优化技巧
  • 与传统方案对比
  • 结论

在这里插入图片描述

引言

在数据分析和监控系统中,基数统计(即统计唯一元素数量)是一个常见但资源密集型的任务。传统方法在处理大规模数据时面临内存消耗大和计算成本高的问题。Redis 的 HyperLogLog (HLL) 数据结构以极小内存占用(约 12KB)提供接近准确的基数估计,标准误差仅约 0.81%。

接下来我们将探讨如何在 Spring Boot 中使用 Spring Data Redis 实现高效的基数统计。

HyperLogLog 工作原理

HyperLogLog 基于概率算法:

  1. 对每个元素应用哈希函数
  2. 计算哈希值的二进制前导零数量
  3. 使用调和平均数估算基数

这种设计使得 HLL 能够:

  • 以固定内存处理任意大集合
  • 提供 O(1) 时间复杂度的添加和查询操作
  • 支持多集合合并操作

Spring Boot 集成 Redis

1. 添加依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
</dependencies>

2. 配置 Redis 连接

# application.properties
spring.redis.host=localhost
spring.redis.port=6379

3. Redis 配置类

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());return template;}
}

HyperLogLog 实战应用

1. 基础操作服务类

@Service
public class HyperLogLogService {private final RedisTemplate<String, String> redisTemplate;public HyperLogLogService(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}// 添加元素到 HLLpublic void add(String key, String... values) {redisTemplate.opsForHyperLogLog().add(key, values);}// 获取基数估计值public long count(String key) {return redisTemplate.opsForHyperLogLog().size(key);}// 合并多个 HLLpublic void merge(String destinationKey, String... sourceKeys) {redisTemplate.opsForHyperLogLog().union(destinationKey, sourceKeys);}
}

2. 网站日活跃用户统计

@RestController
@RequestMapping("/analytics")
public class AnalyticsController {private final HyperLogLogService hllService;public AnalyticsController(HyperLogLogService hllService) {this.hllService = hllService;}// 记录用户访问@PostMapping("/visit")public ResponseEntity<String> recordVisit(@RequestParam String userId,@RequestParam String date) {String key = "dau:" + date;hllService.add(key, userId);return ResponseEntity.ok("Visit recorded");}// 获取日活跃用户数@GetMapping("/dau")public ResponseEntity<Long> getDailyActiveUsers(@RequestParam String date) {String key = "dau:" + date;long count = hllService.count(key);return ResponseEntity.ok(count);}// 获取多日合并活跃用户数@GetMapping("/mau")public ResponseEntity<Long> getMonthlyActiveUsers(@RequestParam int year,@RequestParam int month) {List<String> keys = new ArrayList<>();LocalDate start = LocalDate.of(year, month, 1);LocalDate end = start.withDayOfMonth(start.lengthOfMonth());for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) {keys.add("dau:" + date);}String monthlyKey = "mau:" + year + "-" + month;hllService.merge(monthlyKey, keys.toArray(new String[0]));return ResponseEntity.ok(hllService.count(monthlyKey));}
}

3. 性能测试与误差分析

@SpringBootTest
public class HyperLogLogTests {@Autowiredprivate HyperLogLogService hllService;@Testvoid testAccuracyWithLargeDataset() {String key = "test:accuracy";int totalUsers = 100_000;Set<String> realUsers = new HashSet<>();// 添加 10 万用户(包含部分重复)for (int i = 0; i < 150_000; i++) {String userId = "user-" + (int)(Math.random() * totalUsers);hllService.add(key, userId);realUsers.add(userId);}long estimatedCount = hllService.count(key);long realCount = realUsers.size();System.out.println("真实基数: " + realCount);System.out.println("HLL估计值: " + estimatedCount);System.out.println("误差率: " + String.format("%.2f%%", 100.0 * Math.abs(realCount - estimatedCount) / realCount));// 典型输出:// 真实基数: 99987// HLL估计值: 100542// 误差率: 0.56%}
}

应用场景分析

适用场景

  1. 大规模用户分析:日活/月活用户统计
  2. 网络监控:统计唯一访问 IP
  3. 广告分析:估算广告曝光独立用户数
  4. 实时数据流:去重计数

不适用场景

  1. 需要精确计数的业务(如金融交易)
  2. 需要获取具体元素的场景
  3. 极小数据集(传统方法更合适)

性能优化技巧

  1. 键名设计优化

    // 使用哈希标签确保相关键在同一槽位
    String key = "{analytics}:dau:" + date;
    
  2. 管道批处理

    public void batchAdd(String key, List<String> values) {redisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (String value : values) {connection.pfAdd(key.getBytes(), value.getBytes());}return null;});
    }
    
  3. 内存优化配置

    # 启用 HLL 稀疏表示(对小数据集更高效)
    spring.redis.hyperloglog.sparse=true
    

与传统方案对比

方案内存占用 (100万用户)精确性合并能力复杂度
MySQL DISTINCT~50MB精确复杂O(n)
Redis SET~16MB精确支持O(1)
Redis HLL~12KB~99.19%高效O(1)

结论

Redis HyperLogLog 为大规模基数统计提供了优雅解决方案:

  1. 内存效率极高 - 固定 12KB 内存占用
  2. 操作复杂度恒定 - O(1) 时间操作
  3. 分布式友好 - 支持多集合并行合并
  4. 易于集成 - Spring Data Redis 提供简洁 API

虽然 HLL 提供的是概率性估计,但在大多数分析场景中,其微小的误差率(<1%)是可接受的,尤其是考虑到它带来的巨大资源节省。对于需要精确统计的场景,可考虑结合使用 HLL 和 Redis Bloom Filter 等互补技术。

提示:在实际生产环境中,建议定期将 HLL 结果持久化到数据库,并设置 Redis 键的 TTL 策略以管理内存使用。

so, 我们可以在 Spring Boot 应用中轻松实现高效、可扩展的基数统计系统,处理海量数据而无需担心资源消耗问题。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92732.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92732.shtml
英文地址,请注明出处:http://en.pswp.cn/web/92732.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

後端開發技術教學(三) 表單提交、數據處理

上回&#xff1a;後端開發技術教學(二) 條件指令、循環結構、定義函數 -CSDN博客 必要資源&#xff1a; trae中文版下載網址: TRAE - The Real AI Engineer phpStudy 2018 : phpStudy - Windows 一键部署 PHP 开发环境 小皮出品 目錄 一、表單提交 1.1 get & post 1.…

Python训练Day39

浙大疏锦行 图像数据的格式&#xff1a;灰度和彩色数据模型的定义显存占用的4种地方 模型参数梯度参数优化器参数数据批量所占显存神经元输出中间状态 batchisize和训练的关系 一、 图像数据的介绍 图像数据&#xff0c;相较于结构化数据&#xff08;表格数据&#xff09;他的特…

十八、MySQL-DML-数据操作-插入(增加)、更新(修改)、删除

DML数据操作添加数据更新(修改)数据删除数据总结代码&#xff1a; -- DML:数据操作语言-- -- DML:插入数据-insert -- 1.为tb_emp表的username,name&#xff0c;gender 字股插入值insert into tb_emp(username,name,gender,create_time,update_time) values (Toki,小时,2,now()…

Linux 安装 JDK 8u291 教程(jdk-8u291-linux-x64.tar.gz 解压配置详细步骤)​

一、准备工作 ​下载 JDK 安装包​ 去 Oracle 官网或者可信的镜像站下载&#xff1a; ​jdk-8u291-linux-x64.tar.gz​ &#xff08;这是一个压缩包&#xff0c;不是安装程序&#xff0c;解压就能用&#xff09; ​jdk-8u291-linux-x64.tar.gz​下载链接&#xff1a;https://pa…

蓝桥杯----锁存器、LED、蜂鸣器、继电器、Motor

(七)、锁存器1、原理蓝桥杯中数据传入口都是P0&#xff0c;也就是数码管段选、位选数据、LED亮灭的数据、蜂鸣器启动或禁用的数据&#xff0c;外设启动或者关闭都需要通过P0写入数据&#xff0c;那么如何这样共用一个端口会造成冲突嘛&#xff0c;答案是肯定的。所以蓝桥杯加入…

AI热点周报(8.3~8.9):OpenAI重返开源,Anthropic放大招,Claude4.1、GPT5相继发布

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录一、OpenAI的"开源回归"&#xff1a;时隔5年的战略大转弯1. GPT-OSS系列&a…

《Kubernetes部署篇:基于x86_64+aarch64架构CPU+containerd一键离线部署容器版K8S1.33.3高可用集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;企业级K8s集群运维实战 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要针对不同的客户环境部署基于containerd容器版 K8S 1.33.3集群&a…

Linux抓包命令tcpdump详解笔记

文章目录一、tcpdump 是什么&#xff1f;二、基本语法三、常用参数说明四、抓包示例&#xff08;通俗易懂&#xff09;1. 抓所有数据包&#xff08;默认 eth0&#xff09;2. 指定接口抓包3. 抓取端口 80 的数据包&#xff08;即 HTTP 请求&#xff09;4. 抓取访问某个 IP 的数据…

抖音、快手、视频号等多平台视频解析下载 + 磁力嗅探下载、视频加工(提取音频 / 压缩等)

跟你们说个安卓上的下载工具&#xff0c;还挺厉害的。它能支持好多种下载方式&#xff0c;具体多少种我没细数&#xff0c;反正挺全乎的。​ 平时用得最多的就是视频解析&#xff0c;像抖音、快手、B 站上那些视频&#xff0c;想存下来直接用它就行&#xff0c;连海外视频的也能…

【iOS】JSONModel源码学习

JSONModel源码学习前言JSONModel的使用最基础的使用转换属性名称自定义错误模型嵌套JSONModel的继承源码实现initWithDictionaryinit__doesDictionaryimportDictionary优点前言 之前了解过JSONModel的一些使用方法等&#xff0c;但是对于底层实现并不清楚了解&#xff0c;今天…

SmartMediaKit 模块化音视频框架实战指南:场景链路 + 能力矩阵全解析

✳️ 引言&#xff1a;从“内核能力”到“模块体系”的演进 自 2015 年起&#xff0c;大牛直播SDK&#xff08;SmartMediaKit&#xff09;便致力于打造一个可深度嵌入、跨平台兼容、模块自由组合的实时音视频基础能力框架。经过多轮技术迭代与场景打磨&#xff0c;该 SDK 已覆…

【第5话:相机模型1】针孔相机、鱼眼相机模型的介绍及其在自动驾驶中的作用及使用方法

相机模型介绍及相机模型在自动驾驶中的作用及使用方法 相机模型是计算机视觉中的核心概念&#xff0c;用于描述真实世界中的点如何投影到图像平面上。在自动驾驶系统中&#xff0c;相机模型用于环境感知&#xff0c;如物体检测和场景理解。下面我将详细介绍针孔相机模型和鱼眼相…

推荐一款优质的开源博客与内容管理系统

Halo是一款由Java Spring Boot打造的开源博客与内容管理系统&#xff08;CMS&#xff09;&#xff0c;在 GitHub上拥有超过36K Start的活跃开发者社区。它使用GPL‑3.0授权开源&#xff0c;稳定性与可维护性极高。 Halo的设计简洁、注重性能&#xff0c;同时保持高度灵活性&a…

【GPT入门】第43课 使用LlamaFactory微调Llama3

【GPT入门】第43课 使用LlamaFactory微调Llama31.环境准备2. 下载基座模型3.LLaMA-Factory部署与启动4. 重新训练![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e7aa869f8e2c4951a0983f0918e1b638.png)1.环境准备 采购autodl服务器&#xff0c;24G,GPU,型号3090&am…

计算机网络:如何理解目的网络不再是一个完整的分类网络

这一理解主要源于无分类域间路由&#xff08;CIDR&#xff09;技术的广泛应用&#xff0c;它打破了传统的基于类的IP地址分配方式。具体可从以下方面理解&#xff1a; 传统分类网络的局限性&#xff1a;在早期互联网中&#xff0c;IP地址被分为A、B、C等固定类别&#xff0c;每…

小米开源大模型 MiDashengLM-7B:不仅是“听懂”,更能“理解”声音

目录 前言 一、一枚“重磅炸弹”&#xff1a;开源&#xff0c;意味着一扇大门的敞开 二、揭秘MiDashengLM-7B&#xff1a;它究竟“神”在哪里&#xff1f; 2.1 “超级耳朵” 与 “智慧大脑” 的协作 2.2 突破&#xff1a;从 “听见文字” 到 “理解世界” 2.3 创新训练&a…

mysql出现大量redolog、undolog排查以及解决方案

排查步骤 监控日志增长情况 -- 查看InnoDB状态 SHOW ENGINE INNODB STATUS;-- 查看redo log配置和使用情况 SHOW VARIABLES LIKE innodb_log_file%; SHOW VARIABLES LIKE innodb_log_buffer_size;-- 查看undo log信息 SHOW VARIABLES LIKE innodb_undo%;检查长时间运行的事务 -…

华为网路设备学习-28(BGP协议 三)路由策略

目录&#xff1a; 一、BGP路由汇总1、注&#xff1a;使用network命令注入的BGP不会被自动汇总2、主类网络号计算过程如下&#xff1a;3.示例 开启BGP路由自动汇总bgp100 开启BGP路由自动汇总import-route 直连路由 11.1.1.0 /24对端 为 10.1.12.2 AS 2004.手动配置BGP路…

微信小程序中实现表单数据实时验证的方法

一、实时验证的基本实现思路表单实时时验证通过监听表单元素的输入事件&#xff0c;在用户输入过程中即时对数据进行校验&#xff0c;并并即时反馈验证结果&#xff0c;主要实现步骤包括&#xff1a;为每个表单字段绑定输入事件在事件处理函数中获取当前输入值应用验证规则进行…

openpnp - 顶部相机如果超过6.5米影响通讯质量,可以加USB3.0信号放大器延长线

文章目录openpnp - 顶部相机如果超过6.5米影响通讯质量&#xff0c;可以加USB3.0信号放大器延长线概述备注ENDopenpnp - 顶部相机如果超过6.5米影响通讯质量&#xff0c;可以加USB3.0信号放大器延长线 概述 手头有1080x720x60FPS的摄像头模组备件&#xff0c;换上后&#xff…