三分钟了解Redis HyperLogLog 数据结构

news2025/2/5 14:50:50

文章目录

  • 0. 前言
  • 1. 原理
    • 1.2 原理解析
  • 2.实战案例
  • 3. Redis从入门到精通系列文章
  • 4. 常见问题
    • 4.1. 什么是Redis HyperLogLog?
    • 4.2. HyperLogLog算法的核心思想是什么?
    • 4.3. HyperLogLog算法的误差率如何控制?
    • 4.4. HyperLogLog算法的存储空间大小与误差率的关系是怎样的?
    • 4.5. HyperLogLog算法在Redis中如何实现?
    • 4.6. HyperLogLog算法有什么应用场景?
    • 4.7. HyperLogLog算法的优缺点是什么?
    • 4.8. Redis HyperLogLog与Bloom Filter有什么区别?
    • 4.9. Redis HyperLogLog如何处理哈希冲突?
    • 4.10. Redis HyperLogLog的优化策略有哪些?

在这里插入图片描述

0. 前言

HyperLogLog算法是一种非常有用的数据结构和算法,它可以在很小的空间内估计一个集合中不重复元素的数量,具有很高的效率和精度,非常适合用于大数据量的计数场景。在使用时,需要注意HyperLogLog算法的概率特性,以及对误差的容忍度,才能得到最好的效果。

1. 原理

HyperLogLog是一种基数估计算法,它可以在只使用很少的内存空间的情况下,近似地估计一个集合中不重复元素的数量。

HyperLogLog算法的核心思想是将每个元素映射为一个二进制字符串,并对这个字符串进行一些特殊的处理,最终得到一个估计值,表示集合中不重复元素的数量。HyperLogLog算法的基本原理可以概括为以下几步:

  1. 对每个元素进行哈希运算,得到一个二进制字符串。

  2. 将这个二进制字符串分成若干个组(比如分成4个组),每个组的长度相等。

  3. 对每个组分别取最高位为1的位置(即从左往右数第一个为1的位置),得到一个索引值。

  4. 将这些索引值合并成一个二进制数,并将其转换为一个整数,作为集合中不重复元素的数量的估计值。

HyperLogLog算法的估计值的精度和存储空间有关,通常来说,可以通过调整存储空间的大小来控制估计值的误差率。HyperLogLog算法的误差率可以控制在0.81%以内。

下面是一个简单的实例,说明HyperLogLog算法的基本原理:

假设有一个集合S,包含以下元素:

S = {A, B, C, D, E, F, G, H}

首先,对每个元素进行哈希运算,得到一个二进制字符串:

A: 10101101
B: 11011101
C: 01101001
D: 01011011
E: 00111010
F: 10011011
G: 00111011
H: 00101101

然后,将这些二进制字符串分成若干个组,每个组的长度相等:

1010 1101
1101 1101
0110 1001
0101 1011
0011 1010
1001 1011
0011 1011
0010 1101

对每个组分别取最高位为1的位置,得到一个索引值:

4 3
4 3
2 4
2 3
1 3
4 3
1 3
1 4

将这些索引值合并成一个二进制数,并将其转换为一个整数,作为集合中不重复元素的数量的估计值:

11001010 -> 202

这个估计值可能会存在一定的误差,但是通过调整存储空间的大小,可以控制误差率在可接受的范围内。

HyperLogLog算法是一种非常有用的基数估计算法,它可以在很小的内存空间内,近似地估计一个集合中不重复元素的数量,具有很高的效率和精度,非常适合用于大数据量的计数场景。
Redis HyperLogLog是一种基于概率统计算法的数据结构,用于近似地计算一个集合中不重复元素的数量。它的优点是使用很少的内存来存储大量的元素,并且可以在不牺牲太多精度的情况下,快速地计算元素的数量。

HyperLogLog算法最初是由Philippe Flajolet和其它的研究人员提出的,它的核心思想是将每个元素映射为一个二进制字符串,并对这个字符串进行一些特殊的处理,最终得到一个估计值,表示集合中不重复元素的数量。在Redis中,HyperLogLog是通过一个专门的命令来实现的,这个命令的名称是PFADD,它可以用来添加元素到HyperLogLog中,还有一个命令PFCOUNT,可以用来获取HyperLogLog中不重复元素的数量。

HyperLogLog算法的核心技术是基数估计(cardinality estimation),它是一种通过概率统计算法来估计一个集合中不重复元素数量的方法。HyperLogLog算法的基本思路是对每个元素进行一些特殊的映射处理,然后将这些处理后的结果聚合起来,得到一个估计值。这个估计值的精度取决于使用的存储空间(即HyperLogLog的大小),通常来说,HyperLogLog的误差率可以控制在0.81%以内。

HyperLogLog算法的具体实现是比较复杂的,需要涉及到一些概率统计和数学知识。在Redis中,HyperLogLog算法是通过一些专门的数据结构和算法来实现的,这些数据结构和算法的底层实现是比较复杂的,但对于使用者来说,只需要掌握一些基本的命令即可。

在使用HyperLogLog算法时,需要注意以下几点:

  1. HyperLogLog算法是一种概率算法,它的估计值可能会出现一定的误差,因此在使用时需要根据实际情况来选择HyperLogLog的大小,以及对误差的容忍度。

  2. HyperLogLog算法只能用来估计集合中不重复元素的数量,不能用来判断具体的元素是否在集合中。

  3. 在使用PFADD命令向HyperLogLog中添加元素时,需要注意元素的唯一性,重复的元素不会被重复计算。

  4. 在使用PFCOUNT命令获取HyperLogLog中不重复元素的数量时,需要注意这个值是一个近似值,可能会存在一定的误差。

1.2 原理解析

HyperLogLog 是一种概率数据结构,它使用概率算法来统计集合的近似基数。而它算法的最本源则是伯努利过程。

伯努利过程就是一个抛硬币实验的过程。抛一枚正常硬币,落地可能是正面,也可能是反面,二者的概率都是 1/2 。伯努利过程就是一直抛硬币,直到落地时出现正面位置,并记录下抛掷次数 k。比如说,抛一次硬币就出现正面了,此时 k 为 1; 第一次抛硬币是反面,则继续抛,直到第三次才出现正面,此时 k 为 3。

在这里插入图片描述
(备注:有特殊公式符号,无法显示,所以截图贴在该位置)

下面,我们就来讲解一下 HyperLogLog 是如何模拟伯努利过程,并最终统计集合基数的。

HyperLogLog 在添加元素时,会通过 Hash 函数,将元素转为 64 位比特串,例如输入 5,便转为 101(省略前面的 0,下同)。这些比特串就类似于一次抛硬币的伯努利过程。比特串中,0 代表了抛硬币落地是反面,1 代表抛硬币落地是正面,如果一个数据最终被转化了 10010000,那么从低位往高位看,我们可以认为,这串比特串可以代表一次伯努利过程,首次出现 1 的位数为 5,就是抛了 5 次才出现正面。

所以 HyperLogLog 的基本思想是利用集合中数字的比特串第一个 1 出现位置的最大值来预估整体基数,但是这种预估方法存在较大误差,为了改善误差情况,HyperLogLog 中引入分桶平均的概念,计算 m 个桶的调和平均值。

在这里插入图片描述

Redis 中 HyperLogLog 一共分了 2^14 个桶,也就是 16384 个桶。每个桶中是一个 6 bit 的数组,如下图所示。

在这里插入图片描述

HyperLogLog 将上文所说的 64 位比特串的低 14 位单独拿出,它的值就对应桶的序号,然后将剩下 50 位中第一次出现 1 的位置值设置到桶中。50 位中出现 1 的位置值最大为 50,所以每个桶中的 6 位数组正好可以表示该值。

在设置前,要设置进桶的值是否大于桶中的旧值,如果大于才进行设置,否则不进行设置。示例如下图所示。

在这里插入图片描述

此时为了性能考虑,是不会去统计当前的基数的,而是将 HyperLogLog 头的 card 属性中的标志位置为 1,表示下次进行 pfcount 操作的时候,当前的缓存值已经失效了,需要重新统计缓存值。在后面 pfcount 流程的时候,发现这个标记为失效,就会去重新统计新的基数,放入基数缓存。

在计算近似基数时,就分别计算每个桶中的值,带入到上文将的 DV 公式中,进行调和平均和结果修正,就能得到估算的基数值。

2.实战案例

假设有一个在线商城系统,需要统计每个商品浏览量的数量,以便进行商品推荐和排序等操作。如果使用传统的数据结构和算法,需要使用一个哈希表来存储每个商品的浏览量,这样会占用大量的内存空间。而使用Redis HyperLogLog算法,可以使用很少的内存来存储大量的商品浏览量,并且可以快速地估计每个商品的浏览量。

下面是一个使用Spring Boot和Redis HyperLogLog算法实现商品浏览量统计的例子:

首先,在pom.xml文件中添加Redis和Spring Data Redis的依赖:

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

然后,在application.properties文件中配置Redis的连接信息:

spring.redis.host=localhost
spring.redis.port=6379

接着,定义一个RedisTemplate的Bean,用于操作Redis:

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return redisTemplate;
}

然后,定义一个商品浏览量服务类,用于实现商品浏览量的统计和查询:

@Service
public class ProductViewService {

    private final RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public ProductViewService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void addViewCount(String productId, String userId) {
        String key = "product:" + productId + ":view";
        String value = userId;
        redisTemplate.opsForHyperLogLog().add(key, value);
    }

    public long getViewCount(String productId) {
        String key = "product:" + productId + ":view";
        return redisTemplate.opsForHyperLogLog().size(key);
    }
}

在addViewCount方法中,使用PFADD命令向HyperLogLog中添加元素,元素的值为userId,表示这个用户浏览了这个商品。在getViewCount方法中,使用PFCOUNT命令获取HyperLogLog中不重复元素的数量,即为这个商品的浏览量。

最后,在商品详情页中调用addViewCount方法,统计商品的浏览量,在商品列表页中调用getViewCount方法,显示每个商品的浏览量。

@GetMapping("/product/detail/{id}")
public String productDetail(@PathVariable("id") String id, HttpSession session) {
    String userId = session.getId();
    productViewService.addViewCount(id, userId);
    // other logic
}

@GetMapping("/product/list")
public List<Product> productList() {
    List<Product> products = productService.getProducts();
    for (Product product : products) {
        long viewCount = productViewService.getViewCount(product.getId());
        product.setViewCount(viewCount);
    }
    return products;
}

这样,就可以使用Redis HyperLogLog算法来实现商品浏览量的统计和查询,大大地节省了内存空间,并且能够快速地获取每个商品的浏览量。

3. Redis从入门到精通系列文章

《Redis 从入门到精通【进阶篇】之高可用哨兵机制(Redis Sentinel)详解》
《Redis 从入门到精通【进阶篇】之redis主从复制详解》
《Redis 从入门到精通【进阶篇】之Redis事务详解》
《Redis从入门到精通【进阶篇】之对象机制详解》
《Redis从入门到精通【进阶篇】之消息传递发布订阅模式详解》
《Redis从入门到精通【进阶篇】之持久化 AOF详解》
《Redis从入门到精通【进阶篇】之持久化RDB详解》
《Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解》
《Redis从入门到精通【高阶篇】之底层数据结构快表QuickList详解》
《Redis从入门到精通【高阶篇】之底层数据结构简单动态字符串(SDS)详解》
《Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解》
《Redis从入门到精通【进阶篇】之数据类型Stream详解和使用示例》

4. 常见问题

根据上面的学习,我们来简答一下常见的Redis数据结构相关面试题
Redis HyperLogLog是一个非常有用的基数估计算法,常常在面试中被提及。下面是一些常见的Redis HyperLogLog面试题及其答案:

4.1. 什么是Redis HyperLogLog?

答:Redis HyperLogLog是一种基数估计算法,它可以在只使用很少的内存空间的情况下,近似地估计一个集合中不重复元素的数量。

4.2. HyperLogLog算法的核心思想是什么?

答:HyperLogLog算法的核心思想是将每个元素映射为一个二进制字符串,并对这个字符串进行一些特殊的处理,最终得到一个估计值,表示集合中不重复元素的数量。

4.3. HyperLogLog算法的误差率如何控制?

答:HyperLogLog算法的误差率可以通过调整存储空间的大小来控制,通常来说,可以将存储空间的大小设置为2^b个字节,其中b是一个整数,表示二进制字符串的长度。

4.4. HyperLogLog算法的存储空间大小与误差率的关系是怎样的?

答:HyperLogLog算法的存储空间大小与误差率成反比例关系,存储空间越大,误差率越小。

4.5. HyperLogLog算法在Redis中如何实现?

答:在Redis中,可以使用PFADD命令向HyperLogLog中添加元素,使用PFCOUNT命令获取HyperLogLog中不重复元素的数量。

4.6. HyperLogLog算法有什么应用场景?

答:HyperLogLog算法可以用于统计网站的UV(Unique Visitor)和PV(Page View)等指标,也可以用于计算各种统计分析数据,如用户活跃度、广告点击率等。

4.7. HyperLogLog算法的优缺点是什么?

答:HyperLogLog算法的优点是可以在很小的内存空间内,近似地估计一个集合中不重复元素的数量,具有很高的效率和精度,非常适合用于大数据量的计数场景。缺点是HyperLogLog算法只能估计不重复元素的数量,而不能精确地计算,误差率也受到存储空间大小的限制。

4.8. Redis HyperLogLog与Bloom Filter有什么区别?

答:Redis HyperLogLog和Bloom Filter都是基数估计算法,但是它们的应用场景略有不同。HyperLogLog算法适用于估计集合中不重复元素的数量,而Bloom Filter算法则适用于判断一个元素是否属于某个集合。此外,HyperLogLog算法的误差率可以控制在一个比较小的范围内,而Bloom Filter算法的误差率会随着存储空间大小的增加而逐渐减小。

4.9. Redis HyperLogLog如何处理哈希冲突?

答:Redis HyperLogLog使用Hash函数对元素进行哈希运算,得到一个哈希值。如果发生哈希冲突,HyperLogLog会选择一个最小的值作为索引位置。这样做可以保证估计值的误差率不会超过预设的误差率。

4.10. Redis HyperLogLog的优化策略有哪些?

答:Redis HyperLogLog的优化策略主要有两个:稀疏化和交集估计。稀疏化是指对于一些元素数量较少的HyperLogLog,可以使用较小的存储空间来存储,从而节省内存空间。交集估计是指对于多个HyperLogLog的交集,可以使用一些特殊的算法来估计交集的大小,从而减小误差率。
在这里插入图片描述大家好,我是冰点,今天的HyperLogLog 数据结构详解,全部内容就是这些。如果你有疑问或见解可以在评论区留言。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超图数据集概念学习1

以前写过一些数据源数据集有关的博文&#xff1b;从头学习一下&#xff1b; 数据集是同种类型数据的集合&#xff0c;比如&#xff1a;点数据集、线数据集。根据数据类型的不同&#xff0c;分为矢量数据集、格网数据集和影像数据集&#xff0c;以及为了处理特定问题而设计的如路…

​CentOS防火墙操作命令 ​

CentOS防火墙操作命令 1、查看防火墙服务状态 systemctl status firewalld.service 或者查看防火墙的状态&#xff1a; 1 firewall-cmd --state 2、开启、重启防火墙 启动firewall&#xff1a; 1 systemctl start firewalld.service 设置开机自启或禁用&#xff1a; …

【Ceph】基于ceph-deploy部署Ceph集群详解

基于ceph-deploy部署Ceph集群详解 1. 存储基础1.1 单机存储设备1.1.1 单机存储的问题1.1.2 商业存储解决方案 1.2 分布式存储&#xff08;软件定义的存储SDS&#xff09;1.2.1 分布式存储的类型 2. Ceph简介2.1 Ceph优势2.2 Ceph架构2.2.1 高层应用接口 2.3 Ceph核心组件2.3.1 …

CTFShow-WEB入门篇文件上传详细Wp(151-170)

WEB入门篇--命令执行详细Wp 文件上传&#xff1a;Web151&#xff1a;Web152&#xff1a;Web153&#xff1a;Web154&#xff1a;Web155&#xff1a;Web156&#xff1a;Web157&#xff1a;Web158&#xff1a;Web159&#xff1a;Web160&#xff1a;Web161&#xff1a;Web162&#…

Java:基本数据类型 和 所占大小

目录 java基本程序结构命名注释数据类型 和 大小整数类型浮点char编码boolean 变量常量final 的作用 java基本程序结构 命名 小驼峰&#xff1a;第一个单词小写&#xff0c;后面的单词大写。 大驼峰&#xff1a;每个单词都大写。 变量&#xff0c;方法&#xff1a;小驼峰。 j…

046、TiDB特性_内存悲观锁(了解)

悲观锁 传统悲观锁有两个性能问题&#xff1a; 磁盘io 需要将lock 的信息持久化到 lock CF中&#xff0c;这个时候产生磁盘io网络io 因为每个Region都是多副本&#xff0c;需要将信息通过网络 发送到Follower的lock CF中。 内存悲观锁 为了解决上面两个问题。 就有个内存悲观…

RPC学习笔记

1、Remote Procedure Call RPC的主要目标是让构建分布式更容易&#xff0c;在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标&#xff0c;RPC框架需要提供一种透明的调用机制&#xff0c;让使用者不必显示的区别本地调用和远程调用。RPC不是一个协议或者方…

CodeArts Check系统规则集还不够?带你体验如何创建、启用自定义规则集

代码检查&#xff08;CodeArts Check&#xff09;是基于云端实现的代码检查服务。建立在多年自动化源代码静态检查技术积累与企业级应用经验的沉淀之上&#xff0c;为用户提供代码风格、通用质量与网络安全风险等丰富的检查能力&#xff0c;提供全面质量报告、便捷闭环处理问题…

BTY生态系统DNS关于DeSoc的构想

2022年5月&#xff0c;以太坊创始人Vitalik Buterin与经济学家Glen Weyl和Flashbots研究员Puja Ohlhaver联合发布了《Decentralized Society: Finding Web3’s Soul》。这篇论文的核心是围绕“Web3灵魂”创造出去中心化社会的可能性。 论文中阐述&#xff0c;当下Web3 更多是表…

Java语言基础

目录 一.代码注释 二.变量与常量 1.标识符 2.关键字 3.变量 4.常量 三.基本数据类型 1.整数类型 2.浮点类型 3.字符类型 1.char型 2.转义字符 4.布尔类型 一.代码注释 在代码中添加注释能提高代码的可读性。注释中包含了程序的信息&#xff0c;可以帮助程序员更…

前端学习——JS进阶 (Day3)

编程思想 面向过程编程 面向对象编程 (oop) 构造函数 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…

第一阶段-第十章 Python基础的综合案例(数据可视化-折线图可视化)

目录 一、本章的案例介绍  1.可视化案例&#xff08;本章&#xff09;的学习目标  2.需要实现的效果图  3.数据来源 二、json数据格式  1.学习目标  2.什么是json  3. json的作用  4.json的语法要求  5.Python数据和json数据的相互转化&#xff08;dumps转json…

卷积神经网络识别人脸项目—使用百度飞桨ai计算

卷积神经网络识别人脸项目的详细过程 整个项目需要的准备文件&#xff1a; 下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1WEndfi14EhVh-8Vvt62I_w 提取码&#xff1a;7777 链接&#xff1a;https://pan.baidu.com/s/10weqx3r_zbS5gNEq-xGrzg 提取码&#x…

❤️创意网页:打造简洁美观的网页轮播图(HTML简单实现轮播图)操作简单可以直接使用

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

MQTT协议在物联网环境中的应用及代码实现解析(一)

MQTT协议全称是Message Queuing Telemetry Transport&#xff0c;翻译过来就是消息队列遥测传输协议&#xff0c;它是物联网常用的应用层协议&#xff0c;运行在TCP/IP中的应用层中&#xff0c;依赖TCP协议&#xff0c;因此它具有非常高的可靠性&#xff0c;同时它是基于TCP协议…

macos使用搭建算法竞赛c/c++的g++/gcc编译环境(homebrew,含万能头,改环境变量,vscode/clion可用)

文章目录 1、homebrew安装2、安装g3、改环境变量 1、homebrew安装 我没改镜像&#xff0c;直接网上脚本一键安装的&#xff0c;具体命令忘了&#xff0c;可能是这个 反正装这个的方法很多&#xff0c;网上一搜都有。 成功装上homebrew就行。 /bin/bash -c "$(curl -fsSL…

一款功能强大的子域收集工具OneForAll

简介 借助官方的宣传简介阐述一下&#xff1a; 在渗透测试中信息收集的重要性不言而喻&#xff0c;子域收集是信息收集中必不可少且非常重要的一环&#xff0c;目前网上也开源了许多子域收集的工具&#xff0c;但是总是存在以下部分问题&#xff1a; 不够强大&#xff0c;子域…

基于Cyclone V SoC利用HLS实现卷积手写体数字识别设计

基于Cyclone V SoC利用HLS实现卷积手写体数字识别设计 本文是基于英特尔 Cyclone V SoC 开发板&#xff0c;利用 HLS 技术实现三层卷积两层池化两层全连接推理运算的手写体数字识别设计 硬件环境&#xff1a; Cyclone V SoC开发板 SD卡 电脑 软件环境&#xff1a; Windows 11 Q…

unity3d:YooAsset shader变体收集代码解析

开始收集 YooAsset.Editor.ShaderVariantCollector.Run 创建临时场景 // 创建临时测试场景CreateTempScene();_steps ESteps.Prepare;EditorApplication.update EditorUpdate;准备阶段 反射调用ShaderUtil.ClearCurrentShaderVariantCollection清空当前项目搜集到的变体&…

第52步 深度学习图像识别:Transformer in Transformer建模(Pytorch)

基于WIN10的64位系统演示 一、写在前面 &#xff08;1&#xff09;Transformer in Transformer Transformer in Transformer&#xff08;TNT&#xff09;模型是一种新的图像分类模型&#xff0c;由研究者在2021年提出。这种模型的特点是在传统的Vision Transformer模型的基础…