三分钟了解Redis HyperLogLog 数据结构

这篇具有很好参考价值的文章主要介绍了三分钟了解Redis HyperLogLog 数据结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存

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。

三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存
(备注:有特殊公式符号,无法显示,所以截图贴在该位置)

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

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

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

三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存

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

三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存

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

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

三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存

此时为了性能考虑,是不会去统计当前的基数的,而是将 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的交集,可以使用一些特殊的算法来估计交集的大小,从而减小误差率。
三分钟了解Redis HyperLogLog 数据结构,Redis从入门到精通2023版,redis,数据结构,java,面试,后端,缓存大家好,我是冰点,今天的HyperLogLog 数据结构详解,全部内容就是这些。如果你有疑问或见解可以在评论区留言。文章来源地址https://www.toymoban.com/news/detail-572280.html

到了这里,关于三分钟了解Redis HyperLogLog 数据结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis从入门到精通【高阶篇】之底层数据结构跳表(SkipList)

    上个篇章回顾,我们上个章节我们学习了《Redis从入门到精通【高阶篇】之底层数据结构整数集(IntSet)详解》,我们从源码层了解整数集由一个头部和多个数据块组成。头部中存储了整数集的元素个数、编码方式和数据块的起始地址等信息。数据块中存储了实际的整型数据,当

    2024年02月09日
    浏览(49)
  • Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解

    上个篇章回顾,我们上个章节,讲了Redis中的快表(QuickList),它是一种特殊的数据结构,用于存储一系列的连续节点,每个节点可以是一个整数或一个字节数组。快表是Redis中的底层数据结构之一,常用于存储有序集合(Sorted Set)等数据类型的底层实现。 那么本章讲解Red

    2024年02月09日
    浏览(50)
  • Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解

    前面的Redis从入门到精通的基础篇和进阶篇都是在使用层面和概念层面,本章节,我们了解一下redis的底层数据结构,上几个章节,我们讲了SDS,字典 。本章节我们聊一下ZipList。 压缩列表(ZipList)就是redis为了节约内存而设计开发的数据结构,并且作为列表键和哈希键的底层

    2024年02月08日
    浏览(91)
  • Redis从入门到精通【高阶篇】之底层数据结构整数集(IntSet)详解

    上个篇章回顾,我们上个章节我们学习了《Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解》,我们从源码层了解字典是一种以键值对(key-value)形式存储数据的数据结构。在 Redis 中,字典使用哈希表来实现。哈希表是一种以常数时间复杂度 O(1) 进行插入、删

    2024年02月09日
    浏览(42)
  • 【数据结构】五分钟自测主干知识(四)

    线性数据结构中有两个典型代表——栈和队列。它们的逻辑结构和线性表一致,不同之处在于其操作的特殊性:栈的插入和删除操作只能在线性表的一端进行,并且元素遵循“后进先出”的原则 今天我们先来讲述这个经典概念:“栈” 3.1栈的基本概念 栈 (Stack)是一种线性

    2024年03月19日
    浏览(36)
  • 5分钟学会数据结构中的线性链表

    除了一些算法之外,我们还要掌握一些常见的数据结构,比如 数组、链表、栈、队列、树等结构。 在之前的文章中,已经带着大家学习了Java里的一维数组和多维数组,所以对此我就不再细述了。 接下来我会给大家讲解一下线性结构中的链表,希望你能喜欢哦。 全文大约【

    2024年02月08日
    浏览(52)
  • 【数据结构】--- 几分钟走进栈和队列(详解-上)

    👧 个人主页 :@小沈熬夜秃头中୧⍤⃝❅ 😚 小编介绍 :欢迎来到我的乱七八糟小星球🌝 📋 专栏 :数据结构 🔑 本章内容 :[数据结构]—栈和队列 送给各位 💌:一事无成也代表万事皆有可能 欢迎 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,

    2024年02月06日
    浏览(34)
  • 【数据结构】初步了解排序

      Yan-英杰的主页 悟已往之不谏 知来者之可追    C++程序员,2024届电子信息研究生 目录 1.排序的概念及其运用         1.1排序的概念           2.常见排序算法的实现         2.1插入排序         2.2希尔排序                问题:gap是多少合适?        

    2024年02月11日
    浏览(40)
  • 【数据结构】---几分钟简单几步学会手撕链式二叉树(下)

    👧个人主页:@小沈熬夜秃头中୧⍤⃝❅ 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:数据结构 🔑本章内容:手撕链式二叉树 送给各位💌:成为更好的自己才是应该做的事 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,下面案例可

    2024年02月08日
    浏览(41)
  • 【数据结构】---几分钟简单几步学会手撕链式二叉树(上)

    👧个人主页:@小沈熬夜秃头中୧⍤⃝❅ 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:数据结构 🔑本章内容:手撕链式二叉树 送给各位💌:我从没觉得孤独 说的浪漫点 我完全自由 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,下

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包