Redis 从入门到实战

一、初识 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 命令手动验证密码
python 复制代码
127.0.0.1:6379> AUTH <你的密码>
  • 通用命令实践 让我们来练习几个最基础的通用命令,来管理 Redis 中的 Key。

    • SET key value - 设置一个键值对
python 复制代码
127.0.0.1:6379> SET user:1:name "Alice"
OK
  1. GET key - 获取一个键的值
python 复制代码
127.0.0.1:6379> GET user:1:name
"Alice"
  1. KEYS pattern - 查找所有符合给定模式的 Key(注意:生产环境慎用,可能阻塞服务
python 复制代码
127.0.0.1:6379> KEYS user:*
1) "user:1:name"
  1. 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
  1. TYPE key - 返回 Key 所存储的值的类型
python 复制代码
127.0.0.1:6379> TYPE user:1:name
string
  1. 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 // 设置成功
  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 应用场景

  1. 缓存对象 :将用户信息、商品信息等序列化成 JSON 字符串后,用 SET/GET 缓存。

    1. 命令:SET user:1 '{"name":"Bob", "age":25, "email":"``bob@example.com``"}' EX 3600
  2. 常规计数:网站的访问量、用户点赞数、商品库存等。

    1. 命令:INCR page:view:count
  3. 分布式锁 :利用 SETNX (SET if Not eXists) 的特性,当 key 不存在时才能设置成功,可以保证在分布式环境下只有一个客户端能获取到锁。

    1. 命令: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 应用场景

  1. 缓存结构化对象:缓存用户信息、商品信息、文章详情等。

    1. 例:管理用户 user:1 的信息。
python 复制代码
HSET user:1 name "Carol" email "carol@example.com" followers 99
  1. 购物车:以用户 ID 为 key,商品 ID 为 field,商品数量为 value。

    1. 例:用户 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 应用场景

  1. 文章列表 (Feed 流) :微博、朋友圈等。用户发布新内容时 LPUSH 到关注者的 Feed 列表中,LRANGE 用于分页展示。

    1. 例:用户 A 发布了一篇新文章 post:501
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 应用场景

  1. 标签系统:为一篇文章或一个商品打上多个标签。

    1. SADD tags:post:1 "redis" "nosql" "database"
  2. 共同好友/共同关注 :利用 SINTER 计算两个用户的共同好友。

    1. SADD friends:user:1 "userA" "userB" "userC"

    2. SADD friends:user:2 "userB" "userC" "userD"

    3. SINTER friends:user:1 friends:user:2 -> {"userB", "userC"}

  3. 抽奖程序 :使用 SADD 将参与用户ID加入集合,SPOPSRANDMEMBER (可以重复中奖)随机抽取中奖用户。

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 应用场景

  1. 排行榜:游戏积分榜、热搜榜、销售榜等。分数(score)是积分/热度,成员(member)是用户ID/搜索词。

    1. ZREVRANGE hot-searches 0 9 WITHSCORES // 获取 Top 10 热搜

    2. ZINCRBY game:leaderboard:2026 300 "PlayerOne" // 更新玩家积分

    3. ZREVRANK game:leaderboard:2026 "PlayerOne" // 查询玩家当前排名

ZREVRANGE:O(logN + M),M是返回的元素数

ZINCRBY:O(logN)

ZREVRANK:O(log(N))

  1. 延迟队列 :用分数存储任务的执行时间戳,通过 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

三、Redis 客户端与 Spring 集成

String 类型操作