本文是「程序员名词解释」系列第 01 期。系列目标:用最少的篇幅,把高频知识点讲透。
适合人群:后端入门、准备面试、想系统梳理 Redis 基础的开发者。
学 Redis 那会儿,我对着命令表背了三天,越背越晕。后来换了个方法:先搞懂每个结构"长什么样、拿来干嘛",命令反而是顺带记住的。
Redis 本质上就是内存里的 5 个抽屉:
| 结构 | 像什么 | 一句话场景 |
|---|---|---|
| String | 便利贴 | 缓存 / 计数 / 分布式锁 |
| Hash | 档案袋 | 存对象 / 购物车 |
| List | 排队通道 | 时间线 / 任务队列 |
| Set | 抽奖箱 | 去重 / 共同好友 |
| 事务 | 打包窗口 | 一组命令一起执行 |
下面逐个展开。
一、String(字符串)—— 便利贴
一次贴一张,一张写一个值,这是 Redis 中最简单也最常用的结构。
生活类比:便利店储物柜——一个柜子号对应一件东西。
核心特点
- 一个 key 对应一个 value(字符串或数字)
- 支持设置过期时间(自动删除)
- 数字可以直接自增/自减,且是原子操作
实战场景
- 缓存热点数据:商品详情页天天被访问,放内存里秒开;
- 计数器:文章点赞数用
INCR一步到位,天然原子性,不怕并发打爆; - 分布式锁:
SETNX(set if not exists)——谁先把贴贴上,锁就归谁。
常用命令
SET key value # 设置值
GET key # 取值
SETEX key 60 value # 设置值并指定 60 秒后过期
SETNX key value # 仅当 key 不存在时设置(分布式锁基础)
INCR count # 原子自增 1
INCRBY count 5 # 原子自增 5
DECR count # 原子自减 1
APPEND key "abc" # 追加字符串
STRLEN key # 取长度
记忆点:一个 key 对一个 value,还能贴个"自动过期时间"。
二、Hash(哈希)—— 档案袋
一个 key 里面装多个"字段:值"对,是存储对象的天然结构。每个 Hash 最多可存储约 4 亿个键值对。
生活类比:员工档案袋——一个袋子装姓名、工号、部门若干卡片,抽改互不影响。
核心特点
- 字段名和值都是字符串,构成映射关系
- 可以只改对象里的某一个字段,不用整个对象读出再写回
- 相比"一个对象序列化成一个 String"存法,改单字段更省、更不易出错
实战场景
- 存用户信息:改年龄只抽"年龄"那张卡,整个档案不用动;
- 购物车:
user:1001一个袋子,里面放商品 ID 和数量。
常用命令
HSET user:1 name fenglaixiang # 设置字段
HGET user:1 name # 取单个字段
HMSET user:1 name 张三 age 18 # 批量设置
HGETALL user:1 # 取全部字段和值
HEXISTS user:1 age # 判断字段是否存在
HINCRBY cart:1001 sku2001 2 # 字段值原子自增(购物车加数量)
HDEL user:1 age # 删除字段
记忆点:一个对象 = 一个袋,改哪张卡抽哪张。
三、List(列表)—— 排队通道
按插入顺序排序的字符串列表,两端都能进出。单个列表最多可存 2^32 - 1(约 42 亿+)个元素。
生活类比:银行排队通道——前端进来排着,后端叫号办完离开。
核心特点
- 有序:严格按插入顺序
- 两端操作效率极高:
LPUSH/RPUSH/LPOP/RPOP都是 O(1) - 中间元素访问较慢:按下标取是 O(N),别拿它当数组用
实战场景
- 最新消息列表:你刷的微博时间线,背后就是 List(
LRANGE取前 N 条); - 简单任务队列:
RPUSH生产任务,LPOP取走执行;要阻塞式消费就用BLPOP。
常用命令
LPUSH tl msg1 # 左端入队
RPUSH tl msg2 # 右端入队
LRANGE tl 0 9 # 取前 10 条(时间线翻页)
LPOP tl # 左端弹出
RPOP tl # 右端弹出
LLEN tl # 取长度
LINDEX tl 5 # 按下标取(慎用,O(N))
LTRIM tl 0 99 # 修剪列表,只保留前 100 条
记忆点:两头进出、先来后到——时间线和队列都是它。
四、Set(集合)—— 抽奖箱
无序、自动去重的字符串集合。判断"某个值在不在集合里"是 O(1),不管集合里有多少元素。
生活类比:抽奖箱——同一个名字不会掉进去两次;摇一摇随机出奖。
核心特点
- 唯一性:重复元素进不去
- 无序:不保证顺序
- 支持交、并、差集运算(这是它最值钱的能力)
实战场景
- 去重:访问过的 IP 扔进去,重复的自动进不去;
- 共同好友:两个用户的关注集合求交集(
SINTER),交集就是共同好友; - 抽奖:
SPOP随机弹出中奖名单。
常用命令
SADD ip_visits 1.2.3.4 # 加入集合
SISMEMBER ip_visits 1.2.3.4 # 判断是否在集合中(O(1))
SCARD ip_visits # 集合大小
SINTER friends_A friends_B # 交集(共同好友)
SUNION friends_A friends_B # 并集
SDIFF friends_A friends_B # 差集(A 有 B 没有的)
SPOP lottery 3 # 随机弹 3 个(抽奖)
SRANDMEMBER lottery 3 # 随机取 3 个但不删除
记忆点:自动去重 + 交并差运算,社交功能神器。
五、事务(Transaction)—— 打包窗口
把一组命令打包成一个整体执行:要么全部执行,要么都不执行,执行过程中不会插入其他客户端的命令。
生活类比:银行柜台的打包业务——材料齐了一次性盖完章,中途不许别的客户插队。
玩法三步走
MULTI:开始打包,后续命令进入队列排队,不立即执行;EXEC:交单,队列里的命令按顺序一次性执行;DISCARD:中途反悔,丢弃已排队的全部命令。
进阶:WATCH(乐观锁思想)
WATCH key 监视某个 key,如果在 EXEC 之前这个 key 被其他客户端改过,本次事务直接放弃(返回 nil),一个命令都不执行。适合"读-改-写"防冲突场景。
示例
MULTI
SET a 1
INCR count
EXEC # 上面两条命令作为一个整体被执行
MULTI
WATCH balance # (实际使用时 WATCH 在 MULTI 之前)
# 若 balance 在 EXEC 前被别人改动,本事务不执行
DECRBY balance 100
EXEC
记忆点:MULTI 是开始,EXEC 是交单,中途不接客。
六、一图总结
| 结构 | 像什么 | 核心能力 | 典型场景 | 代表命令 |
|---|---|---|---|---|
| String | 便利贴 | 单值 + 过期 + 原子自增 | 缓存、计数、锁 | SET SETEX INCR SETNX |
| Hash | 档案袋 | 对象级存取,改单字段 | 用户信息、购物车 | HSET HGET HGETALL |
| List | 排队通道 | 两端 O(1),顺序保证 | 时间线、队列 | LPUSH RPOP LRANGE |
| Set | 抽奖箱 | 去重 + 交并差 | 去重、共同好友、抽奖 | SADD SISMEMBER SINTER |
| 事务 | 打包窗口 | 命令打包原子执行 | 扣款+加积分成对操作 | MULTI EXEC WATCH |
面试提醒:被问"Redis 有哪些数据结构",别只报菜名——每个结构带一句"我用它做过什么",例如"我们用 Set 的 SINTER 做共同好友,两个集合求交集就够了",含金量立刻不一样。
下期预告
《Redis 为什么比 MySQL 快 100 倍?》——从内存存储、单线程模型、IO 多路复用三个角度讲清楚。关注我,不错过更新。
如果本文对你有帮助,欢迎 点赞、收藏、评论 三连;有任何讲得不准确的地方,评论区指出,我会第一时间勘误。
参考资料:本人 Redis 学习笔记整理(环境搭建、数据结构、事务章节)。命令示例基于 Redis 6.x。
本文系统讲解Redis的五种基础数据结构:String(字符串)、Hash(哈希)、List(列表)、Set(集合)及事务(Transaction)。重点阐述各结构的核心特点、典型实战场景(如缓存、计数器、用户信息存储、消息队列、去重、共同好友计算、分布式锁与乐观锁WATCH)及关键命令。强调结构设计意图与使用边界,助力开发者理解本质而非死记命令。
342

被折叠的 条评论
为什么被折叠?



