第 2 章:五大基础数据类型

jerry北京市2026年4月24日Redis 5 次阅读 约 18 分钟
第 2 章:五大基础数据类型

掌握 String、List、Hash、Set、Sorted Set 的核心命令、底层编码和典型使用场景。


2.1 String(字符串)

最基础的类型,可以存储字符串、整数或浮点数,最大 512MB。

常用命令

# 基本操作
SET key value                  # 设置值
GET key                        # 获取值
DEL key                        # 删除
STRLEN key                     # 获取长度

# 设置选项
SET key value EX 60            # 设置值并指定过期时间(秒)
SET key value PX 60000         # 设置值并指定过期时间(毫秒)
SET key value NX               # 仅当 key 不存在时设置(分布式锁核心)
SET key value XX               # 仅当 key 存在时设置
SETNX key value                # 等价于 SET key value NX
SETEX key 60 value             # 等价于 SET key value EX 60

# 批量操作
MSET k1 v1 k2 v2 k3 v3        # 批量设置
MGET k1 k2 k3                 # 批量获取

# 数值操作
SET counter 100
INCR counter                   # +1 → 101
DECR counter                   # -1 → 100
INCRBY counter 10              # +10 → 110
DECRBY counter 5               # -5 → 105
INCRBYFLOAT counter 1.5        # +1.5 → 106.5

# 追加
APPEND key " world"            # 追加字符串

# 获取子串
GETRANGE key 0 4               # 获取索引 0-4 的子串

# 先获取旧值再设置新值
GETSET key newvalue            # 返回旧值(Redis 6.2+ 用 GETDEL/GETEX)

底层编码

数据 编码 说明
整数(≤ long 范围) int 直接存储整数值
短字符串(≤ 44 字节) embstr 一次内存分配,SDS 和 redisObject 连续
长字符串(> 44 字节) raw 两次内存分配,SDS 和 redisObject 分离
SET num 12345
OBJECT ENCODING num    # "int"

SET short "hello"
OBJECT ENCODING short  # "embstr"

SET long "aaaa...(超过44字节)"
OBJECT ENCODING long   # "raw"

应用场景

  • 缓存:SET user:1001 "{json数据}" EX 3600
  • 计数器:INCR article:1001:views
  • 分布式锁:SET lock:order NX EX 30
  • 分布式 ID:INCR global:id

2.2 List(列表)

有序的字符串列表,支持从两端插入和弹出,底层是双向链表(quicklist)。

常用命令

# 插入
LPUSH list a b c               # 左侧插入:c b a
RPUSH list d e                 # 右侧插入:c b a d e

# 弹出
LPOP list                      # 弹出左侧第一个:c
RPOP list                      # 弹出右侧第一个:e

# 阻塞弹出(消息队列常用)
BLPOP list 10                  # 阻塞等待 10 秒,有数据则弹出
BRPOP list 10

# 查看
LRANGE list 0 -1               # 获取所有元素
LRANGE list 0 2                # 获取前 3 个
LLEN list                      # 列表长度
LINDEX list 0                  # 获取指定索引的元素

# 修改
LSET list 0 "new"              # 设置索引 0 的值
LINSERT list BEFORE "b" "x"    # 在 b 前面插入 x

# 删除
LREM list 2 "a"                # 从左侧删除 2 个值为 a 的元素
LTRIM list 0 99                # 只保留索引 0-99 的元素

# 移动
RPOPLPUSH source dest          # 从 source 右侧弹出,推入 dest 左侧
LMOVE source dest LEFT RIGHT   # Redis 6.2+,更灵活的移动

应用场景

  • 消息队列:LPUSH + BRPOP(简单队列)
  • 最新消息列表:LPUSH + LTRIM(保留最新 N 条)
  • 时间线:微博/朋友圈的 Feed 流
# 示例:最新 10 条消息
LPUSH news:latest "新闻1"
LPUSH news:latest "新闻2"
LTRIM news:latest 0 9          # 只保留最新 10 条
LRANGE news:latest 0 -1        # 获取所有

2.3 Hash(哈希)

键值对集合,适合存储对象,类似于 Java 的 HashMap。

常用命令

# 设置
HSET user:1001 name "Alice" age 30 city "Beijing"
HSETNX user:1001 email "alice@example.com"  # 字段不存在时才设置

# 获取
HGET user:1001 name                # "Alice"
HMGET user:1001 name age           # "Alice" "30"
HGETALL user:1001                  # 获取所有字段和值
HKEYS user:1001                    # 获取所有字段名
HVALS user:1001                    # 获取所有值

# 删除
HDEL user:1001 city

# 判断
HEXISTS user:1001 name             # 1(存在)
HLEN user:1001                     # 字段数量

# 数值操作
HINCRBY user:1001 age 1            # age + 1
HINCRBYFLOAT user:1001 score 1.5

底层编码

条件 编码 说明
字段数 ≤ 128 且所有值 ≤ 64 字节 listpack(7.0+)/ ziplist 紧凑存储,省内存
超过上述限制 hashtable 标准哈希表

应用场景

  • 存储对象:HSET user:1001 name "Alice" age 30
  • 购物车:HSET cart:user1001 item:2001 3(商品 ID → 数量)
  • 计数器组:HINCRBY article:1001 likes 1

Hash vs String 存储对象的对比:

方式 优点 缺点
String(JSON) 序列化简单,一次读取 修改单个字段需要全量读写
Hash 可以单独读写字段,省带宽 不支持嵌套结构

2.4 Set(集合)

无序、不重复的字符串集合,支持交集、并集、差集运算。

常用命令

# 添加
SADD tags "go" "redis" "docker"

# 查看
SMEMBERS tags                  # 所有成员
SCARD tags                     # 成员数量
SISMEMBER tags "go"            # 是否存在:1
SRANDMEMBER tags 2             # 随机返回 2 个成员

# 删除
SREM tags "docker"             # 删除指定成员
SPOP tags                      # 随机弹出一个成员

# 集合运算
SADD set1 a b c d
SADD set2 c d e f

SINTER set1 set2               # 交集:c d
SUNION set1 set2               # 并集:a b c d e f
SDIFF set1 set2                # 差集(set1 有但 set2 没有):a b

# 将运算结果存储到新集合
SINTERSTORE result set1 set2

应用场景

  • 标签系统:SADD article:1001:tags "go" "redis"
  • 共同好友:SINTER user:1001:friends user:1002:friends
  • 抽奖:SRANDMEMBER lottery 3(随机抽 3 人)
  • 点赞:SADD article:1001:likes user:2001
  • 唯一计数:SCARD article:1001:likes

2.5 Sorted Set(有序集合)

每个成员关联一个分数(score),按分数排序,成员唯一但分数可以重复。

常用命令

# 添加
ZADD leaderboard 100 "Alice" 95 "Bob" 88 "Charlie"

# 查看
ZRANGE leaderboard 0 -1                    # 按分数升序
ZRANGE leaderboard 0 -1 WITHSCORES         # 带分数
ZREVRANGE leaderboard 0 2                  # 按分数降序,前 3 名
ZRANGEBYSCORE leaderboard 90 100           # 分数在 90-100 之间
ZSCORE leaderboard "Alice"                 # 获取分数:100
ZRANK leaderboard "Alice"                  # 排名(升序,从 0 开始)
ZREVRANK leaderboard "Alice"               # 排名(降序)
ZCARD leaderboard                          # 成员数量
ZCOUNT leaderboard 90 100                  # 分数在 90-100 的数量

# 修改
ZINCRBY leaderboard 5 "Bob"                # Bob 加 5 分

# 删除
ZREM leaderboard "Charlie"
ZREMRANGEBYSCORE leaderboard 0 60          # 删除分数 0-60 的成员
ZREMRANGEBYRANK leaderboard 0 2            # 删除排名 0-2 的成员

# 集合运算
ZUNIONSTORE dest 2 zset1 zset2 WEIGHTS 1 2  # 并集,zset2 权重 x2
ZINTERSTORE dest 2 zset1 zset2               # 交集

底层编码

条件 编码 说明
成员数 ≤ 128 且所有值 ≤ 64 字节 listpack / ziplist 紧凑存储
超过上述限制 skiplist + hashtable 跳表 + 哈希表

应用场景

  • 排行榜:ZADD + ZREVRANGE
  • 延迟队列:score 存时间戳,定时取出到期任务
  • 滑动窗口限流:score 存时间戳
# 示例:排行榜
ZADD game:leaderboard 1500 "player:1001"
ZADD game:leaderboard 2300 "player:1002"
ZADD game:leaderboard 1800 "player:1003"

# 获取 Top 10
ZREVRANGE game:leaderboard 0 9 WITHSCORES

# 获取某玩家排名
ZREVRANK game:leaderboard "player:1002"  # 0(第一名)

2.6 数据类型选择指南

需求 推荐类型 说明
简单缓存 String JSON 序列化存储
对象属性 Hash 可单独读写字段
队列/栈 List LPUSH/RPOP 或 RPUSH/LPOP
去重集合 Set 自动去重
排行榜 Sorted Set 按分数排序
计数器 String(INCR) 原子递增
二值状态 Bitmap 签到、在线状态
基数统计 HyperLogLog UV 统计
地理位置 GEO 附近的人

2.7 面试要点

  1. Redis 有哪些数据类型?

    • 5 种基础类型 + Bitmap、HyperLogLog、GEO、Stream
  2. String 的三种编码?

    • int(整数)、embstr(短字符串 ≤ 44 字节)、raw(长字符串)
  3. Hash 和 String 存对象的区别?

    • Hash 可以单独读写字段,String 需要全量序列化/反序列化
  4. Sorted Set 的底层实现?

    • 小数据量用 listpack/ziplist,大数据量用 skiplist + hashtable
  5. List 实现消息队列的局限?

    • 不支持消费确认、不支持消费组、消息丢失风险

练习

  1. 使用 String 实现一个简单的访问计数器
  2. 使用 Hash 存储用户信息,实现增删改查
  3. 使用 Set 实现两个用户的共同好友查询
  4. 使用 Sorted Set 实现一个实时排行榜

← 上一章:Redis 初识与环境搭建 | 下一章:高级数据类型 →

评论

登录 后发表评论

暂无评论