Redis 扩展数据类型

文章目录

1.引言

Redis 的 String、List、Hash、Set、ZSet 五大基础类型已能覆盖大部分场景,但针对 "消息队列""地理位置""海量去重计数""空间优化存储" 等细分需求,Redis 提供了 5 种特殊数据类型 ------Stream(高级消息队列)、Geospatial(地理位置)、HyperLogLog(海量去重计数)、Bitmap(位图)、Bitfields(位域)。它们虽不像基础类型那样通用,却在各自领域做到了 "高效 + 省空间",是分布式系统中解决特定问题的 "利器"。本文将逐一拆解这 5 种类型的核心特性、命令与应用场景,帮你掌握 "什么时候用、怎么用"。

2.Stream

Stream 是 Redis 5.0 新增的类型,专为 "可靠消息队列" 设计,解决了 List 实现消息队列时 "无消息确认、无重复消费防护" 的痛点,是 Redis 作为消息中间件的核心支撑。

stream就是一个阻塞队列

是redis作为一个消息队列的重要支撑

属于是List blpop / brpop 的升级版本

核心特性

  • 消息持久化:Stream 中的消息会持久化到 RDB 和 AOF,Redis 重启后消息不丢失(List 的消息若未手动持久化,重启后可能丢失);
  • 消息确认机制:消费者读取消息后需手动 "确认"(ACK),未确认的消息会重新进入待消费队列,避免消息丢失;
  • 分组消费:支持多个 "消费组" 同时消费同一个 Stream,每个消费组内可有多个消费者,实现 "消息广播" 与 "负载均衡";
  • 阻塞读取:支持类似 Listbrpop的阻塞读取,且能指定 "从最新消息开始读" 或 "从历史消息开始读",灵活应对不同场景。

核心命令

xadd key * field value [field value ...](生产消息)

  • 功能:向 Stream 中添加一条消息;*表示让 Redis 自动生成唯一消息 ID(格式为 "时间戳 - 序列号",如1717200000-0);field-value为消息内容(支持多字段,类似 Hash)。

xreadgroup GROUP groupName consumerName COUNT count STREAMS key ID(消费消息)

  • 功能:消费组内的消费者读取 Stream 消息;GROUP指定消费组名,consumerName指定消费者名,COUNT指定单次读取条数,ID指定从哪个消息 ID 开始读(>表示读最新未消费消息,0表示读历史消息)。

xack key groupName msgId [msgId ...](确认消息)

  • 功能:消费者处理完消息后,向 Stream 确认 "消息已处理",避免消息重新进入待消费队列。

应用场景:可靠消息队列

  • 订单状态流转:订单创建后,通过 Stream 发送 "订单待支付" 消息,支付服务消费后处理支付,处理完确认消息;若支付失败,消息不确认,会被重新消费
  • 日志收集:多台服务器将日志通过xadd写入 Stream,日志服务通过消费组批量消费日志,实现 "分布式日志集中收集"。

3.Geospatial

Geospatial(简称 GEO)专为存储 "经纬度坐标" 设计,支持 "按距离查找附近地点""按区域查找地点" 等地理相关操作,适用于 "附近的人""周边商户推荐" 等场景。

核心特性:高效处理地理坐标

  • 坐标存储:底层通过 Zset 实现(将经纬度编码为score,地点名称为member),支持 O (logN) 的增删查效率;
  • 距离计算:支持计算两个地点之间的直线距离(单位可选米、千米、英里等);
  • 范围查询:支持两种范围查询 ------"按半径查找圆形区域内的地点""按矩形区域查找范围内的地点"。

核心命令

geoadd key longitude latitude member [longitude latitude member ...](添加地理坐标)

  • 功能:向 GEO 类型中添加一个或多个 "经纬度 - 地点" 对;longitude为经度(范围 - 180~180),latitude为纬度(范围 - 90~90),member为地点名称。

georadius key longitude latitude radius m|km|mi|ft [WITHCOORD] [WITHDIST] [COUNT count](按半径查附近地点)

  • 功能:以 "指定经纬度" 为中心,查找半径radius范围内的地点;m/km/mi/ft分别表示米、千米、英里、英尺;WITHCOORD返回地点经纬度,WITHDIST返回地点到中心的距离,COUNT限制返回条数

geodist key member1 member2 [m|km|mi|ft](计算两点距离)

  • 功能:计算两个地点之间的直线距离,返回距离值(单位默认米)。

应用场景:地理相关需求

  • 附近的人:存储用户实时经纬度,通过georadius查找 "以当前用户为中心,1 千米内的其他用户";
  • 周边商户推荐:存储商户坐标,用户打开 App 时,查找 "500 米内的餐厅 / 便利店",并按距离排序展示。

4. HyperLogLog

HyperLogLog(简称 HLL)是一种 "概率性数据结构",核心功能只有一个 ------估算集合中的元素个数(去重计数),特点是 "占用空间极小(固定约 12KB),支持海量数据(亿级)",但存在 0.81% 左右的计数误差。

核心特性:用空间换精度,适合海量去重

  • 固定空间:无论统计的元素个数是 100 还是 1 亿,HyperLogLog 始终占用约 12KB 内存(对比 Set:1 亿个 8 字节的用户 ID 需 800MB 内存);
  • 去重计数:自动实现元素去重,重复添加的元素不会重复计数(如同一用户多次访问,仅计 1 次 UV);
  • 概率估算:计数结果存在 0.81% 的误差,适合 "对精度要求不高,对内存敏感" 的场景(如 UV 统计、访问量统计);
  • 不存元素:仅记录元素的 "特征"(用于判断是否新元素),无法获取具体元素内容(区别于 Set)。

核心命令

pfadd key element [element ...](添加元素)

  • 功能:向 HyperLogLog 中添加一个或多个元素;重复添加的元素会被自动忽略。

pfcount key [key ...](统计元素个数)

  • 功能:估算 HyperLogLog 中元素的去重个数;支持同时统计多个 HyperLogLog 的合并个数。

pfmerge destkey sourcekey [sourcekey ...](合并多个 HLL)

  • 功能:将多个 HyperLogLog 的元素合并到destkey中,destkey的计数结果为所有源 HLL 的 "去重合并个数"。

应用场景

  • UV 统计:统计网站 / APP 的独立访客数(无需精确到个位数,0.81% 误差可接受);
  • 搜索关键词去重:统计某段时间内用户搜索的 "不重复关键词个数",无需存储具体关键词;
  • 设备去重:统计连接 WiFi 的 "不重复设备数",海量设备场景下节省内存。

5.Bitmap

Bitmap(位图)是一种 "按位存储" 的数据结构,本质是一个二进制字符串(如010110),每个比特位(bit)对应一个 "状态"(0 或 1),支持 "位级别的读写操作",核心优势是 "极致节省空间"(1 字节 = 8 比特,可存储 8 个整数的状态)。

核心特性

  • 空间高效:存储 100 万个整数的状态(如 "是否在线"),仅需约 125KB 内存(1000000 / 8 / 1024 ≈ 122KB);
  • 位级操作:支持 "设置某比特位的值""获取某比特位的值""统计所有 1 的个数" 等操作,时间复杂度均为 O (1);
  • 整数映射:适合存储 "整数型 ID" 的状态(如用户 ID、设备 ID),每个 ID 对应一个比特位(ID 为比特位的下标)。

核心命令

setbit key offset value(设置某比特位的值)

  • 功能:设置 Bitmap 中 "下标为offset" 的比特位的值(value为 0 或 1);offset为非负整数(对应整数 ID,如用户 ID=100,offset=100)。

getbit key offset(获取某比特位的值)

  • 功能:获取 Bitmap 中 "下标为offset" 的比特位的值(0 或 1);若offset超出当前 Bitmap 长度,返回 0。

bitcount key [start end](统计 1 的个数)

  • 功能:统计 Bitmap 中 "所有比特位为 1" 的个数;start和end为字节下标(可选,默认统计所有字节),用于限定统计范围。

应用场景

  • 用户在线状态:每个用户 ID 对应一个比特位(如用户 1001 对应offset=1001),1 = 在线,0 = 离线。通过setbit实时更新状态,bitcount快速统计在线人数,getbit查询单个用户状态 ------ 相比用 Set 存储 "在线用户 ID",内存占用降低 8 倍以上。
  • 签到功能:用sign:user:1001存储用户 1001 的月度签到记录,offset为日期(1-31),1 = 已签到,0 = 未签到。例如 "3 号签到" 调用setbit sign:user:1001 3 1,月末用bitcount sign:user:1001统计当月签到天数,高效且省空间。
  • 数据权限标记:用 Bitmap 存储 "用户对资源的权限",如perm:user:1001中,offset=1表示 "查看权限",offset=2表示 "编辑权限",1 = 拥有权限,0 = 无权限。通过setbit授予 / 收回权限,getbit验证权限,逻辑简洁。

与 HyperLogLog 的区别

两者虽都 "省空间",但核心用途完全不同:

对比维度 Bitmap HyperLogLog
核心功能 存储整数 ID 的 "状态"(0/1),支持查询单个状态 估算集合元素个数(去重计数),不存状态
数据可读性 可通过getbit查询单个 ID 的状态 无法查询单个元素是否存在
适用场景 用户在线、签到、权限标记 UV 统计、关键词去重计数

6. Bitfields

Bitfields(位域)是 Bitmap 的 "进阶版"------ 它将一个二进制字符串(字节数组)拆分为多个 "位段"(Bit Segment),每个位段赋予独立含义(如用 3 位存 "年龄段",2 位存 "性别"),支持对单个位段进行 "读取、修改、算术运算",核心目标是 "在极小空间内存储多维度整数信息"。

核心特性

  • 位段自定义:可自由定义每个位段的 "长度" 和 "符号"(无符号 / 有符号),例如用 4 位存 "等级"(0-15),5 位存 "积分"(0-31);
  • 多操作批量执行:支持在一个bitfields命令中批量执行多个位段操作(如同时读取 "等级" 和 "积分"),减少网络请求;
  • 安全算术运算:对位点段执行 "加 / 减" 时,自动检测溢出并返回溢出状态,避免数据错误(如 3 位无符号位段最大为 7,加 1 溢出时返回溢出标记)。

核心命令

bitfields key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

bitfields是一个 "复合命令",通过子命令(GET/SET/INCRBY)实现不同操作,type表示位段类型(如u3=3 位无符号,i4=4 位有符号),offset表示位段在二进制字符串中的起始位置(从 0 开始)。


6.小结

类型 核心功能 空间效率 典型场景 关键限制
Stream 高级消息队列,支持 ACK、分组消费 中等(按消息条数增长) 订单状态流转、分布式日志收集 不支持消息延迟发送(需额外开发)
Geospatial 存储经纬度,支持距离 / 范围查询 中等(底层 Zset) 附近的人、周边商户推荐 仅支持二维平面距离计算(不支持海拔)
HyperLogLog 海量元素去重计数(估算) 极高(固定 12KB) UV 统计、关键词去重计数 存在 0.81% 误差,无法查询单个元素
Bitmap 位级存储整数 ID 状态(0/1) 极高(1 字节存 8 个状态) 用户在线、签到、权限标记 仅支持整数 ID,不适合多维度信息
Bitfields 拆分位段,存储多维度小整数 极高(自定义位段长度) 用户画像、设备状态、游戏属性 位段长度有限(最大 64 位),适合小整数

Redis 的五大特殊类型,本质是针对 "细分场景" 的 "专精工具"------ 它们不像 String、Hash 那样通用,却在各自领域做到了 "效率与空间的极致平衡":

  • Stream 解决了 "可靠消息队列" 的痛点,让 Redis 能替代轻量级中间件;
  • Geospatial 让 Redis 具备 "地理计算" 能力,无需依赖专门的地理数据库;
  • HyperLogLog 用 12KB 搞定亿级去重计数,突破内存限制;
  • Bitmap 和 Bitfields 则将 "位操作" 用到极致,在小空间内存储更多信息。

使用这些特殊类型时,关键是 "不滥用"------ 先明确业务需求是否属于它们的 "专精领域",再结合空间、精度、操作成本选择。

相关推荐
maray3 小时前
论 AI Database
数据库·人工智能
茉莉玫瑰花茶3 小时前
Qt 界面优化 --- 绘图
开发语言·数据库·qt
hqwest3 小时前
QT肝8天07--连接数据库
开发语言·数据库·c++·qt·sqlite·上位机·qt开发
lagelangri6664 小时前
MySql的存储过程以及JDBC实战
android·数据库·mysql
Joseit10 小时前
AI应用生成平台:数据库、缓存与存储
数据库·人工智能·缓存
迎風吹頭髮11 小时前
UNIX下C语言编程与实践9-UNIX 动态库创建实战:gcc 参数 -fpic、-shared 的作用与动态库生成步骤
c语言·数据库·unix
黑马金牌编程12 小时前
深入浅出 Redis:从核心原理到运维实战指南一
数据库·redis·缓存·性能优化·非关系型数据库
李迟12 小时前
2025年9月个人工作生活总结
服务器·数据库·生活
Terio_my13 小时前
Spring Boot 集成 Redis 缓存解决方案
spring boot·redis·缓存