Redis是一个高性能的(key/value)分布式内存数据库,它支持多种数据类型,包括字符串、哈希、列表、集合、有序集合等。除了这些常见的数据类型,Redis还提供了一些特殊的数据类型,如Hyperloglog、GEO、Bitmap、Bitfield等,它们可以用来实现一些高效的功能,如基数统计、地理位置计算、位图操作等。本文将介绍这些特殊数据类型的概念、用法和应用场景。
HyperLogLog 是一种概率数据结构,用于在恒定的内存大小下估计集合的基数(不同元素的个数)。它不是一个独立的数据类型,而是一种特殊的 string 类型,它可以使用极小的空间来统计一个集合中不同元素的数量,也就是基数。一个 hyperloglog 类型的键最多可以存储 12 KB 的数据
hyperloglog 类型的底层实现是 SDS(simple dynamic string),它和 string 类型相同,只是在操作时会使用一种概率算法来计算基数。hyperloglog 的误差率为 0.81%,也就是说如果真实基数为 1000,那么 hyperloglog 计算出来的基数可能在 981 到 1019 之间
hyperloglog 类型的应用场景主要是利用空间换时间和精度,比如:
假如需要统计某商品的用户关注数,可以通过以下方式:
> PFADD goodA "1"
1
> PFADD goodA "2"
1
> PFADD goodA "3"
1
> PFCOUNT goodA
3
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
不是一个独立的数据类型,而是一种特殊的 string 类型,它可以将一个 string 类型的值看作是一个由二进制位组成的数组,并提供了一系列操作二进制位的命令。一个 bitmap 类型的键最多可以存储 2^32 - 1 个二进制位。
bitmap 类型的底层实现是 SDS(simple dynamic string),它和 string 类型相同,只是在操作时会将每个字节拆分成 8 个二进制位。
bitmap 类型的应用场景主要是利用二进制位的特性,比如:
假如需要统计每个用户的当天登录次数统计。
首先,需要规定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
结构是基于字符串类型的一种扩展,可以让你对一个字符串中的任意位进行设置,增加和获取操作,就像一个位数组一样
可以操作任意位长度的整数,从无符号的1位整数到有符号的63位整数。这些值是使用二进制编码的Redis
字符串来存储的
bitfield
结构支持原子的读,写和增加操作,使它们成为管理计数器和类似数值的好选择
Bitfield
的使用场景与bitmap
类似,主要是一些需要用不同位长度的整数来表示状态或属性的场合,例如:
用一个32位的无符号整数来表示用户的金币数量,用一个32位的无符号整数来表示用户杀死的怪物数量,可以方便地对这些数值进行设置,增加和获取
用一个16位的有符号整数来表示用户的等级,用一个16位的有符号整数来表示用户的经验值,可以方便地对这些数值进行设置,增加和获取
用一个8位的无符号整数来表示用户的性别,用一个8位的无符号整数来表示用户的年龄,可以方便地对这些数值进行设置,增加和获取
bitfield
和bitmap
都是基于string
类型的位操作,但是有一些区别:
bitmap
只能操作1位的无符号整数,而bitfield
可以操作任意位长度的有符号或无符号整数bitmap
只能设置或获取指定偏移量上的位,而bitfield
可以对指定偏移量上的位进行增加或减少操作bitmap
可以对多个字符串进行位运算,而bitfield
只能对单个字符串进行位操作bitmap
的偏移量是从0开始的,而bitfield
的偏移量是从最高有效位开始的例如,使用bitfield
存储用户的个人信息,
假设有一个用户,性别是女,年龄是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
这些特殊数据类型都展示了Redis的强大和灵活性,为开发者提供了更多的可能性
Redis内存优化——String类型介绍及底层原理详解
Redis内存优化——Hash类型介绍及底层原理详解
Redis内存优化——List类型介绍及底层原理详解
Redis内存优化——Set类型介绍及底层原理详解
Redis内存优化——ZSet类型介绍及底层原理详解
Redis内存优化——Stream类型介绍及底层原理详解
Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解
Redis的三种持久化策略及选取建议