一、初识 Redis
python
# 拉取最新的 Redis 镜像
docker pull redis
# 启动一个名为 redis 的容器,将容器的 6379 端口映射到宿主机的 6379 端口
# -d 表示后台运行
docker run --name redis -p 6379:6379 -d redis
docker ps
- 如果使用 Docker 启动的 Redis,输入命令:
python
docker exec -it redis redis-cli
上面命令后面加上 --raw 参数即可正常显示中文
如果 Redis 运行在本机且端口为 6379,输入:
python
redis-cli
-
连接成功后,会看到提示符
127.0.0.1:6379>。- 如果设置了Redis密码,则需要使用
AUTH命令手动验证密码
- 如果设置了Redis密码,则需要使用
python
127.0.0.1:6379> AUTH <你的密码>
-
通用命令实践 让我们来练习几个最基础的通用命令,来管理 Redis 中的 Key。
SET key value- 设置一个键值对
python
127.0.0.1:6379> SET user:1:name "Alice"
OK
GET key- 获取一个键的值
python
127.0.0.1:6379> GET user:1:name
"Alice"
KEYS pattern- 查找所有符合给定模式的 Key(注意:生产环境慎用,可能阻塞服务)
python
127.0.0.1:6379> KEYS user:*
1) "user:1:name"
EXISTS key- 判断一个 Key 是否存在
python
127.0.0.1:6379> EXISTS user:1:name
(integer) 1 // 存在返回 1
127.0.0.1:6379> EXISTS non_exist_key
(integer) 0 // 不存在返回 0
TYPE key- 返回 Key 所存储的值的类型
python
127.0.0.1:6379> TYPE user:1:name
string
EXPIRE key seconds- 为 Key 设置过期时间(单位:秒)
python
127.0.0.1:6379> SET session:token "xyz123"
OK
127.0.0.1:6379> EXPIRE session:token 60
(integer) 1 // 设置成功
DEL key [key ...]- 删除一个或多个 Key
python
127.0.0.1:6379> DEL user:1:name
(integer) 1 // 成功删除 1 个 key
二、Redis 五大数据结构详解
1. String (字符串)
1.2 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
| SET key value | 设置指定 key 的值 | SET user:1:name "Alice" |
| GET key | 获取指定 key 的值 | GET user:1:name |
| MSET k1 v1 k2 v2 | 同时设置一个或多个 key-value 对 | MSET product:1 "iPhone" product:2 "MacBook" product:3 "iPad" |
| MGET k1 k2 | 同时获取一个或多个 key 的值 | MGET product:1 product:2 product:3 |
| INCR key | 将 key 中储存的数字值增一(原子操作) | INCR page:view:count |
| DECR key | 将 key 中储存的数字值减一(原子操作) | DECR product:1:stock |
| SETNX key value | 仅当 key 不存在时,设置 key 的值(常用于分布式锁) | SETNX lock:order:1 "processing" |
1.3 应用场景
-
缓存对象 :将用户信息、商品信息等序列化成 JSON 字符串后,用
SET/GET缓存。- 命令:
SET user:1 '{"name":"Bob", "age":25, "email":"``bob@example.com``"}' EX 3600
- 命令:
-
常规计数:网站的访问量、用户点赞数、商品库存等。
- 命令:
INCR page:view:count
- 命令:
-
分布式锁 :利用
SETNX(SET if Not eXists) 的特性,当 key 不存在时才能设置成功,可以保证在分布式环境下只有一个客户端能获取到锁。- 命令:
SET lock:payment:xyz "unique_request_id" NX PX 10000
- 命令:
2. Hash (哈希)
2.2 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
| HSET key field value | 将哈希表 key 中的字段 field 的值设为 value | HSET user:1 name "Carol" email "``carol@example.com``" followers 99 |
| HGET key field | 获取哈希表 key 中给定字段 field 的值 | HGET user:1 name |
| HMGET key f1 f2 | 获取哈希表 key 中一个或多个给定字段的值 | HMGET user:1 name email |
| HGETALL key | 获取哈希表 key 中所有的字段和值 | HGETALL user:1 |
| HDEL key f1 f2 | 删除哈希表 key 中的一个或多个指定字段 | HDEL user:1 email followers |
| HINCRBY key field n | 为哈希表 key 中字段 field 的值加上增量 n | HINCRBY user:1 followers 1 |
2.3 应用场景
-
缓存结构化对象:缓存用户信息、商品信息、文章详情等。
- 例:管理用户
user:1的信息。
- 例:管理用户
python
HSET user:1 name "Carol" email "carol@example.com" followers 99
-
购物车:以用户 ID 为 key,商品 ID 为 field,商品数量为 value。
- 例:用户
user:2的购物车。
- 例:用户
python
HSET cart:user:2 product:101 2 # id为2的用户添加2件id为101的商品到购物车
HINCRBY cart:user:2 product:101 1 # id为101的商品数量加1
HGETALL cart:user:2 # 查看id为2的用户的购物车
3. List (列表)
3.2 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
| LPUSH key v1 v2 ... | 将一个或多个值插入到列表头部 | LPUSH tasks "task1" "task2" "task3" |
| RPUSH key v1 v2 ... | 将一个或多个值插入到列表尾部 | RPUSH tasks "task1" "task2" "task3" |
| LPOP key | 移出并获取列表的第一个元素 | LPOP tasks |
| RPOP key | 移出并获取列表的最后一个元素 | RPOP tasks |
| LRANGE key start stop | 获取列表指定范围内的元素 | LRANGE tasks 0 -1 (获取所有) LRANGE numbers 0 2(获取前3个(索引0,1,2)) LRANGE numbers -3 -1获取后3个(负索引表示从尾部数) |
| DEL key key2 ... | 删除一个或多个指定的键 | DEL tasks |
| BLPOP key timeout | LPOP 的阻塞版本,列表为空时会阻塞等待 | BLPOP tasks 10 BRPOP tasks 10 |
3.3 应用场景
-
文章列表 (Feed 流) :微博、朋友圈等。用户发布新内容时
LPUSH到关注者的 Feed 列表中,LRANGE用于分页展示。- 例:用户 A 发布了一篇新文章
post:501。
- 例:用户 A 发布了一篇新文章
python
# 把这篇文章推送到所有粉丝的Feed列表
> LPUSH feed:user:B post:501
> LPUSH feed:user:C post:501
> LPUSH feed:user:D post:501
...
> LRANGE feed:user:B 0 9 # 用户B刷新微博,获取最新的10条动态
4. Set (集合)
4.2 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
| SADD key m1 m2 ... | 向集合添加一个或多个成员 | SADD tags:post:1 "redis" "nosql" "database" SADD tags:post:2 "redis" "cache" "performance" SADD lottery_pool "user1" "user2" "user3" "user4" "user5" |
| SMEMBERS key | 返回集合中的所有成员 | SMEMBERS tags:post:1 |
| SISMEMBER key m | 判断成员 m 是否是集合 key 的成员 | SISMEMBER tags:post:1 "redis" SISMEMBER tags:post:1 "java" |
| SINTER key1 key2 ... | 返回给定所有集合的交集 | SINTER tags:post:1 tags:post:2 |
| SUNION key1 key2 ... | 返回给定所有集合的并集 | SUNION tags:post:1 tags:post:2 |
| SDIFF key1 key2 ... | 返回给定第一个集合与之后所有集合的差集 | SDIFF tags:post:1 tags:post:2 |
| SPOP key count | 随机移除并返回集合中一个或多个成员 | SPOP lottery_pool 1 |
4.3 应用场景
-
标签系统:为一篇文章或一个商品打上多个标签。
SADD tags:post:1 "redis" "nosql" "database"
-
共同好友/共同关注 :利用
SINTER计算两个用户的共同好友。-
SADD friends:user:1 "userA" "userB" "userC" -
SADD friends:user:2 "userB" "userC" "userD" -
SINTER friends:user:1 friends:user:2->{"userB", "userC"}
-
-
抽奖程序 :使用
SADD将参与用户ID加入集合,SPOP或SRANDMEMBER(可以重复中奖)随机抽取中奖用户。
5. Sorted Set (有序集合)
5.2 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
| ZADD key score member | 向有序集合添加一个或多个成员 | ZADD leaderboard 100 "Alice" ZADD leaderboard 200 "Bob" 150 "Carol" ZADD leaderboard 250 "Alice" |
| ZRANGE key start stop | 通过索引区间返回集合的成员(升序) | ZRANGE leaderboard 0 2 WITHSCORES |
| ZREVRANGE key start stop | 通过索引区间返回集合的成员(降序) | ZREVRANGE leaderboard 0 2 WITHSCORES |
| ZRANGEBYSCORE key min max | 通过分数区间返回集合的成员 | ZRANGEBYSCORE leaderboard 100 200 |
| ZSCORE key member | 返回集合中,成员 member 的分数 | ZSCORE leaderboard "Alice" |
| ZINCRBY key increment member | 为成员 member 的分数加上增量 | ZINCRBY leaderboard 30 "Carol" |
| ZREVRANK key member | 返回有序集合中成员 member 的排名(按分数降序) | ZREVRANK leaderboard "Alice" |
5.3 应用场景
-
排行榜:游戏积分榜、热搜榜、销售榜等。分数(score)是积分/热度,成员(member)是用户ID/搜索词。
-
ZREVRANGE hot-searches 0 9 WITHSCORES// 获取 Top 10 热搜 -
ZINCRBY game:leaderboard:2026 300 "PlayerOne"// 更新玩家积分 -
ZREVRANK game:leaderboard:2026 "PlayerOne"// 查询玩家当前排名
-
ZREVRANGE:O(logN + M),M是返回的元素数
ZINCRBY:O(logN)
ZREVRANK:O(log(N))
- 延迟队列 :用分数存储任务的执行时间戳,通过
ZRANGEBYSCORE定期拉取到期的任务执行。
6. 实践环节
python
# Key 设计:likes:article:{文章ID}
# Value:点赞用户的 ID 集合
# 用户 1001 给文章 123 点赞
SADD likes:article:123 "user:1001"
# 用户 1002 点赞
SADD likes:article:123 "user:1002"
# 获取点赞数
SCARD likes:article:123
# 返回 2
# 判断用户 1001 是否已点赞
SISMEMBER likes:article:123 "user:1001"
# 返回 1(已点赞)
# 取消点赞
SREM likes:article:123 "user:1001"
python
# Key 设计:
# following:{用户ID} - 该用户关注的人
# followers:{用户ID} - 该用户的粉丝
# 用户 A 关注用户 B、C、D
SADD following:userA "userB" "userC" "userD"
# 用户 A 被用户 E、F 关注
SADD followers:userA "userE" "userF"
# 用户 X 关注了 B、C、E
SADD following:userX "userB" "userC" "userE"
# 计算 A 和 X 的共同关注
SINTER following:userA following:userX
# 返回 "userB" "userC"
python
# Key 设计:cart:{用户ID}
# Field:商品 ID
# Value:商品数量
# 用户 1001 添加 2 件商品 A
HSET cart:1001 "productA" 2
# 再添加 1 件商品 B
HSET cart:1001 "productB" 1
# 商品 A 数量 +1
HINCRBY cart:1001 "productA" 1
# 现在商品 A 数量变为 3
# 获取购物车所有商品
HGETALL cart:1001
# 返回 "productA" "3" "productB" "1"
# 删除商品 B
HDEL cart:1001 "productB"
python
# Key 设计:hot:searches:{日期}
# Member:搜索词
# Score:热度值
# 用户搜索 "Redis入门",热度 +1
ZINCRBY hot:searches:2026-01-15 1 "Redis入门"
# 用户搜索 "Java面试题",热度 +1
ZINCRBY hot:searches:2026-01-15 1 "Java面试题"
# 假设 "Redis入门" 被搜索了很多次,热度值变为 9999
ZINCRBY hot:searches:2026-01-15 9998 "Redis入门"
# 获取 Top 10 热搜(降序 + 带分数)
ZREVRANGE hot:searches:2026-01-15 0 9 WITHSCORES