redis的基本数据结构讲解

Redis 的核心优势在于其丰富的数据结构,这些结构不仅仅是简单的键值存储,而是针对特定场景高度优化的。理解这些结构及其适用场景是高效使用 Redis 的关键。下面详细说明:

Redis 主要数据结构及适用场景

  1. String (字符串)

    • 描述: 最基本的数据类型。可以存储文本、数字(整数或浮点数)或二进制数据(如图片、序列化对象)。最大可存储 512MB。
    • 关键特性:
      • 二进制安全: 可以存储任何字节序列。
      • 原子操作: INCR, DECR, INCRBY, DECRFLOAT 等命令是原子的,非常适合计数器。
      • 批量操作: MSET, MGET
      • 设置过期时间: SETEX, PSETEX
    • 适用场景:
      • 缓存: 缓存 HTML 片段、API 响应、数据库查询结果等。
      • 计数器: 网站访问量 (INCR)、点赞数 (INCR)、库存扣减 (DECR)。
      • 分布式锁: 配合 SETNX (或 SETNX 选项) 和过期时间实现。
      • Session 存储: 存储用户会话信息。
      • 简单的键值映射: 存储用户配置项、标志位 (SET/GET)。
      • 限速器: 使用 INCREXPIRE 限制 API 调用频率或操作次数。
  2. List (列表)

    • 描述: 有序的字符串元素集合。元素按插入顺序排序,可以添加在头部 (LPUSH) 或尾部 (RPUSH)。底层实现是双向链表ziplist (小列表优化)。
    • 关键特性:
      • 双端操作: LPUSH/RPUSH (添加), LPOP/RPOP (移除并返回), LRANGE (获取范围)。
      • 阻塞操作: BLPOP/BRPOP/BRPOPLPUSH (在列表为空时阻塞客户端,直到有元素可弹出)。
      • 长度操作: LLEN
    • 适用场景:
      • 消息队列:
        • 简单队列:生产者 LPUSH 消息,消费者 RPOP (或 BRPOP) 消息。
        • 工作队列:配合 BRPOPLPUSH 实现安全的工作队列(处理中的消息移到另一个列表)。
      • 最新消息/动态流: LPUSH 新消息,用 LRANGE 0 N 获取最新的 N 条消息 (如 Twitter 时间线)。
      • 历史记录: LPUSH 用户操作记录,用 LTRIM 限制长度 (如浏览历史)。
      • 栈: LPUSH + LPOP
      • 队列: LPUSH + RPOP (或 RPUSH + LPOP)。
  3. Set (集合)

    • 描述: 无序的、唯一的字符串元素集合。不允许重复元素。底层实现是 hashtableintset (纯整数小集合优化)。
    • 关键特性:
      • 添加/删除/检查存在: SADD, SREM, SISMEMBER
      • 集合运算: SINTER (交集), SUNION (并集), SDIFF (差集), SINTERSTORE/SUNIONSTORE/SDIFFSTORE (存储运算结果)。
      • 随机元素: SRANDMEMBER, SPOP (随机移除并返回)。
      • 成员操作: SMEMBERS (获取所有成员 - 小心大集合!), SCARD (获取成员数量)。
    • 适用场景:
      • 标签系统: 给对象(文章、用户)打标签 (SADD),查找拥有某标签的所有对象 (SMEMBERS),查找同时拥有多个标签的对象 (SINTER)。
      • 社交关系: 存储用户的粉丝 (SADD)、关注 (SADD) 列表。计算共同关注 (SINTER)。
      • 唯一值追踪: 记录访问过某资源的唯一用户 ID/IP (SADD, SISMEMBER),统计 UV (SCARD)。
      • 抽奖/随机选取: SPOPSRANDMEMBER
      • 黑名单/白名单: 快速检查元素是否在集合中 (SISMEMBER)。
  4. Hash (哈希表 / 字典)

    • 描述: 键值对集合。field (字段名) 和 value (字段值) 都是字符串类型。非常适合表示对象。底层实现是 hashtableziplist (小哈希优化)。
    • 关键特性:
      • 字段操作: HSET/HGET (单个), HMSET/HMGET (多个), HDEL
      • 原子字段更新: HINCRBY, HINCRBYFLOAT
      • 检查存在: HEXISTS
      • 获取所有/部分: HGETALL (小心大哈希!), HKEYS, HVALS, HSCAN (迭代)。
      • 长度: HLEN
    • 适用场景:
      • 缓存对象: 比将整个对象序列化成 String 更高效。可以单独更新对象的某个字段 (HSET) 而不需要读写整个对象。例如用户信息 (user:id -> {name: "Alice", age: 30, email: ...})。
      • 存储配置项: 多个相关的配置项可以存储在一个 Hash 里。
      • 购物车: user:cart -> {product1_id: quantity, product2_id: quantity, ...}。方便增减数量 (HINCRBY)。
      • 需要频繁读写部分属性的场景。
  5. Sorted Set (有序集合 / ZSet)

    • 描述: 与 Set 类似,也是唯一的字符串元素集合。但每个元素都关联一个 score (分数,浮点数)。元素根据 score 从小到大排序。如果 score 相同,则按元素的字典序排序。底层实现是 skiplist (跳跃表) + hashtableziplist (小集合优化)。
    • 关键特性:
      • 添加/更新: ZADD (可设置/更新分数)。
      • 按分数范围查询: ZRANGEBYSCORE, ZREVRANGEBYSCORE (逆序)。
      • 按排名范围查询: ZRANGE, ZREVRANGE (逆序)。
      • 按成员查询分数/排名: ZSCORE, ZRANK (正序排名), ZREVRANK (逆序排名)。
      • 集合运算: ZUNIONSTORE, ZINTERSTORE (可聚合分数 - 如 SUM, MIN, MAX)。
      • 删除: ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE
      • 统计数量: ZCARD (总数量), ZCOUNT (分数范围内的数量)。
    • 适用场景:
      • 排行榜: 经典场景!分数代表热度、分数、时间戳等。ZADD 更新分数,ZREVRANGE 0 N WITHSCORES 获取 Top N。
      • 带权重的队列: 任务优先级队列。分数表示优先级。
      • 时间轴: 分数存储时间戳,ZRANGEBYSCORE 按时间范围查询事件。
      • 范围查找: 查找分数在某个区间的所有元素。
      • 滑动窗口限流: 将请求时间戳作为分数加入 ZSet,定期删除旧于时间窗口的元素,检查窗口内元素数量是否超限。
  6. Bitmaps (位图)

    • 描述: 不是独立的数据类型,而是基于 String 类型提供的一组面向位的操作命令。可以将 String 视为一个由二进制位组成的数组。
    • 关键特性:
      • 位操作: SETBIT (设置位), GETBIT (获取位), BITCOUNT (统计置位数量), BITOP (位运算 AND/OR/XOR/NOT), BITPOS (查找第一个置位/清零位)。
      • 高效存储: 非常适合存储布尔值信息(是/否,存在/不存在)。
    • 适用场景:
      • 用户在线状态: 用户 ID 作为偏移量 (offset), SETBIT online_status
      • 签到系统: 用户 ID + 日期作为键,偏移量代表具体日期(一年第几天)。SETBIT sign:2024:userid
      • 特征标志: 用户拥有哪些特性/权限 (每个位代表一个特性)。
      • 布隆过滤器 (Bloom Filter) 基础: 需要结合多个 Bitmap 和哈希函数实现。
      • 实时分析: 高效统计大量布尔属性(如活跃用户)。
  7. HyperLogLog (基数统计)

    • 描述: 用于估计一个集合中唯一元素数量 (基数)的概率性数据结构。不是独立类型,有专用命令(PFADD, PFCOUNT, PFMERGE)。
    • 关键特性:
      • 极省内存: 无论元素数量多少,固定使用约 12KB 内存。
      • 非精确: 提供的是带有标准误差(约 0.81%)的估计值。
      • 不支持获取元素: 只能添加元素和统计基数。
    • 适用场景:
      • 海量数据去重计数: 网站每日独立访客数 (UV)、搜索引擎独立搜索词统计、大型集合的近似基数计算。当精确结果不是必需且需要节省大量内存时使用。
  8. Geospatial Indexes (地理空间索引)

    • 描述: 基于 Sorted Set (ZSet) 实现的,用于存储地理位置(经度、纬度)并执行相关查询的数据结构。有专用命令(GEOADD, GEODIST, GEORADIUS, GEORADIUSBYMEMBER, GEOHASH)。
    • 关键特性:
      • 添加位置: GEOADD (本质上是将经纬度编码成 score 存入 ZSet)。
      • 计算距离: GEODIST
      • 范围查询: GEORADIUS (以给定点为中心,半径内的元素), GEORADIUSBYMEMBER (以某个成员为中心)。
      • 获取 Geohash: GEOHASH
    • 适用场景:
      • 附近的人/地点: 查找用户当前位置一定半径范围内的 POI(兴趣点)、司机、朋友等。
      • 距离计算: 计算两个地理位置之间的距离。
      • 基于位置的推荐。
  9. Streams (流)

    • 描述: Redis 5.0 引入的,专为消息传递和事件溯源设计的数据结构。类似于 Kafka 或 RabbitMQ 的持久化消息队列。
    • 关键特性:
      • 消息持久化与多播: 支持持久化消息,多个消费者组可以独立消费。
      • 结构化消息: 每条消息由键值对组成。
      • 消费者组: 提供消费者组 (XGROUP), 消费者 (XREADGROUP), 消息确认 (XACK), 待处理消息处理 (XPENDING, XCLAIM) 等机制。
      • 范围查询: XRANGE, XREVRANGE
      • 阻塞读取: XREAD/XREADGROUP 支持阻塞等待新消息。
    • 适用场景:
      • 可靠的消息队列: 需要持久化、多消费者组、消息确认的场景。
      • 事件溯源: 记录系统中发生的事件序列。
      • 实时数据管道: 连接不同服务或微服务。
      • 日志采集与分发。

选择数据结构的总结建议

  1. 简单键值/缓存/计数器? -> String
  2. 队列/栈/最新列表? -> List
  3. 无序唯一集合/标签/社交关系? -> Set
  4. 对象缓存/购物车/需要更新部分字段? -> Hash
  5. 排行榜/带权重队列/时间轴/范围查询? -> Sorted Set (ZSet)
  6. 布尔值/特征标志/签到/在线状态? -> Bitmaps (基于 String)
  7. 海量数据去重计数 (近似值)? -> HyperLogLog
  8. 地理位置/附近搜索? -> Geospatial (基于 ZSet)
  9. 可靠消息队列/事件溯源? -> Streams

重要注意事项

  • 内存是核心资源: Redis 数据存储在内存中,选择合适的数据结构对控制内存占用至关重要(如使用 Hash 代替多个 String,使用 HyperLogLog 代替 Set 计数)。
  • 时间复杂度: 了解主要命令的时间复杂度(如 SMEMBERS 是 O(n),大集合慎用;ZRANGE 是 O(log N + M),M 是返回元素数)。使用 SCANHSCANSSCANZSCAN 替代 KEYSHGETALLSMEMBERS 等遍历命令避免阻塞。
  • 持久化: 根据需求配置 RDB 快照或 AOF 日志,确保数据安全。
  • 集群与分片: 单实例容量有限,大数据量需要 Redis Cluster 或客户端分片。
相关推荐
超浪的晨1 小时前
Java 实现 B/S 架构详解:从基础到实战,彻底掌握浏览器/服务器编程
java·开发语言·后端·学习·个人开发
追逐时光者2 小时前
一款超级经典复古的 Windows 9x 主题风格 Avalonia UI 控件库,满满的回忆杀!
后端·.net
Python涛哥3 小时前
go语言基础教程:【1】基础语法:变量
开发语言·后端·golang
我命由我123453 小时前
PostgreSQL 保留关键字冲突问题:语法错误 在 “user“ 或附近的 LINE 1: CREATE TABLE user
数据库·后端·sql·mysql·postgresql·问题·数据库系统
LUCIAZZZ4 小时前
final修饰符不可变的底层
java·开发语言·spring boot·后端·spring·操作系统
wsj__WSJ4 小时前
Spring Boot 请求参数绑定:全面解析常用注解及最佳实践
java·spring boot·后端
CodeUp.5 小时前
SpringBoot航空订票系统的设计与实现
java·spring boot·后端
码事漫谈5 小时前
Linux下使用VSCode配置GCC环境与调试指南
后端
求知摆渡5 小时前
RocketMQ 从二进制到 Docker 完整部署(含 Dashboard)
运维·后端