Skip to content

第六章 高级数据类型 v1.0 ​

一、基数统计(HyperLogLog) ​

HyperLogLog 是 Redis 2.8.9 版本引入的数据结构,用于基数统计(统计一个集合中不重复元素的个数)。

传统方案比如用 Set 存储,会随着数据量增大占用大量内存。HyperLogLog 只需要固定 12KB 内存就能统计接近 2^64 个不同元素的基数。

1.基本命令 ​

bash
# 添加元素(本质是记录,不存储元素本身)
PFADD key element [element ...]

# 返回基数估算值
PFCOUNT key [key ...]

# 合并多个 HyperLogLog 到一个 key
PFMERGE destkey sourcekey [sourcekey ...]

2.特点 ​

  • 统计结果有 0.81% 的标准误差
  • 不存储元素本身,只存储基数
  • 固定 12KB 内存,适合大数据量的去重统计

3.适用场景 ​

  • 统计网站 UV(独立访客数)
  • 统计每日活跃用户数

二、发布订阅(Pub/Sub) ​

Redis 的 Pub/Sub 是一种消息通信模式:发送者(Publisher)发送消息,订阅者(Subscriber)接收消息。

1.基本命令 ​

bash
# 订阅一个或多个频道
SUBSCRIBE channel [channel ...]

# 向频道发送消息
PUBLISH channel message

# 订阅符合模式的频道(如 news.* 匹配 news.sport、news.tech 等)
PSUBSCRIBE pattern [pattern ...]

# 退订频道
UNSUBSCRIBE [channel [channel ...]]

# 退订模式
PUNSUBSCRIBE [pattern [pattern ...]]

2.使用示例 ​

bash
# 终端1:订阅 news 频道
SUBSCRIBE news

# 终端2:向 news 频道发送消息
PUBLISH news "Hello Redis Pub/Sub"
# 返回值为订阅者数量

3.注意事项 ​

  • 消息不会持久化,没有订阅者的消息会丢失
  • 不支持消费者组和消息确认,生产环境建议使用 Stream
  • 客户端断开连接后,订阅自动取消

三、地理空间(Geo) ​

Redis 3.2 版本引入了 Geo 类型,用于存储地理位置信息,底层使用 Sorted Set 实现。

1.基本命令 ​

bash
# 添加地理位置(经度、纬度、名称)
GEOADD key longitude latitude member [longitude latitude member ...]

# 获取指定名称的经纬度
GEOPOS key member [member ...]

# 计算两个位置之间的距离
GEODIST key member1 member2 [m|km|ft|mi]

# 以给定经纬度为中心,查找指定半径内的成员
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [COUNT count]

# 以某个成员为中心,查找指定半径内的成员
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [COUNT count]

# 返回 geohash 字符串
GEOHASH key member [member ...]

# 删除地理位置
ZREM key member [member ...]

2.使用示例 ​

bash
# 添加几个城市的位置
GEOADD cities 116.40 39.90 "北京"
GEOADD cities 121.47 31.23 "上海"
GEOADD cities 113.26 23.13 "广州"

# 计算北京到上海的距离
GEODIST cities "北京" "上海" km

# 查找距离北京 1500km 内的城市
GEORADIUSBYMEMBER cities "北京" 1500 km WITHDIST

3.注意事项 ​

  • 经度范围:-180 ~ 180,纬度范围:-85.05112878 ~ 85.05112878
  • 底层是 Sorted Set,可以用 ZREM 删除成员
  • 直接两极附近的坐标可能会有精度问题

四、位图(BitMap) ​

BitMap 不是一种独立的数据类型,而是基于 String 类型的一组按位操作命令。适合用一个 bit 位来表示某个元素的状态值。

1.基本命令 ​

bash
# 设置指定偏移量的值(0 或 1)
SETBIT key offset value

# 获取指定偏移量的值
GETBIT key offset

# 统计值为 1 的 bit 数量
BITCOUNT key [start end]

# 对多个 key 做位运算(AND、OR、XOR、NOT)
BITOP AND|OR|XOR|NOT destkey key [key ...]

# 返回第一个值为 0 或 1 的 bit 位
BITPOS key 0|1 [start] [end]

2.使用示例 ​

bash
# 用 BitMap 记录用户签到(offset = 用户ID,第 7 天)
SETBIT sign:user1001:2024-01 6 1

# 查询用户第 7 天是否签到
GETBIT sign:user1001:2024-01 6

# 统计本月签到天数
BITCOUNT sign:user1001:2024-01

# 统计多个用户的签到情况
BITOP AND sign:common user1:user2:sign user2:user2:sign

3.适用场景 ​

  • 用户签到打卡
  • 统计活跃用户(每天一个 key,bit 位对应用户 ID)
  • 布尔值的高效存储(如权限开关)

五、流(Stream) ​

Stream 是 Redis 5.0 引入的消息队列数据类型,支持消费者组和消息确认,可以看作是 Pub/Sub 的增强版。

1.基本命令 ​

bash
# 添加消息(* 表示自动生成 ID)
XADD key ID field value [field value ...]

# 读取消息
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]

# 创建消费者组
XGROUP CREATE key groupname ID [MKSTREAM]

# 消费者组读取消息
XREADGROUP GROUP groupname consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]

# 确认消息已被处理
XACK key groupname ID [ID ...]

# 获取 Stream 信息
XINFO STREAM key

# 获取消费者组信息
XINFO GROUPS key

# 删除消息
XDEL key ID [ID ...]

# 裁剪 Stream 长度
XTRIM key MAXLEN [~] count

2.使用示例 ​

bash
# 添加消息
XADD mystream * name "John" action "login"

# 读取最新消息
XREAD COUNT 10 STREAMS mystream 0

# 创建消费者组(从最新消息开始消费)
XGROUP CREATE mystream mygroup $

# 消费者组读取消息
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >

# 确认消息处理完成
XACK mystream mygroup 1234567890-0

3.与 Pub/Sub 的对比 ​

对比项Pub/SubStream
消息持久化不支持支持
消费者组不支持支持
消息确认不支持支持(XACK)
历史消息回溯不支持支持
适用场景简单通知生产环境消息队列

六、位域(BitField) ​

BitField 命令允许在一个 String 类型的 key 中操作多个位域,支持自定义位宽的有符号/无符号整数的读写和自增操作。

1.基本命令 ​

bash
BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
  • type:u + 位数(无符号)或 i + 位数(有符号),如 u8 表示 8 位无符号整数,i16 表示 16 位有符号整数
  • offset:位偏移量
  • OVERFLOW:溢出策略
    • WRAP:回绕(默认)
    • SAT:饱和(到最大/最小值后停止)
    • FAIL:溢时不执行

2.使用示例 ​

bash
# 设置一个无符号 8 位整数(偏移量 0),值为 200
BITFIELD mykey SET u8 0 200

# 读取该值
BITFIELD mykey GET u8 0

# 自增 10
BITFIELD mykey INCRBY u8 0 10

# 使用 SAT 溢出策略,防止溢出回绕
BITFIELD mykey OVERFLOW SAT SET u8 0 250
BITFIELD mykey OVERFLOW SAT INCRBY u8 0 10
# 结果为 255(不会溢出到 4)

3.适用场景 ​

  • 紧凑存储多个小整数(如计数器、状态标志)
  • 节省内存的统计数据存储