Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解


前言

Redis是一个高性能的(key/value)分布式内存数据库,它支持多种数据类型,包括字符串、哈希、列表、集合、有序集合等。除了这些常见的数据类型,Redis还提供了一些特殊的数据类型,如Hyperloglog、GEO、Bitmap、Bitfield等,它们可以用来实现一些高效的功能,如基数统计、地理位置计算、位图操作等。本文将介绍这些特殊数据类型的概念、用法和应用场景。


Redis Hyperloglog、GEO、Bitmap、Bitfield类型详解

Hyperloglog

HyperLogLog 是一种概率数据结构,用于在恒定的内存大小下估计集合的基数(不同元素的个数)。它不是一个独立的数据类型,而是一种特殊的 string 类型,它可以使用极小的空间来统计一个集合中不同元素的数量,也就是基数。一个 hyperloglog 类型的键最多可以存储 12 KB 的数据

hyperloglog 类型的底层实现是 SDS(simple dynamic string),它和 string 类型相同,只是在操作时会使用一种概率算法来计算基数。hyperloglog 的误差率为 0.81%,也就是说如果真实基数为 1000,那么 hyperloglog 计算出来的基数可能在 981 到 1019 之间

应用场景

hyperloglog 类型的应用场景主要是利用空间换时间和精度,比如:

  • 统计网站的独立访客数(UV)
  • 统计在线游戏的活跃用户数(DAU)
  • 统计电商平台的商品浏览量
  • 统计社交网络的用户关注数
  • 统计日志分析中的不同事件数

假如需要统计某商品的用户关注数,可以通过以下方式:

> PFADD goodA "1"
1
> PFADD goodA "2"
1
> PFADD goodA "3"
1
> PFCOUNT goodA
3

GEO

geospatial 是一种用于存储和查询地理空间位置的数据类型,它基于 sorted set 数据结构实现,利用 geohash 算法将经纬度编码为二进制字符串,并作为 sorted set 的 score 值。Redis geospatial 提供了一系列的命令来添加、删除、搜索和计算地理空间位置,例如:

  • GEOADD key longitude latitude member [longitude latitude member …]:将一个或多个地理空间位置(经度、纬度、名称)添加到指定的 key 中

  • GEOPOS key member [member …]:返回一个或多个地理空间位置的经纬度

  • GEODIST key member1 member2 [unit]:返回两个地理空间位置之间的距离,可以指定单位(m, km, mi, ft)

  • GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]:返回指定圆心和半径内的地理空间位置,可以指定返回坐标、距离、哈希值、数量、排序方式等,也可以将结果存储到另一个 key 中

  • GEORADIUSBYMEMBER key member radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]: 返回以指定成员为圆心的指定半径内的地理空间位置,其他参数同 GEORADIUS

应用场景

geospatial 的应用是地理位置搜索、分析和展示,例如地图应用、导航应用、位置服务应用等。例如,可以使用 geospatial 来实现以下功能:

  • 统计某个区域内的商家或用户数量
  • 查询某个位置附近的餐馆或酒店
  • 计算两个位置之间的距离或行驶时间
  • 显示某个位置周围的景点或活动

Bitmap

bitmap 不是一个独立的数据类型,而是一种特殊的 string 类型,它可以将一个 string 类型的值看作是一个由二进制位组成的数组,并提供了一系列操作二进制位的命令。一个 bitmap 类型的键最多可以存储 2^32 - 1 个二进制位。

bitmap 类型的底层实现是 SDS(simple dynamic string),它和 string 类型相同,只是在操作时会将每个字节拆分成 8 个二进制位。

应用场景

bitmap 类型的应用场景主要是利用二进制位的特性,比如:

  • 统计用户活跃度,利用 setbit 和 bitcount 命令实现每天或每月用户登录次数的统计。
  • 实现布隆过滤器,利用 setbit 和 getbit 命令实现快速判断一个元素是否存在于一个集合中。
  • 实现位图索引,利用 bitop 和 bitpos 命令实现对多个条件进行位运算和定位

假如需要统计每个用户的当天登录次数统计。

首先,需要规定bitmap的格式,假设为{userid}:{年份}:{第几天} {秒数} {是否登录}

userid为100的用户,记录他在2024年第100天中第1秒,是否登录

SETBIT 1000:2024:100 1 1
0

userid为100的用户,记录他在2024年第100天中第10240 秒,是否登录

SETBIT 1000:2024:100 10240 1
0

userid为100的用户,记录他在2024年第100天中第86400 秒,是否登录

SETBIT 1000:2024:100 86400 1
0

统计userid为100的用户,在2024年第100天的登录次数

BITCOUNT 1000:2024:100
3

Bitfield

bitfield结构是基于字符串类型的一种扩展,可以让你对一个字符串中的任意位进行设置,增加和获取操作,就像一个位数组一样

可以操作任意位长度的整数,从无符号的1位整数有符号的63位整数。这些值是使用二进制编码的Redis字符串来存储的

bitfield结构支持原子的读,写和增加操作,使它们成为管理计数器和类似数值的好选择

应用场景

Bitfield的使用场景与bitmap 类似,主要是一些需要用不同位长度的整数来表示状态或属性的场合,例如:

  • 用一个32位的无符号整数来表示用户的金币数量,用一个32位的无符号整数来表示用户杀死的怪物数量,可以方便地对这些数值进行设置,增加和获取

  • 用一个16位的有符号整数来表示用户的等级,用一个16位的有符号整数来表示用户的经验值,可以方便地对这些数值进行设置,增加和获取

  • 用一个8位的无符号整数来表示用户的性别,用一个8位的无符号整数来表示用户的年龄,可以方便地对这些数值进行设置,增加和获取

bitfieldbitmap都是基于string类型的位操作,但是有一些区别:

  • bitmap只能操作1位的无符号整数,而bitfield可以操作任意位长度的有符号或无符号整数
  • bitmap只能设置或获取指定偏移量上的位,而bitfield可以对指定偏移量上的位进行增加或减少操作
  • bitmap可以对多个字符串进行位运算,而bitfield只能对单个字符串进行位操作
  • bitmap的偏移量是从0开始的,而bitfield的偏移量是从最高有效位开始的

例如,使用bitfield存储用户的个人信息,

  • 用一个8位的无符号整数来表示用户的性别,0表示男,1表示女
  • 用一个8位的无符号整数来表示用户的年龄,范围是0-255
  • 用一个16位的无符号整数来表示用户的身高,单位是厘米,范围是0-65535
  • 用一个16位的无符号整数来表示用户的体重,单位是克,范围是0-65535

假设有一个用户,性别是女,年龄是25,身高是165厘米,体重是50千克,可以用以下命令来存储和获取这些信息:

> BITFIELD user:1:info SET u8 #0 1 SET u8 #1 25 SET u16 #2 165 SET u16 #3 50000
0
0
0
0

然后,获取这个用户的信息,性别、年龄、身高、体重

> BITFIELD user:1:info GET u8 #0 GET u8 #1 GET u16 #2 GET u16 #3
1
25
165
50000

总结

本文介绍了Redis中的四种特殊数据类型:Hyperloglog、GEO、Bitmap、Bitfield

  • Hyperloglog是一种用来估计基数的算法,它可以用少量的内存来统计大量不重复元素的个数,适用于诸如UV统计、在线用户数等场景
  • GEO是一种用来存储地理坐标和计算距离的数据类型,它可以用来实现附近的人、地点等功能
  • Bitmap是一种用一个bit位来表示某个元素对应的值或状态的数据类型,它可以用来实现用户在线状态、签到功能等
  • Bitfield是一种用来对字符串中的位进行操作的命令,它可以用来实现计数器、布隆过滤器等功能

这些特殊数据类型都展示了Redis的强大和灵活性,为开发者提供了更多的可能性


系列文章目录

Redis内存优化——String类型介绍及底层原理详解
Redis内存优化——Hash类型介绍及底层原理详解
Redis内存优化——List类型介绍及底层原理详解
Redis内存优化——Set类型介绍及底层原理详解
Redis内存优化——ZSet类型介绍及底层原理详解
Redis内存优化——Stream类型介绍及底层原理详解
Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解
Redis的三种持久化策略及选取建议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr___Ray

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值