本文是大数据系列第 41 篇,介绍 Redis 三种高级数据类型:Bitmap 位图、Geo 地理位置与 Stream 消息流。

完整图文版(含截图):CSDN 原文 | 掘金

Bitmap 位图

核心概念:位图是一种用二进制位表示数据的数据结构,每个 bit 只能为 0 或 1,用来表示某个元素的值或状态。

空间效率

Bitmap 的最大优势在于极高的空间利用率。存储 10,000 个用户的签到状态:

  • 传统方式(布尔值存 Set):约 40KB
  • Bitmap 方式:约 1.25KB(节省超过 97%)

常用场景

  1. 用户签到打卡
  2. 在线用户统计
  3. 布隆过滤器
  4. 权限管理
  5. 去重计数

核心命令

命令说明
SETBIT key offset value设置指定偏移量的 bit 值(0 或 1)
GETBIT key offset获取指定偏移量的 bit 值
BITCOUNT key [start end]统计值为 1 的 bit 数量
BITOP operation destkey key [key ...]对多个 Bitmap 执行位运算(AND/OR/XOR/NOT)

实战示例:用户签到

# 用户 1000 在 2024-01-01 签到
SETBIT user:sign:1000 20240101 1

# 查询用户 1000 在 2024-01-01 是否签到
GETBIT user:sign:1000 20240101

# 统计用户 1000 总签到天数
BITCOUNT user:sign:1000

Geo 地理位置类型

Redis 的 Geo 类型内部基于 Sorted Set 实现,结合了三项核心技术:Z-order 曲线、Base32 编码与 GeoHash 算法。

Z-Order 曲线

Z-order 曲线是一种空间填充曲线,能将多维数据映射到一维,同时保持空间局部性——地理位置相近的点,在一维编码中也靠近彼此。

编码过程(以坐标 (3, 5) 为例):

  1. 将 X=3、Y=5 分别转为二进制:011101
  2. 交叉合并各 bit(先 Y 后 X 交替):011011
  3. 转为十进制:27

Base32 编码

Base32 使用 32 个字符(0-9b-z 去掉易混淆字符)将二进制数据转为可打印 ASCII:

  1. 将二进制数据拆分为 5-bit 一组
  2. 每组(0–31)映射到 Base32 字母表
  3. 末尾不足 5-bit 时补 = 填充

GeoHash 算法

GeoHash 将地球上任意位置的经纬度编码为一个紧凑字符串。Redis 内部使用 52-bit 整数存储在 Sorted Set 的 score 中,通过 z-score 排序实现高效的附近查询。

核心命令

# 添加地理位置(经度 纬度 成员名)
GEOADD user:addr 111.11 44.44 ww 112.22 43.33 kk

# 获取 GeoHash 编码
GEOHASH user:addr ww

# 获取坐标
GEOPOS user:addr ww

# 计算两点距离(单位:km)
GEODIST user:addr ww kk km

# 查找附近成员(Redis 6.2+)
GEOSEARCH user:addr FROMMEMBER ww BYRADIUS 100 km ASC

Stream 消息流

Stream 是 Redis 5.0 引入的数据结构,提供持久化消息队列功能,弥补了 Pub/Sub 不能持久化的缺陷。

主要能力

  • 自动生成消息 ID(格式:毫秒时间戳-序号
  • 消息遍历与范围查询
  • 阻塞/非阻塞读取
  • 消费者组(Consumer Group)支持
  • Pending 消息确认机制
  • 队列监控与消息回溯

核心命令

# 写入消息(* 表示自动生成 ID)
XADD topic:001 * name wzk age 18

# 读取范围消息(- 表示最小 ID,+ 表示最大 ID)
XRANGE topic:001 - +

# 消费消息(从 ID=0 开始读 1 条)
XREAD COUNT 1 STREAMS topic:001 0

# 创建消费者组
XGROUP CREATE topic:001 group1 0

# 消费者组读取
XREADGROUP GROUP group1 consumer1 COUNT 1 STREAMS topic:001 >

# 确认消息
XACK topic:001 group1 <message-id>

与 Pub/Sub 的区别

特性StreamPub/Sub
消息持久化支持不支持
消费确认支持(ACK)不支持
消费者组支持不支持
历史消息可回溯无法获取

Stream 适合对消息可靠性有要求的场景,而 Pub/Sub 更适合实时广播、对丢消息不敏感的场景。