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 的元素数量总和。

当然这种做法也存在两个问题:

  1. 当统计的数据量变大时,相应的存储内存也会线性增长
  2. 当集合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实现海量数据基数统计的更多相关文章

  1. redis 系列10 字符串对象

    一. 字符串对象编码 Redis中字符串可以存储3种类型,分别是字节串(byte string).整数.浮点数.在上章节中讲到字符串对象的编码可以是int, raw,embstr. 如果一个字符串对象 ...

  2. 【目录】redis 系列篇

    随笔分类 - redis 系列篇 redis 系列27 Cluster高可用 (2) 摘要: 一. ASK错误 集群上篇最后讲到,对于重新分片由redis-trib负责执行,关于该工具以后再介绍.在进 ...

  3. Redis系列(三):Bitmaps和HyperLogLog

    本篇介绍Bitmaps和HyperLogLog. 一.Bitmaps 计算机中最小的单位是bit(位),很多计算机语言也提供了位操作符,比如Java中就有&.|.>>.>&g ...

  4. redis常用数据类型 HyperLoglog

    1.HyperLoglog简介 HyperLoglog是redis新支持的两种类型中的另外一种(上一种是位图类型Bitmaps).主要适用场景是海量数据的计算.特点是速度快.占用空间小. 同样是用于计 ...

  5. redis系列:redis介绍与安装

    前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...

  6. Redis系列8:Bitmap实现亿万级数据计算

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  7. Redis系列9:Geo 类型赋能亿级地图位置计算

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  8. Redis系列(2)之数据类型

    Redis系列(2)之数据类型 <Redis系列(1)之安装>中介绍了Redis支持以下几种数据类型,那么本节主要介绍学习下这几种数据类型的基本操作 字符串类型,string 散列类型,h ...

  9. Python操作redis系列之 列表(list) (四)

    # -*- coding: utf- -*- import redis r =redis.Redis(host=,password="ZBHRwlb1608") 1. Lpush ...

随机推荐

  1. HMS Core基于地理位置请求广告,流量变现快人一步

    对于想买车的用户来说,如果走在路上刷社交软件时突然在App里收到一条广告:"前方500米商圈里的某品牌汽车正在做优惠,力度大福利多."不管买不买,八成都会去看看,原因有三:距离近. ...

  2. Homework6

    1.问:阅读和了解什么是形式化方法? 答:形式化方法在逻辑科学中是指分析.研究思维形式结构的方法.是把各种具有不同内容的思维形式(主要是命题和推理)加以比较,找出各个部分相互联结的方式,抽取出共同的形 ...

  3. 一文搞懂mysql索引底层逻辑,干货满满!

    一.什么是索引 在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录.通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列即可 ...

  4. 若依代码生成的一个大坑 You have an error in your SQL syntax; check the manual that corresponds to your MySQL s

    报错如下所示:显示我的xml文件的SQL语句有错 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: You h ...

  5. The 19th Zhejiang Provincial Collegiate Programming Contest

    目录 A.JB Loves Math B.JB Loves Comma C. JB Wants to Earn Big Money G. Easy Glide I. Barbecue L. Candy ...

  6. 使用filebeat收集k8s上pod里的容器日志配置文件模板

    具体使用有待商榷 filebeat.inputs: - type: container paths: - /var/log/containers/*.log processors: - add_kub ...

  7. ingress-nginx 的使用 =》 部署在 Kubernetes 集群中的应用暴露给外部的用户使用

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247488189&idx=1&sn=8175f067 ...

  8. Elasticsearch:设置Elastic账户安全

  9. 查看docker程序使用的内存脚本

    #!/bin/bash # 找出所有运行的容器 idNames=`docker ps --format "{{.ID}}|{{.Names}},"` # 按,号分隔 OLD_IFS ...

  10. Linux 宝塔部署 ASP.NET Core 应用

    第一步,发步应用 我这是一个API 应用和 MVC 应用 设置,服务器上要运行的端口 API 端口5000 MVC 端口5001 打包文件夹,发步 1.桌面新建俩个文件夹 2.右键项目发步,选中iis ...