七、Redis三种高级数据结构-HyperLogLog

Redis HyperLogLog是用来做基数统计的算法,HyperLogLog在优点是,在输入的元素的数量或者体积非常大时,计算基数占用的空间总是固定的、并且非常小。在Redis里每个HyperLogLog键只需花费12KB内存,就可以计算接近 264 个元素的基数。因为HyperLogLog只是计算输入元素的基数,而不会储存元素的本身,因此HyperLogLog不会返回输入的元素。

1、什么是基数

比如数据集{1,3,5,7,9,3,5,7},那么这个数据集的基数集为{1,3,5,7,9},基数为5(不重复的元素)。基数估计就是在误差可接受的范围内,快速计算基数。

2、常用命令

  • pfadd key element[element…]:将数据添加到HyperLogLog数据结构中。
  • pfcount key [key…]:返回给定HyperLogLog的基数估计值。
  • pfmerge destKey sourceKey[sourceKey]:将多个HyperLogLog合并为一个HyperLogLog

3、HyperLogLog特点

1、占用内存小,12KB的内存大小,可以统计将近264 个元素。
2、计数存在一定的误差,但整体误差率较低。标准误差为0.81%。

*在Java中,我们知道long类型占用8字节,1byte=8位,即long类型能表示的最大数值为263 -1。对应上面的 264个数。假设现在有264个数。那么按照long,以及1KB=1024字节。那么264个数占用的内存为(264 8)/1024。其占用的内存远远高于12KB。

4、HyperLogLog原理

4.1、伯努利实验

在了解为什么HyperLogLog能在占用内存那么小的情况下,来统计那么大的数据。需要先了解下伯努利实验。

伯努利试验是数学中概率论的一部分内容。它的典故来源于抛硬币。

硬币只有正反两面(正好对应计算机中的0和1),最终出现正反面的概率都是50%。假设,我们一直抛硬币,只要出现一次正面,就记为一次完整实验。中间可能一次就出现正面,也可能10次才出现正面。不论抛了多少次,只要出现一次正面,就记为一次完整的实验。这个实验就是伯努利实验。
那么对于n次伯努利实验。意味着出现了**n**次正面。每一次的结果都有可能不同。假设第一次伯努利实验抛掷次数为**k1**,以此类推,第**n**此为**kn**
其中,在n次实验中,必然会存在一次是抛掷次数最大的。假设有一次伯努利实验抛掷了12次才出现正面,是最多的一次,我们将这个数记为**k_max**
在伯努利实验中,很容易得出以下结论:
1、n次伯努利实验中的抛掷次数都不大于k_max。
2、n次伯努利实验过程中最少有一次抛掷次数等于k_max。

其中n和k_max有一个估算关联关系**n=2^k_max**(我也不知道怎么推导的)。

假如有一轮伯努利实验的例子如下:

**第一次试验: 抛了3次才出现正面,此时 k=3,n=1 **
**第二次试验: 抛了2次才出现正面,此时 k=2,n=2 **
**第三次试验: 抛了6次才出现正面,此时 k=6,n=3 **
第n 次试验:抛了12次才出现正面,此时我们估算, n = 2^12

假设在上面的例子中,我们总共实验了3组,那么最大实验次数k_max就是6,那么由公式**n=2^k_max**可得n=2^6!=3。由此可知,在实验次数很少时,这种估算结果误差很大。
image.png

4.2、估算的优化

在上面的3组例子中,我们称为一轮实验。如果只进行一轮的话,当n足够大时,误差也会变小,但不是足够小。
因此是否可以进行多轮实验,然后取每轮实验的**k_max**平均值。例如进行100轮实验,然后再取平均数k_max/100。最终在估算出n。下面是**LogLog**的估算公式:

其中,DVLL 对应的就是n;m对应实验的轮次;头上有一横的R就是平均数(k_max1+k_max2+…+k_maxm)/m;constant是修正因子,可以通过修改这个数值还改变误差率。

通过这种增加实验轮次,然后取平均数是LogLog的做法。而HyperLogLog采用的不是平均数而是调和平均数。调和平均数和算术平均数的最大的区别在于调和平均数不容易受大的值影响。

求平均工资:
A的是1000/月,B的30000/月。采用平均数的方式就是: (1000 + 30000) / 2 = 15500
采用调和平均数的方式就是: 2/(1/1000 + 1/30000) ≈ 1935.484

**调和平均数公式为,**∑ 是累加符号:

HypeLogLog结合调和平均数的计算公式为:

4.3、HyperLogLog的做法

4.3.1、bit串

在Redis的HyperLogLog中,其首先将要保存的元素通过hash函数计算得到其64位的hash值。并将这个hash值转换成bit串。例如hash值是5,那么bit串就是“101”。
那么为什么要转换成bit串呢?是为了和伯努利实验的正反面对应上。bit串中的0和1就对应了伯努利实验的正面和反面。假如一个数据的hash值的bit串是“100010000”,那么从低往高,从右往左数,第一个1的位置就是出现正面的次数。
那么基于上面的估算结论:我们就可以根据最大的抛掷次数来估算出大概进行了多少次实现。同样的,也就可以根据存入的数据,转化后出现1的位置k_max来估算出,大致存了多少数据。

4.3.2、分桶

HyperLogLog中的分桶其实就是应伯努利实现估算优化中的多轮。每一个桶对应一轮的伯努利实验。转换成计算机存储就是:存储的是一个单位是bit,长度为L的大数组S,将S分为m组,其中m就是多轮实验。每组占用的bit个数是平均记为P,那么存在以下关系:
1、L=S.length
2、L=m*P
3、以K为单位,数组S占用大小为L/8/1024

在Redis中,HyperLogLog中设置m为16834(16384个桶),P为6(每个桶占6位,只占用6位原因:bit串是64位的其中低14位用来计算桶的位置,也就是说还有50位用来得到第一个1出现的问题,如果1在最左边,那么1的位置最大也就是50,2^6 =64,是第一个大于50的数,因此6位就可以完全存下1的位置),那么L=168346(bit)。占用内存为168346/8/1024=12K。

** 第0组 第1组 … 第16833组 **
[000 000] [000 000] [000 000] [000 000] … [000 000]

4.3.3、做法

在Redis中,HyperLogLog首先,将保存的元素转换成对应的hash值bit串(64位)。然后根据bit串来计算应该落在桶的位置。按照从右往左的顺序,取14位(因为Redis只是将桶分为16384个=2^14 ,14位正好可以将桶完全使用上)。根据低14位计算到桶的位置之后,然后再根据剩下的50位,从右往左,找到第一个1的位置。如果1出现的位置index>oldIndex,那么index会替换掉oldIndex。否则是跳过。
image.png

参考文章
HyperLogLog在线观察** **

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

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

相关文章

#04 构建您的第一个神经网络:PyTorch入门指南

文章目录 前言理论基础神经网络层的组成前向传播与反向传播 神经网络设计步骤1:准备数据集步骤2:构建模型步骤3:定义损失函数和优化器步骤4:训练模型步骤5:评估模型结论 前言 在过去的几天里,我们深入了解了…

头歌实践教学平台:CG1-v2.0-直线绘制

第1关&#xff1a;直线光栅化-DDA画线算法 一.任务描述 1.本关任务 (1)根据直线DDA算法补全line函数&#xff0c;其中直线斜率0<k<1&#xff1b; (2)当直线方程恰好经过P(x,y)和T(x,y1)的中点M时&#xff0c;统一选取直线上方的T点为显示的像素点。 2.输入 (1)直线两…

使用com.google.common.collect依赖包中的Lists.transform()方法转换集合对象之后,修改集合中的对象属性,发现不生效

目录 1.1、错误描述 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;模拟代码 &#xff08;3&#xff09;运行结果 1.2、解决方案 1.1、错误描述 最近在开发过程中&#xff0c;使用到了com.google.common.collect依赖包&#xff0c;通过这个依赖包中提供的…

Vue踩坑,less与less-loader安装,版本不一致

无脑通过npm i less -D安装less之后&#xff0c;继续无脑通过npm i less-loader -D安装less-loader出现如下错误&#xff1a; 解决方法&#xff1a; 1) npm uninstall less与 npm uninstall less-loader 2) 直接对其版本&#xff1a; npm i less3.0.4 -D npm i less-loader…

es关闭开启除了系统索引以外的所有索引

1、es 开启 “删除或关闭时索引名称支持通配符” 功能 2、kibanan平台执行 POST *,-.*/_close 关闭索引POST *,-.*/_open 打开索引3、其他命令 DELETE index_* // 按通配符删除以index_开头的索引 DELETE _all // 删除全部索引 DELETE *,-.* 删除全…

鸿蒙OpenHarmony开发板解析:【系统能力配置规则】

如何按需配置部件的系统能力 SysCap&#xff08;SystemCapability&#xff0c;系统能力&#xff09;是部件向开发者提供的接口的集合。 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 部件配置系统…

Java入门——类和对象(上)

经读者反映与笔者考虑&#xff0c;近期以及往后内容更新将主要以java为主&#xff0c;望读者周知、见谅。 类与对象是什么&#xff1f; C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 JAVA是基于面向对…

DDOS攻击实战演示,一次DDOS的成本有多低?

DDoS攻击成本概览 分布式拒绝服务&#xff08;DDoS&#xff09;攻击以其低廉的启动成本和惊人的破坏力著称。攻击者通过黑市轻松获取服务&#xff0c;成本从几十元人民币的小额支出到针对大型目标的数千乃至数万元不等。为了具体理解这一成本结构&#xff0c;我们将通过一个简…

每日两题 / 226. 翻转二叉树 98. 验证二叉搜索树(LeetCode热题100)

226. 翻转二叉树 - 力扣&#xff08;LeetCode&#xff09; 以后续遍历的方式交换当前节点的左右指针 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), ri…

机器学习-12-sklearn案例03-flask对外提供服务

整体思路 训练一个模型&#xff0c;把模型保存 写一个基于flask的web服务&#xff0c;在web运行时加载模型&#xff0c;并在对应的接口调用模型进行预测并返回 使用curl进行测试&#xff0c;测试通过 再创建一个html页面&#xff0c;接受参数输入&#xff0c;并返回。 目录结…

CSS悬浮动画

<button class"btn">悬浮动画</button>.btn {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);padding: 10px 20px;width: 200px;height: 50px;background-color: transparent;border-radius: 5px;border: 2px solid powderblu…

R2S+ZeroTier+Trilium

软路由使用ZeroTier搭建远程笔记 软路由使用ZeroTier搭建远程笔记 环境部署 安装ZeroTier安装trilium 环境 软路由硬件&#xff1a;友善 Nanopo R2S软路由系统&#xff1a;OpenWrt&#xff0c;使用第三方固件nanopi-openwrt。内网穿透&#xff1a;ZeroTier。远程笔记&…

银河麒麟操作系统 v10 离线安装 Docker v20.10.9

1查看系统版本 [rootweb-0001 ~]# cat /etc/os-release NAME"Kylin Linux Advanced Server" VERSION"V10 (Tercel)" ID"kylin" VERSION_ID"V10" PRETTY_NAME"Kylin Linux Advanced Server V10 (Tercel)" ANSI_COLOR"…

pyqt动画效果放大与缩小

pyqt动画效果放大与缩小 QPropertyAnimation介绍放大与缩小效果代码 QPropertyAnimation介绍 QPropertyAnimation 是 PyQt中的一个类&#xff0c;它用于对 Qt 对象的属性进行动画处理。通过使用 QPropertyAnimation&#xff0c;你可以平滑地改变一个对象的属性值&#xff0c;例…

服务器2080ti驱动的卸载与安装

服务器2080ti驱动的卸载与安装 前言1、下载驱动2、驱动卸载与安装2.1 卸载原来驱动2.2 安装新驱动 3、查看安装情况 前言 安装transformers库&#xff0c;运行bert模型时出错&#xff0c;显示torch版本太低&#xff0c;要2.0以上的&#xff0c;所以更新显卡驱动&#xff0c;重…

基于vgg16和efficientnet卷积神经网络的天气识别系统(pytorch框架)全网首发【图像识别-天气分类】

一个能够从给定的环境图像中自动识别并分类天气&#xff08;如晴天、多云、雨天、雪天闪电等&#xff09;的系统。 技术栈&#xff1a; 深度学习框架&#xff1a;PyTorch基础模型&#xff1a;VGG16与EfficientNet任务类型&#xff1a;计算机视觉中的图像分类 模型选择 VGG16 …

1.基于python的单细胞数据预处理-归一化

目录 归一化的引入移位对数皮尔森近似残差两个归一化方法的总结 参考&#xff1a; [1] https://github.com/Starlitnightly/single_cell_tutorial [2] https://github.com/theislab/single-cell-best-practices 归一化的引入 在质量控制中&#xff0c;已经从数据集删除了低质…

【网络安全】一次sql注入问题的处理

目录 问题 10.60.100.194&#xff0c;修改之前 修改方案 问题解决 测试过程 问题思考与总结 问题 一次sql注入问题的筛查报告&#xff0c;主要是sql注入的问题资源-CSDN文库 doc-new\20-设计文档\34-Mesh设备管理\100-网络安全 10.60.100.194&#xff0c;修改之前 修改…

Multitouch for Mac:手势自定义,提升工作效率

Multitouch for Mac作为一款触控板手势增强软件&#xff0c;其核心功能在于手势的自定义和与Mac系统的深度整合。通过Multitouch&#xff0c;用户可以轻松设置各种手势&#xff0c;如三指轻点、四指左右滑动等&#xff0c;来执行常见的任务&#xff0c;如打开应用、切换窗口、滚…

ansible部署lamp架构

搭建参考&#xff1a;ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…