当前位置: 首页 > news >正文

Redis核心数据结构详解与应用

Redis 的强大核心在于其丰富的数据结构,每种结构都针对特定场景设计,并配有专用的命令集。以下是 Redis 最常用的核心数据结构及其关键特性、应用场景和典型命令:


1. String (字符串)

  • 本质: 最简单、最基础的类型。可存储文本、数字(整数/浮点数)或二进制数据(最大 512MB)。
  • 底层实现: 通常使用 SDS (Simple Dynamic String),支持高效的长度获取、追加操作和二进制安全。
  • 核心特性:
    • 原子计数器 (INCR, DECR, INCRBY, DECRBY, INCRBYFLOAT)。
    • 位操作 (SETBIT, GETBIT, BITCOUNT, BITOP)。
    • 设置过期时间 (SET key value EX seconds, SETEX, PSETEX)。
    • 不存在时设置 (SETNX - 用于分布式锁基础)。
    • 批量设置/获取 (MSET, MGET)。
  • 典型应用场景:
    • 缓存 HTML 片段、API 响应结果、序列化对象。
    • 计数器(用户点赞数、文章阅读量、库存)。
    • 分布式锁(SET resource_name random_value NX PX milliseconds)。
    • 位图 (Bitmaps) 实现签到、用户状态位图(本质是 String)。
    • 存储小图片或文件序列化。
  • 常用命令:
    SET key value [EX seconds|PX milliseconds] [NX|XX]  # 设置值 (可带过期/条件)
    GET key                                             # 获取值
    INCR key                                            # 整数+1
    DECR key                                            # 整数-1
    INCRBY key increment                                # 整数增加指定值
    APPEND key value                                    # 追加字符串
    STRLEN key                                          # 获取字符串长度
    GETRANGE key start end                              # 获取子串
    SETBIT key offset value                             # 设置位 (value 0/1)
    GETBIT key offset                                   # 获取位
    MSET key1 value1 key2 value2 ...                    # 批量设置
    MGET key1 key2 ...                                  # 批量获取
    

2. Hash (哈希表 / 字典)

  • 本质: 一个 field-value 映射表。非常适合存储对象(如用户信息、商品属性)。
  • 底层实现: 当元素少且小用 ziplist(压缩列表,节省内存),否则用 hashtable
  • 核心特性:
    • 可独立操作单个字段 (HSET, HGET, HDEL)。
    • 批量操作 (HMSET, HMGET, HGETALL)。
    • 字段自增 (HINCRBY, HINCRBYFLOAT)。
    • 判断字段存在 (HEXISTS)。
  • 典型应用场景:
    • 存储对象(用户信息:user:1000 {name: "Alice", age: 30, email: ...})。
    • 购物车(cart:user123 {productId1: quantity, productId2: quantity})。
    • 存储具有多个属性的配置项。
  • 优点 (相比 String 存储对象):
    • 节省空间: 多个字段存储在一个 Key 下,减少 Key 数量。
    • 操作高效: 可单独读写/更新对象的某个属性,无需序列化/反序列化整个对象。
  • 常用命令:
    HSET key field value                                # 设置单个字段
    HGET key field                                      # 获取单个字段
    HMSET key field1 value1 field2 value2 ...           # 批量设置字段 (HMSET 在新版本中常被 HSET 替代)
    HMGET key field1 field2 ...                         # 批量获取字段
    HGETALL key                                         # 获取所有字段和值 (小心大 Hash!)
    HKEYS key                                           # 获取所有字段名
    HVALS key                                           # 获取所有字段值
    HDEL key field1 [field2 ...]                        # 删除字段
    HEXISTS key field                                   # 判断字段是否存在
    HINCRBY key field increment                         # 整数字段增加指定值
    HLEN key                                            # 获取字段数量
    

3. List (列表)

  • 本质: 一个有序、可重复元素的集合。元素在列表两端插入或弹出。
  • 底层实现: 早期用 ziplist (小列表),现在多用 linkedlist (双端链表) 或 quicklist (3.2+,ziplist 组成的双向链表,平衡内存和效率)。
  • 核心特性:
    • 支持 LIFO (栈)FIFO (队列) 操作。
    • 可在头部 (LPUSH) 或尾部 (RPUSH) 插入元素。
    • 可在头部 (LPOP) 或尾部 (RPOP) 弹出元素。
    • 按索引获取元素 (LINDEX)。
    • 获取列表片段 (LRANGE)。
    • 阻塞弹出 (BLPOP, BRPOP - 用于简单消息队列)。
  • 典型应用场景:
    • 消息队列 (LPUSH + BRPOP / RPOPLPUSH 保证可靠性)。
    • 最新消息/文章列表 (LPUSH + LTRIM 保留最新 N 条)。
    • 记录操作流水。
    • 实现栈 (LPUSH + LPOP)。
  • 常用命令:
    LPUSH key element [element ...]                     # 从头部插入一个或多个元素
    RPUSH key element [element ...]                     # 从尾部插入一个或多个元素
    LPOP key                                            # 从头部弹出元素
    RPOP key                                            # 从尾部弹出元素
    BLPOP key [key ...] timeout                         # 阻塞地从头部弹出 (队列)
    BRPOP key [key ...] timeout                         # 阻塞地从尾部弹出 (队列)
    LLEN key                                            # 获取列表长度
    LRANGE key start stop                               # 获取列表片段 (0 -1 表示所有)
    LINDEX key index                                    # 按索引获取元素
    LTRIM key start stop                                # 修剪列表,只保留指定索引范围内元素
    RPOPLPUSH source destination                        # 从 source 尾部弹出并插入到 destination 头部 (原子操作,用于可靠队列)
    

4. Set (集合)

  • 本质: 一个无序、不重复元素的集合。支持高效的集合运算。
  • 底层实现: 元素少且为整数用 intset,否则用 hashtable (value 为 null)。
  • 核心特性:
    • 添加/删除元素 (SADD, SREM)。
    • 判断元素存在 (SISMEMBER)。
    • 获取所有元素 (SMEMBERS - 小心大集合!)。
    • 集合运算:
      • 交集 (SINTER, SINTERSTORE)
      • 并集 (SUNION, SUNIONSTORE)
      • 差集 (SDIFF, SDIFFSTORE)
    • 随机元素 (SRANDMEMBER, SPOP)。
  • 典型应用场景:
    • 标签系统(文章标签、用户兴趣)。
    • 社交关系(共同好友:交集;好友推荐:差集)。
    • 唯一性保证(防止重复提交、抽奖参与者)。
    • 随机选取(抽奖 SPOP,随机推荐 SRANDMEMBER)。
    • 数据过滤(白名单/黑名单)。
  • 常用命令:
    SADD key member [member ...]                        # 添加一个或多个成员
    SREM key member [member ...]                        # 移除一个或多个成员
    SISMEMBER key member                                # 判断成员是否存在
    SMEMBERS key                                        # 获取所有成员 (无序)
    SCARD key                                           # 获取成员数量
    SRANDMEMBER key [count]                             # 随机返回一个或多个成员 (不删除)
    SPOP key [count]                                    # 随机移除并返回一个或多个成员
    SINTER key [key ...]                                # 计算多个集合的交集
    SUNION key [key ...]                                # 计算多个集合的并集
    SDIFF key [key ...]                                 # 计算第一个集合与其他集合的差集
    SINTERSTORE destination key [key ...]               # 计算交集并存储到 destination
    

5. Sorted Set (ZSet - 有序集合)

  • 本质: 在 Set 的基础上,为每个元素关联一个分数 (score)。元素按分数排序(从小到大),分数可相同。元素唯一,分数可更新。
  • 底层实现: ziplist (小集合) 或 skiplist (跳跃表) + hashtable。跳跃表保证有序范围查询效率,hashtable 保证按成员查询效率。
  • 核心特性:
    • 按分数范围查询 (ZRANGEBYSCORE, ZREVRANGEBYSCORE)。
    • 按排名(索引)查询 (ZRANGE, ZREVRANGE)。
    • 获取成员排名 (ZRANK - 正序, ZREVRANK - 逆序)。
    • 获取成员分数 (ZSCORE)。
    • 增加成员分数 (ZINCRBY)。
    • 集合运算(ZUNIONSTORE, ZINTERSTORE - 可指定分数聚合方式 sum/min/max)。
  • 典型应用场景:
    • 排行榜!(按分数排序,如游戏积分榜、商品销量榜、热搜榜)。
    • 带权重的队列(分数代表优先级或执行时间戳)。
    • 范围查找(时间线、价格区间商品)。
    • 限流(滑动窗口,用 ZSet 存储时间戳)。
  • 常用命令:
    ZADD key [NX|XX] [CH] [INCR] score member [score member ...] # 添加成员及其分数 (可带条件/增量)
    ZSCORE key member                                   # 获取成员分数
    ZRANGE key start stop [WITHSCORES]                  # 按排名(低->高)获取成员(带分数)
    ZREVRANGE key start stop [WITHSCORES]               # 按排名(高->低)获取成员(带分数)
    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] # 按分数范围(低->高)获取成员
    ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] # 按分数范围(高->低)获取成员
    ZRANK key member                                    # 获取成员正序排名 (从0开始)
    ZREVRANK key member                                 # 获取成员逆序排名
    ZINCRBY key increment member                        # 增加成员分数
    ZCARD key                                           # 获取成员数量
    ZCOUNT key min max                                  # 计算分数范围内成员数量
    ZREM key member [member ...]                        # 移除成员
    ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] # 并集计算并存储
    

6. 其他重要/高级数据类型

虽然上述 5 种是最核心的,但 Redis 还提供了一些强大的扩展类型:

  • Bitmaps (位图):
    • 本质: 通过 String 类型的位操作实现。可视为一个巨大的位数组。
    • 应用: 用户在线状态、每日签到记录 (SETBIT, GETBIT, BITCOUNT, BITOP - AND/OR/XOR/NOT)。
  • HyperLogLog (基数统计):
    • 本质: 用于估算一个集合中不重复元素的数量(基数),占用极小固定内存(约 12KB)。
    • 应用: 大规模独立访客统计 (UV) (PFADD, PFCOUNT, PFMERGE)。
    • 注意: 有误差(约 0.81%),无法获取具体元素。
  • Geospatial Indexes (地理空间索引):
    • 本质: 基于 Sorted Set 实现,存储经纬度信息。
    • 应用: 附近的人/地点、计算距离 (GEOADD, GEOPOS, GEODIST, GEORADIUS, GEORADIUSBYMEMBER)。
  • Streams (流):
    • 本质: Redis 5.0+ 引入,为日志类数据设计的持久化消息队列。支持消费者组、消息确认、回溯。
    • 应用: 比 List 更可靠的消息队列、事件溯源 (XADD, XREAD, XREADGROUP, XACK, XRANGE, XGROUP)。

选择数据结构的建议

  1. 问“我要存什么?”:

    • 简单键值/计数器? -> String
    • 对象(多个属性)? -> Hash
    • 有序列表(最新、队列、栈)? -> List
    • 唯一集合(标签、共同好友)? -> Set
    • 需要排序(排行榜、优先级)? -> Sorted Set
    • 是/否状态(签到)? -> Bitmaps
    • 估算大量不重复元素(UV)? -> HyperLogLog
    • 地理位置? -> Geospatial
    • 可靠消息流? -> Streams
  2. 考虑性能: 了解常用命令的时间复杂度 (O(1), O(log(N)), O(N))。避免对大集合使用 SMEMBERSHGETALLKEYS *(用 SCAN 代替)。

  3. 考虑内存: ziplist / intset 在元素少且小时非常节省内存。关注 INFO MEMORY

  4. 组合使用: 复杂业务场景可能需要组合多种数据结构(例如,用 Sorted Set 存储排行榜 ID 和分数,用 Hash 存储 ID 对应的详细信息)。

理解并熟练掌握这些数据结构及其适用场景,是高效、优雅使用 Redis 的关键! 它们赋予了 Redis 远超简单键值存储的灵活性和强大能力。

相关文章:

  • 手搓transformer
  • day22
  • Python----神经网络发(神经网络发展历程)
  • Ubuntu系统Docker安装失败问题解决办法
  • 在Vue2项目中引入ElementUI详细步骤
  • 【论文阅读32】预期寿命预测(2024)
  • 用于在多个远程计算机上求解的 Ansoft RSM 设置 - Windows
  • 关于使用EasyExcel、 Vue3实现导入导出功能
  • SpringCloud + MybatisPlus:多租户模式与实现
  • 《网络安全与防护》知识点复习
  • Linux安装C语言环境教程
  • C# net8生成excel,并设置列规则导出文件
  • 深入剖析 Spring @Bean 注解:灵活定义与掌控你的 Bean
  • ABAP 上传 excel 报表
  • get_attribute的使用方法
  • ThreadPoolTaskExecutor+CompletableFuture实现多线程异步数据同步和自定义线程池监控和动态调整实现
  • UE5 学习系列(九)光照系统介绍
  • stm32cubeide中编译非flash起始地址开始的程序
  • 【ARMv7-A】——CLZ 指令
  • Swift 解法详解:如何在二叉树中寻找最长连续序列
  • 软件测试培训包就业是真的吗/免费seo推广计划
  • 网站网页制作教程/企业品牌网站营销
  • 开网站赚钱吗/海洋网络推广效果
  • 常德政府网站市民留言/淘宝关键词怎么选取
  • 做网站必须需要服务器嘛/百度推广平台收费标准
  • 网站logo做黑页/小程序定制开发公司