Redis系列10:HyperLogLog实现海量数据基数统计
Redis系列1:深刻理解高性能Redis的本质
Redis系列2:数据持久化提高可用性
Redis系列3:高可用之主从架构
Redis系列4:高可用之Sentinel(哨兵模式)
Redis系列5:深入分析Cluster 集群模式
追求性能极致:Redis6.0的多线程模型
追求性能极致:客户端缓存带来的革命
Redis系列8:Bitmap实现亿万级数据计算
Redis系列9:Geo 类型赋能亿级地图位置计算
1 前言
我们来回顾下在这个系列的第一篇 深刻理解高性能Redis的本质 中介绍过Redis的几种基本数据结构,
它服务于各种不同的业务场景而设计的,比如:
- 动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)
- 双端列表(REDIS_ENCODING_LINKEDLIST)
- 压缩列表(REDIS_ENCODING_ZIPLIST)
- 跳跃表(REDIS_ENCODING_SKIPLIST)
- 哈希表(REDIS_HASH)
- 整数集合(REDIS_ENCODING_INTSET)
除了这些常见数据类型,还有一些不常用的数据类型,如 BitMap、Geo、HyperLogLog 等等,他们在各自的方向为不同的类型的数据统计给出解决方案。
- 位图(BitMap)计算:可以应用于任何大数据场景下的二值计算,比如 是否登录、是否在线、是否签到、用户性别状态、IP黑名单、是否VIP用户统计 等等场景。
- Geo类型:记录地理空间信息,如 地理坐标存储、位置计算、距离计算等能力,普遍运用在地图业务中的各种场景。
这一篇我们来介绍下HyperLogLog,HyperLogLog 主要用于Redis基数的统计,比如IP统计,用户访问量,页面访问量。
2 关于HyperLogLog
HyperLogLog 主要用于Redis 的基数统计,它的数据结构专门设计用来做数据合并和计算,并能节省大量的空间。
基数计数( cardinality counting) 通常用来统计一个集合中不重复的元素个数 , 例如统计某个网站的UV、PV或者网站搜索的的关键词数量。
在各种应用领域基数统计被广泛应用,如数据分析、网络监控指标、存储性能优化等。
简单来说,基数计数就是记录集合中所有不重复的元素Su ,当新增元素Xa时,判断Su中是否包含,不包含则将其加入Su,包含则不加入,计数值就是Su 的元素数量总和。
当然这种做法也存在两个问题:
- 当统计的数据量变大时,相应的存储内存也会线性增长
- 当集合Su 变大,判断其是否包含新加入元素的成本变大
2.1 实际应用场景
很多计数类场景,比如 每日注册 IP 数、每日访问 IP 数、页面实时访问数 PV、访问用户数 UV等。
因为主要的目标高效、巨量地进行计数,所以对存储的数据的内容并不关系。也就是说它只能用于统计数量,没办法知道具体的统计对象的内容。
- 统计单日一个页面的访问量(PV),单次访问就算一次。
- 统计单日一个页面的用户访问量(UV),即按照用户为维度计算,单个用户一天内多次访问也只算一次。
- 多个key的合并统计,某个门户网站的所有模块的PV聚合统计就是整个网站的总PV。
2.2 高效和海量特性
如果我们使用普通集合,也能够实现对巨量数据的存储和统计么,但是存储量会大很多,性能也比较差。
以百度搜索为例,如果要做百度指数的计算,针对来访IP进行统计。那么如果每天 有 1000 万 IP,一个 IP 占位 15 字节,那么 1000 万个 IP 就是 143M。
10,000,000 * 15 /(1024 * 1024) = 143.05 M
如果使用 HyperLogLog ,那么在 Redis 中每个键占用的内容都是 12K,理论上能够存储 264 个值,即18446744073709551616,这个数是巨量,Java中long类型也只能计算到 262 。
无论存储何值,它一个基于基数估算的算法HyperLogLog Counting(简称HLLC),使用少量固定的内存去存储并识别集合中的唯一元素。
HLLC采用了分桶平均的思想来消减误差,在Redis中, 有16384个桶 。而HyperLogLog的标准偏差公式是1.04 / sqrt(m),m 为桶的个数。所以
1.04 / sqrt(16384) = 1.04 / 128 = 0.008125
所以这个计数的估算,是一个带有 0.81% 标准偏差的近似值。
HyperLogLog 算法原理参考这两篇,写的很清晰:
https://zhuanlan.zhihu.com/p/77289303
http://www.javashuo.com/article/p-mmwxrmjm-ga.html
3 HyperLogLog所支持的能力
HyperLogLog数据结构的命令有三个:PFADD、PFCOUNT、PFMERGE
3.1 PFADD 添加计数
Redis Pfadd 命令将所有元素添加到 HyperLogLog 数据结构中。
语法如下:
redis > PFADD key element [element ...]
下面举例了网站统计模块添加IP的两种情况
/* 对访问百度网站(key=baidu:ip_address)的IP进行添加 */
redis> PFADD baidu:ip_address "192.168.0.1" "192.168.0.2" "192.168.0.3"
(integer) 1
/* 如果IP已经存在,则进行忽略,不对估计数量进行更新 */
redis> PFADD baidu:ip_address "192.168.0.3"
(integer) 0 # IP已经存在
3.2 PFCOUNT 统计数量
Redis Pfcount 命令返回给定 HyperLogLog 的基数的估算值。
语法如下:
redis > PFCOUNT key [key ...]
下面估算了访问IP的基数的值,返回 1034546 。
redis> PFCOUNT baidu:ip_address
(integer) 1034546
3.3 PFMERGE 合并统计
Redis PFMERGE 命令将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是对给定 HyperLogLog 进行并集计算得出的。
所以有重复的会被统计成一条数据。
合并得出的 HyperLogLog 会被储存在 destkey 键里面, 如果该键并不存在,那么命令在执行之前, 会先为该键创建一个空的 HyperLogLog 。
语法如下:
redis > PFMERGE destkey sourcekey [sourcekey ...]
下面演示了合并和统计的过程:
/* 统计百度 baidu:ip_address 访问IP */
redis> PFADD baidu:ip_address "192.168.0.1" "192.168.0.2" "192.168.0.3"
(integer) 1
/* 统计淘宝 taobao:ip_address 访问IP */
redis> PFADD taobao:ip_address "192.168.0.3" "192.168.0.4" "192.168.0.5"
(integer) 1
/* 合并且去重之后放在 total:ip_address */
redis> PFMERGE total:ip_address baidu:ip_address taobao:ip_address
OK
/* 结果为5 */
redis> PFCOUNT total:ip_address
(integer) 5
4 总结
基数计数是用于统计一个集合中不重复的元素个数,好比平常需求场景有,统计页面的UV或者统计在线的用户数、注册IP数等。HyperLogLog 主要基于Redis能力下的基数统计。HyperLogLog的主要使用场景包括:
- 统计单日一个页面的访问量(PV),单次访问就算一次。
- 统计单日一个页面的用户访问量(UV),即按照用户为维度计算,单个用户一天内多次访问也只算一次。
- 多个key的合并统计,某个门户网站的所有模块的PV聚合统计就是整个网站的总PV。
Redis系列10:HyperLogLog实现海量数据基数统计的更多相关文章
- redis 系列10 字符串对象
一. 字符串对象编码 Redis中字符串可以存储3种类型,分别是字节串(byte string).整数.浮点数.在上章节中讲到字符串对象的编码可以是int, raw,embstr. 如果一个字符串对象 ...
- 【目录】redis 系列篇
随笔分类 - redis 系列篇 redis 系列27 Cluster高可用 (2) 摘要: 一. ASK错误 集群上篇最后讲到,对于重新分片由redis-trib负责执行,关于该工具以后再介绍.在进 ...
- Redis系列(三):Bitmaps和HyperLogLog
本篇介绍Bitmaps和HyperLogLog. 一.Bitmaps 计算机中最小的单位是bit(位),很多计算机语言也提供了位操作符,比如Java中就有&.|.>>.>&g ...
- redis常用数据类型 HyperLoglog
1.HyperLoglog简介 HyperLoglog是redis新支持的两种类型中的另外一种(上一种是位图类型Bitmaps).主要适用场景是海量数据的计算.特点是速度快.占用空间小. 同样是用于计 ...
- redis系列:redis介绍与安装
前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...
- Redis系列8:Bitmap实现亿万级数据计算
Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...
- Redis系列9:Geo 类型赋能亿级地图位置计算
Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...
- Redis系列(2)之数据类型
Redis系列(2)之数据类型 <Redis系列(1)之安装>中介绍了Redis支持以下几种数据类型,那么本节主要介绍学习下这几种数据类型的基本操作 字符串类型,string 散列类型,h ...
- Python操作redis系列之 列表(list) (四)
# -*- coding: utf- -*- import redis r =redis.Redis(host=,password="ZBHRwlb1608") 1. Lpush ...
随机推荐
- Crash的数字表格 (莫比乌斯反演)
Crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时被a和b ...
- 【三维地图】开发攻略 —— 详解“GeoJSON”技术和应用场景
GeoJSON ,一个用于存储地理信息的数据格式.GoeJSON对象可以表示几何.特征或特征集合,支持:点.线.面.多点.多线.多面和几何集合.在基于平面地图,三维地图中都需要用到的一种数据类型. 由 ...
- Linux的NFS的配置
快速代码 # nfs的Server配置文件和配置方法 echo '/newnfs 192.168.3.*rw,sync,no_root_squash)' >> /etc/exports # ...
- Swagger以及knife4j的基本使用
Swagger以及knife4j基本使用 目录 Swagger以及knife4j基本使用 Swagger 介绍: Restful 面向资源 SpringBoot使用swagger Knife4j -- ...
- echarts学习笔记(一)
echarts学习笔记(一) echarts开发步骤 创建一个新的html文件 在html文件head头部信息中导入echarts 声明一个容器(可以理解为画布),用于存放echarts 实例化ech ...
- KingbaseES R6 主备流复制集群创建级联复制案例
案例环境: 数据库: test=# select version(); version -------------------------------------------------------- ...
- K8S_删除Pod总结
K8S 不能直接删除Pod,直接删除Pod,会被Deployment重启 删除前,必须先删除对应的Deployment 例子: // 查出Pod [root@k8s-master ~]# kubect ...
- v-contextmenujs 右键菜单点击
忙碌了一晚上的"枫师傅"用上了新插件v-contextmenujs,这个插件就按照他的文档来就行 我的使用: <!-- 这里是demo.vue,之所以选择html是为了代码高 ...
- 使用 Loki 微服务模式部署生产集群
转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247500523&idx=1&sn=0994af2b50 ...
- kube-scheduler 调度调优
文章转载自:https://www.kuboard.cn/learning/k8s-advanced/schedule/tuning.html kube-scheduler 是 Kubernetes ...