【计算基础|Redis02】【上手】五大数据类型命令逐条实操

【计算基础|Redis02】【上手】五大数据类型命令逐条实操

上一篇把连接、配置、通用 key 命令跑通了。这一篇是 Redis 的核心------五大数据类型 。很多人学 Redis 卡在"命令背了一堆,不知道啥时候用哪个"。这篇反过来:每个类型先讲它长什么样、适合干啥,再把高频命令逐条过一遍(语法→实例→输出→易错点),最后用五个真实业务场景把它串起来。

所有命令在 Redis 7.4.11 真实实例上跑过,输出原样贴入。

环境:Docker 官方镜像 redis:7(redis-cli 7.4.11)。先 docker exec -it <容器名> redis-cli 连进去跟着敲。


一、先厘清:五种类型到底是五种"数据结构"

Redis 的 value 不是只能存字符串。它给你五种现成的数据结构,选对类型,很多业务逻辑一行命令就解决。一句话先记住:

类型 像什么 典型场景
String 一个 key → 一个值 缓存、计数、分布式锁、会话
List 双向链表 消息队列、最新列表、时间线
Hash 对象(field-value 字典) 用户信息、商品属性
Set 无序、不重复集合 标签、去重、共同好友
ZSet 带分数的 Set(自动排序) 排行榜、延迟队列、限流

🔴 选型口诀:要计数/缓存用 String,要排队用 List,要存对象用 Hash,要去重/交并差用 Set,要排序用 ZSet。


二、String:最基础,也最能打

String 是最朴素的类型,一个 key 对应一个 value。⚠️ 单个 value 最大 512MB(虽然没人真塞这么大)。它远不止"存个字符串",因为 Redis 给它配了原子的数字操作。

2.1 命令逐条

命令 语法 作用 易错点
SET / GET SET k v / GET k 写 / 读 ---
SETNX SETNX k v 不存在才设 返回 1 成功 / 0 已存在;分布式锁的基础
SETEX SETEX k 秒 v 设值+过期原子完成 一步到位,别先 SET 再 EXPIRE
MSET / MGET MSET k1 v1 k2 v2 批量写 / 批量读 一次网络往返,省 RTT
INCR / DECR INCR k / DECR k 原子 ±1 ⚠️ 值不是整数会报错
INCRBY / DECRBY INCRBY k n 原子 ±n ---
APPEND APPEND k v 尾部追加 ---
STRLEN STRLEN k 值长度(字节) 中文按字节算
GETRANGE / SETRANGE GETRANGE k a b 取/改子串 下标从 0,闭区间
GETSET GETSET k v 设新值,返回旧值 原子"换值取旧"

实跑:

bash 复制代码
# 基本读写
SET goods:1001:stock 50
GET goods:1001:stock
text 复制代码
OK
50

SETNX(分布式锁基础------第二个加锁的人失败):

bash 复制代码
SETNX lock:order "u1"      # 第一次,key 不存在 → 1
SETNX lock:order "u2"      # 第二次,key 已存在 → 0
text 复制代码
1
0

SETEX(设值+过期一步原子完成):

bash 复制代码
SETEX code:138001 60 "889900"
TTL code:138001
text 复制代码
OK
60

MSET / MGET(一次往返读写多个):

bash 复制代码
MSET k1 v1 k2 v2 k3 v3
MGET k1 k2 k3 notexist
text 复制代码
OK
v1
v2
v3
            # notexist 那行是空(nil)

INCR 系列(原子自增,计数神器):

bash 复制代码
SET pv 100
INCR pv        # 101
INCRBY pv 20   # 121
DECR pv        # 120
text 复制代码
OK
101
121
120

⚠️ INCR 对非整数直接报错:

bash 复制代码
SET name "alice"
INCR name
text 复制代码
OK
ERR value is not an integer or out of range

APPEND / STRLEN / GETSET:

bash 复制代码
SET greet "hello"
APPEND greet " world"     # 追加后长度 11
STRLEN greet
GETSET greet "reset"      # 返回旧值 "hello world"
GET greet                 # 现在是 "reset"
text 复制代码
OK
11
11
hello world
reset

GETRANGE / SETRANGE:

bash 复制代码
SET book "redis is fast"
GETRANGE book 0 4         # redis
SETRANGE book 9 "SLOW"    # 从第9位开始替换
GET book                  # redis is SLOW
text 复制代码
OK
redis
13
redis is SLOW

2.2 场景:商品库存扣减

bash 复制代码
SET stock:1001 100        # 上架 100 件
DECR stock:1001            # 卖一件 → 99
INCRBY stock:1001 5        # 退货 5 件 → 104

🔴 为什么用 INCR/DECR 而不是读出来改完写回去?因为 INCR 是原子的。并发 1000 个请求扣库存,读-改-写会超卖,INCR 不会。


三、List:双向链表,天然的队列/栈

List 是按插入顺序排序的字符串链表,头尾插入/删除是 O(1),中间是 O(N)(底层是 quicklist)。所以它适合"只从两端操作"的场景。

3.1 命令逐条

命令 语法 作用 易错点
LPUSH / RPUSH LPUSH k v 从左 / 右插入 LPUSH 后左边是队头
LPOP / RPOP LPOP k 从左 / 右弹出 返回弹出的值
LRANGE LRANGE k start stop 取区间元素 ⚠️ stop 含边界 ;0 -1 是全部
LLEN LLEN k 长度 ---
LINDEX LINDEX k i 按下标取 O(N),别频繁用
LSET LSET k i v 按下标改 ---
LINSERT LINSERT k BEFORE/AFTER 锚 v 在锚点附近插 ---
LREM LREM k count v 删等于 v 的元素 count 控制删几个、方向
LTRIM LTRIM k start stop 只保留区间,删其余 ⚠️ LTRIM 0 99 留最新 100 条

实跑(当消息队列:LPUSH 生产、RPOP 消费):

bash 复制代码
LPUSH queue:msg "task-1" "task-2" "task-3"
LRANGE queue:msg 0 -1
LLEN queue:msg
LINDEX queue:msg 0
text 复制代码
3
task-3       # LPUSH 是左插,最后插的在最左
task-2
task-1
3
task-3

RPOP 从右消费(先进先出):

bash 复制代码
RPOP queue:msg         # task-1(最早进的先出)
LRANGE queue:msg 0 -1
text 复制代码
task-1
task-3
task-2

LSET / LINSERT:

bash 复制代码
LSET queue:msg 0 "task-2-updated"
LINSERT queue:msg BEFORE "task-2-updated" "task-0"
LRANGE queue:msg 0 -1
text 复制代码
OK
3
task-0
task-2-updated
task-2

LREM(删指定元素)/ LTRIM(裁剪):

bash 复制代码
RPUSH queue:msg "task-9" "task-9" "task-9"
LREM queue:msg 2 "task-9"     # 从左往右删 2 个 task-9
LRANGE queue:msg 0 -1
LTRIM queue:msg 0 2           # 只留前 3 个
LRANGE queue:msg 0 -1
LLEN queue:msg
text 复制代码
2
task-0
task-2-updated
task-2
task-9          # 还剩 1 个 task-9
OK
task-0
task-2-updated
task-2
3

3.2 场景:简单消息队列 + 最新 100 条

bash 复制代码
# 生产:LPUSH 塞任务;消费:RPOP 取任务(FIFO)
LPUSH email:queue "uid=1;to=a@x.com"
RPOP email:queue

# "最新 100 条":LPUSH 进,再 LTRIM 裁到留 100 条
LPUSH feed:me "post-1001"
LTRIM feed:me 0 99

⚠️ List 做队列不支持阻塞 ,消费者得自己轮询 RPOP 空转。要阻塞等消息用 BRPOP,要可靠消息用 Stream。


四、Hash:存对象,别用一大坨 String

Hash 是 key 下面挂一堆 field-value,天然就是"对象"。比如一个用户,不用把整个对象序列化成一个 String,而是每个字段一个 field。

4.1 命令逐条

命令 语法 作用 易错点
HSET / HGET HSET k f v / HGET k f 设/取单个字段 7.x 多字段用 HSET
HMGET HMGET k f1 f2 批量取字段 ---
HDEL HDEL k f 删字段 ---
HEXISTS HEXISTS k f 字段是否存在 1/0
HGETALL HGETALL k 取全部字段和值 ⚠️ 大 hash 别用,O(N)
HKEYS / HVALS HKEYS k 只取所有字段名 / 值 ---
HLEN HLEN k 字段个数 ---
HINCRBY HINCRBY k f n 字段原子加 n ---
HSCAN HSCAN k cursor 增量遍历字段 替代 HGETALL 大数据量

Redis 6.0 起 HMSET 已废弃,多字段写入统一用 HSET k f1 v1 f2 v2。

实跑(存用户对象):

bash 复制代码
HSET user:100 name "alice" age 28 city "Beijing"
HGET user:100 name
HGETALL user:100
text 复制代码
3
alice
name
alice
age
28
city
Beijing

HEXISTS / HKEYS / HVALS / HLEN:

bash 复制代码
HEXISTS user:100 phone     # 0
HEXISTS user:100 name       # 1
HKEYS user:100
HVALS user:100
HLEN user:100
text 复制代码
0
1
name
age
city
alice
28
Beijing
3

HINCRBY(字段级自增)/ HDEL:

bash 复制代码
HSET user:100 score 10
HINCRBY user:100 score 5     # 15
HDEL user:100 city            # 删掉 city 字段
HGET user:100 city           # 空
text 复制代码
1
15
1

4.2 场景:用户信息

bash 复制代码
HSET user:1 name "alice" age 28 city "Beijing"
HGET user:1 name        # 单独改/取某个字段,不用动整个对象
HINCRBY user:1 age 1    # 长一岁

🔴 什么时候用 Hash、什么时候用 String 存 JSON?字段经常独立改用 Hash;整个对象整体读写、字段多而杂用 String 存 JSON(序列化方便)。


五、Set:无序不重复,交并差是杀手锏

Set 里的元素不重复、无序 。它真正香的不是"存个集合",而是集合运算:交集、并集、差集,一行命令搞定。

5.1 命令逐条

命令 语法 作用 易错点
SADD / SREM SADD k v... 加 / 删元素 重复元素自动去重
SMEMBERS SMEMBERS k 取全部元素 ⚠️ 大 set 慎用
SISMEMBER SISMEMBER k v 是否存在 1/0,O(1)
SCARD SCARD k 元素个数 ---
SPOP SPOP k 随机弹出并删 抽奖
SRANDMEMBER SRANDMEMBER k n 随机取 n 个不删 ---
SINTER SINTER k1 k2 交集 共同好友
SUNION SUNION k1 k2 并集 ---
SDIFF SDIFF k1 k2 差集 我有你没有
SMOVE SMOVE k1 k2 v 把 v 从 k1 移到 k2 ---

实跑(两个人的关注列表):

bash 复制代码
SADD follow:a "u1" "u2" "u3" "u4"
SADD follow:b "u3" "u4" "u5" "u6"
SMEMBERS follow:a
text 复制代码
4
4
u1
u2
u3
u4

SISMEMBER / SCARD:

bash 复制代码
SISMEMBER follow:a "u3"     # 1
SISMEMBER follow:a "u99"    # 0
SCARD follow:a              # 4
text 复制代码
1
0
4

交并差(本篇灵魂):

bash 复制代码
SINTER follow:a follow:b     # 共同关注
SUNION follow:a follow:b     # 全部关注过的人
SDIFF follow:a follow:b      # A 关注但 B 没关注的
text 复制代码
# 交集
u3
u4
# 并集
u1
u2
u3
u4
u5
u6
# 差集
u1
u2

SPOP / SRANDMEMBER / SMOVE / SREM:

bash 复制代码
SPOP follow:b                 # 随机弹一个
SRANDMEMBER follow:a 2       # 随机取 2 个
SMOVE follow:a follow:b "u2"  # 把 u2 从 a 挪到 b
SREM follow:b "u5"            # 删 u5
text 复制代码
u3
u3
u4
1
1

5.2 场景:共同好友 / 标签去重

bash 复制代码
# 两个人共同关注谁?一行交集
SINTER follow:a follow:b

# 文章打标签,自动去重
SADD article:100:tags "redis" "db" "cache"
SISMEMBER article:100:tags "redis"

六、ZSet:带分数的 Set,排行榜本命

ZSet(Sorted Set)每个 member 绑一个 score(分数) ,member 唯一、score 可重复,并且自动按 score 排好序。要排序、要 Top N,首选它。

6.1 命令逐条

命令 语法 作用 易错点
ZADD ZADD k score member 加元素 member 重复则更新 score
ZRANGE ZRANGE k s e [WITHSCORES] 按 score 升序取区间 下标,闭区间
ZREVRANGE ZREVRANGE k s e 按 score 降序 排行榜 Top N
ZRANGEBYSCORE ZRANGEBYSCORE k min max 按分数区间取 (80 表示开区间
ZSCORE ZSCORE k member 取某 member 的分 ---
ZCARD ZCARD k 元素总数 ---
ZCOUNT ZCOUNT k min max 区间内个数 ---
ZINCRBY ZINCRBY k n member 给某成员加分 原子
ZRANK / ZREVRANK ZRANK k member 排名(升/降) 从 0 开始
ZREM ZREM k member 删成员 ---

实跑(积分排行榜):

bash 复制代码
ZADD rank 90 "alice" 85 "bob" 95 "carol" 70 "dave"
ZRANGE rank 0 -1 WITHSCORES      # 升序,带分数
text 复制代码
4
dave
70
bob
85
alice
90
carol
95

降序取 Top3:

bash 复制代码
ZREVRANGE rank 0 2 WITHSCORES
text 复制代码
carol
95
alice
90
bob
85

按分数区间取(含边界):

bash 复制代码
ZRANGEBYSCORE rank 80 100
text 复制代码
bob
alice
carol

开区间(( 表示不含该边界):

bash 复制代码
ZRANGEBYSCORE rank "(80" 100      # 分数严格大于 80
text 复制代码
bob
alice
carol

ZSCORE / ZCARD / ZCOUNT / ZINCRBY:

bash 复制代码
ZSCORE rank alice       # 90
ZCARD rank              # 4
ZCOUNT rank 80 100      # 3 个在 [80,100]
ZINCRBY rank 5 alice    # alice 加 5 分 → 95
ZSCORE rank alice
text 复制代码
90
4
3
95
95

ZRANK / ZREVRANK(名次从 0 开始,别当成第 1 名):

bash 复制代码
ZREVRANK rank carol     # carol 降序排第 0(即第一名)
ZRANK rank dave         # dave 升序排第 0(最后一名)
text 复制代码
0
0

ZREM:

bash 复制代码
ZREM rank dave
ZCARD rank              # 4 → 3
text 复制代码
1
3

6.2 场景:积分榜 / 延迟队列

bash 复制代码
# 用户答题积分,每答一题加 10 分
ZINCRBY game:score 10 "alice"
# 实时 Top10
ZREVRANGE game:score 0 9 WITHSCORES
# 延迟队列:把"执行时间戳"当 score,到点的任务 ZRANGEBYSCORE 捞出来
ZADD delay:queue 1737000000 "send-sms-123"

🔴 ZSet 底层是跳表 + 哈希表,所以"按分数排序"和"按 member 查分数"都是 O(logN),又快又顺。排行榜、延时队列、按时间线的 feed 都靠它。


七、五个场景对照表:选型不纠结

业务需求 用哪个 核心命令
商品库存 / 页面计数 / 验证码 String SET + DECR/INCR/SETEX
分布式锁 String SETNX(或 SET NX EX)
简单消息队列 / 最新列表 List LPUSH/RPOP + LTRIM
用户对象 / 商品属性 Hash HSET/HGET/HINCRBY
共同好友 / 标签去重 Set SINTER/SADD
积分榜 / 热搜榜 / Top N ZSet ZADD/ZREVRANGE/ZINCRBY
延迟队列 ZSet score 存时间戳,ZRANGEBYSCORE

总结:你真正需要记住的 8 件事

  1. 五类型一句话选型:String 计数缓存、List 排队、Hash 对象、Set 去重交并差、ZSet 排序。
  2. String 单 value 上限 512MB;INCR/DECR 原子自增,并发计数/扣库存的关键,非整数会报错。
  3. SETNX 不存在才设,是分布式锁基础;SETEX 设值+过期原子完成,别拆两步。
  4. List 头尾 O(1)、中间 O(N),只从两端玩;LRANGE 0 -1 是全部(stop 含边界);LTRIM 0 99 留最新 100 条。
  5. Hash 适合字段会独立改的对象;HGETALL 大对象慎用,用 HSCAN。
  6. Set 的杀手锏是 SINTER/SUNION/SDIFF,共同好友一行搞定;元素无序不重复。
  7. ZSet 是排行榜本命:member 唯一、score 可重复,重复加 member 会更新分数;ZREVRANGE 出 Top N,ZRANK 名次从 0 开始。
  8. 大集合别用 SMEMBERS/HGETALL 一把梭(O(N) 阻塞),用对应的 *SCAN 增量遍历。

验证清单

  • 能用 SETNX 复现"第一个加锁成功、第二个失败"
  • 能说出 SETEX 为什么比 SET+EXPIRE 更安全(原子性)
  • 能用 List 搭一个 LPUSH 生产 / RPOP 消费的小队列
  • 会用 LTRIM 0 99 把列表裁成"最新 100 条"
  • 能用 Hash 存一个用户对象,并单独 HINCRBY 给 age 加 1
  • 会用 SINTER 算出两个人的共同关注
  • 能用 ZSet 建一个积分榜,并用 ZREVRANGE ... WITHSCORES 打出 Top3
  • 会用 ZRANGEBYSCORE "(80" 100 表达"分数严格大于 80"
  • 能说清为什么 INCR 扣库存不会超卖、而"读-改-写"会

参考资源


下一篇《【上手】Python 连接 Redis》:用 redis-py 实战------连接池、五类型 CRUD、过期、pipeline 批量(附逐条 vs pipeline 实测耗时对比)、MULTI/WATCH 事务,以及一个能跑通的"查询先查缓存"最小示例,为后面的缓存实战篇打底。

相关推荐
GISer_Jing14 分钟前
AI Agent秋招面试万字通关指南|架构、ReAct、上下文工程、RAG、评测、生产运维全解
后端·ai·langchain
Moment43 分钟前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
时间的拾荒人1 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾1 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
小南家的青蛙2 小时前
基于Spring Boot 2.x开发的微服务访问Redis的方案
redis·springboot
学长毕设2 小时前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
bksczm2 小时前
Redis 持久化:RDB 快照与 AOF 日志
数据库·redis·mybatis
橙序员小站2 小时前
Windows 安装包反复报错?一次排查补上了 5 个 CI 检查点
后端
陈随易2 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员