Redis缓存入门与实战

一、为什么需要Redis?

Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,可以用作数据库、缓存和消息队列。

1.1 Redis vs 传统数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────────┐
│ 传统数据库查询 │
├─────────────────────────────────────────────────────────────────┤
│ 用户请求 → 查询数据库 → 返回结果 │
│ ↓ │
1000个用户同时查询 → 数据库压力山大 😰 │
│ ↓ │
│ 每次都要走磁盘I/O → 响应慢 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
Redis缓存加速 │
├─────────────────────────────────────────────────────────────────┤
│ 用户请求 → 先查Redis缓存 → 有就直接返回 ✅ │
│ ↓ │
│ 没有 → 查询数据库 → 存入Redis → 返回结果 │
│ ↓ │
│ 第二次请求 → Redis直接返回 → 速度飞起 🚀 │
│ │
"内存" vs "磁盘" = 光速 vs 牛车 │
└─────────────────────────────────────────────────────────────────┘

1.2 Redis能做什么?

场景 说明
缓存 热点数据缓存,提升访问速度
Session存储 Web应用会话管理
计数器 点赞数、访问量、限流
排行榜 实时排名、有序集合
分布式锁 多进程互斥、防止重复提交
消息队列 异步任务、消息发布/订阅
验证码 短信验证码、接口限流

1.3 Redis特点

  • 内存存储 → 读写速度极快(QPS可达10万+)
  • 持久化 → 数据可保存到磁盘
  • 多种数据结构 → String、List、Hash、Set、ZSet
  • 主从复制 → 支持读写分离
  • 高可用 → Sentinel + 集群

二、安装Redis

2.1 Ubuntu/Debian安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 更新apt源
sudo apt update

# 安装Redis
sudo apt install -y redis-server

# 启动Redis
sudo systemctl start redis
sudo systemctl enable redis # 开机自启

# 检查状态
sudo systemctl status redis

# 测试连接
redis-cli ping
# 应该返回: PONG

2.2 Docker安装(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 拉取镜像
docker pull redis:7

# 运行Redis容器
docker run -d \
--name redis-server \
-p 6379:6379 \
redis:7

# 运行并挂载数据卷
docker run -d \
--name redis-server \
-p 6379:6379 \
-v ~/redis/data:/data \
redis:7 \
redis-server --appendonly yes

# 连接Redis
docker exec -it redis-server redis-cli

2.3 Windows安装

1
2
3
4
5
# 方法一:使用WSL(推荐)
# 在WSL中按照Ubuntu方式安装

# 方法二:使用Docker Desktop
# 下载安装 Docker Desktop,运行上面Docker命令

2.4 配置文件常用参数

1
2
3
4
5
6
7
8
9
10
11
# 配置文件位置
sudo vim /etc/redis/redis.conf

# 常用配置
bind 0.0.0.0 # 允许远程连接
port 6379 # 端口
daemonize yes # 后台运行
requirepass yourpassword # 设置密码
maxmemory 512mb # 最大内存
appendonly yes # 开启持久化
logfile /var/log/redis/redis.log # 日志文件

三、Redis数据结构

3.1 String(字符串)

最基础的数据类型,可以存字符串、数字、JSON等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 基本操作
SET name "zhangsan" # 设置值
GET name # 获取值
GETRANGE name 0 3 # 截取字符串(0-3)
STRLEN name # 获取长度

# 数字操作
SET count 10
INCR count # 自增1 → 11
INCRBY count 5 # 自增5 → 16
DECR count # 自减1 → 15
DECRBY count 3 # 自减3 → 12

# 批量操作
MSET key1 "value1" key2 "value2" # 批量设置
MGET key1 key2 # 批量获取

# 过期时间
SETEX token 3600 "abc123" # 设置值+过期时间(秒)
PSETEX token 3600000 "abc123" # 过期时间(毫秒)

# 高级操作
SETNX lock "1" # 不存在则设置(分布式锁)
GETSET old "new" # 获取旧值并设置新值

3.2 Hash(哈希)

适合存储对象、JSON数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 基本操作
HSET user:1 name "zhangsan" # 设置哈希字段
HGET user:1 name # 获取字段值
HMGET user:1 name age # 批量获取
HGETALL user:1 # 获取所有字段和值

# 字段操作
HEXISTS user:1 name # 字段是否存在
HINCRBY user:1 age 1 # 数字字段自增
HDEL user:1 name # 删除字段

# 统计
HLEN user:1 # 字段数量
HKEYS user:1 # 所有字段名
HVALS user:1 # 所有字段值

实战:存储用户信息

1
2
3
4
5
6
7
8
9
10
11
# 存储用户对象
HSET user:1001 username "zhangsan"
HSET user:1001 email "zhangsan@example.com"
HSET user:1001 age "25"

# 或者用一条命令
HSET user:1002 username "lisi" email "lisi@example.com" age "30"

# 获取用户信息
HGETALL user:1001
# 返回: username, zhangsan, email, zhangsan@example.com, age, 25

3.3 List(列表)

有序、可重复的列表,支持双向操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 基本操作
LPUSH tasks "task1" # 左边插入
RPUSH tasks "task3" # 右边插入
LPUSH tasks "task0"

LRANGE tasks 0 -1 # 查看列表(0到-1=全部)
# 返回: task0, task1, task3

# 弹出操作
LPOP tasks # 左边弹出
RPOP tasks # 右边弹出

# 列表长度
LLEN tasks

# 高级操作
LTRIM tasks 0 4 # 截取列表(保留0-4)
LSET tasks 0 "newfirst" # 设置指定位置的值

# 消息队列示例
RPUSH queue:email "user1@example.com"
RPUSH queue:email "user2@example.com"
BRPOP queue:email 0 # 阻塞弹出(等待消息)

3.4 Set(集合)

无序、不重复的元素集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 基本操作
SADD tags "python" "java" "go" # 添加元素
SMEMBERS tags # 查看所有元素
SISMEMBER tags "python" # 检查是否存在
SREM tags "java" # 删除元素

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

SUNION set1 set2 # 并集 → a,b,c,d
SINTER set1 set2 # 交集 → b,c
SDIFF set1 set2 # 差集 → a

# 统计
SCARD tags # 元素数量
SRANDMEMBER tags # 随机获取一个元素
SPOP tags # 随机弹出(删除)

实战:抽奖程序

1
2
3
4
5
6
7
8
9
10
11
# 添加参与者
SADD lottery:2026 "user1" "user2" "user3" "user4" "user5"

# 抽取1个中奖者
SRANDMEMBER lottery:2026

# 抽取3个中奖者
SRANDMEMBER lottery:2026 3

# 抽取并移除(中奖后不能重复中奖)
SPOP lottery:2026 3

3.5 ZSet(有序集合)

每个元素有一个分数,按分数排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 基本操作
ZADD leaderboard 100 "zhangsan" # 添加元素及分数
ZADD leaderboard 95 "lisi" 88 "wangwu"

ZRANGE leaderboard 0 -1 WITHSCORES # 正序查询
ZREVRANGE leaderboard 0 -1 WITHSCORES # 倒序查询

# 排名操作
ZRANK leaderboard "zhangsan" # 正序排名(从0开始)
ZREVRANK leaderboard "zhangsan" # 倒序排名

# 分数操作
ZINCRBY leaderboard 10 "lisi" # 增加分数
ZSCORE leaderboard "zhangsan" # 获取分数

# 范围查询
ZRANGEBYSCORE leaderboard 90 100 # 分数90-100之间的成员

实战:排行榜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 模拟游戏排行榜
ZADD game:scores 5000 "player1"
ZADD game:scores 8500 "player2"
ZADD game:scores 3200 "player3"
ZADD game:scores 9700 "player4"

# 获取前3名
ZREVRANGE game:scores 0 2 WITHSCORES

# player2再玩一局,增加500分
ZINCRBY game:scores 500 "player2"

# 再次查看排名
ZREVRANGE game:scores 0 2 WITHSCORES

四、Redis持久化

4.1 RDB方式

定时快照,生成数据文件。

1
2
3
4
5
6
7
8
9
10
11
# 配置(redis.conf)
save 900 1 # 1个key变化,900秒后保存
save 300 10 # 10个key变化,300秒后保存
save 60 10000 # 10000个key变化,60秒后保存

dbfilename dump.rdb
dir /var/lib/redis

# 手动触发
BGSAVE # 后台保存
SAVE # 同步保存(阻塞)

优点:恢复快,文件紧凑
缺点:可能丢失最后一次快照的数据

4.2 AOF方式

记录所有写操作命令。

1
2
3
4
5
6
7
8
# 配置(redis.conf)
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec # everysec(每秒),always(每次),no(系统)

# 重写压缩
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

优点:数据安全,最多丢失1秒
缺点:文件较大,恢复稍慢

4.3 建议配置

1
2
3
4
# 兼顾性能和安全
appendonly yes
appendfsync everysec
rdbcompression yes

五、Redis安全

5.1 设置密码

1
2
3
4
5
6
7
8
9
10
11
12
# 临时设置(重启失效)
redis-cli CONFIG SET requirepass "yourpassword"

# 永久设置
# 在redis.conf中添加:
requirepass yourpassword

# 登录
redis-cli -a yourpassword
# 或
redis-cli
AUTH yourpassword

5.2 禁用危险命令

1
2
3
4
5
# 在redis.conf中
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
rename-command CONFIG ""

六、Redis Java客户端

6.1 Jedis(简单易用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 添加依赖
// <dependency>
// <groupId>redis.clients</groupId>
// <artifactId>jedis</artifactId>
// <version>5.0.0</version>
// </dependency>

import redis.clients.jedis.Jedis;

public class RedisDemo {
public static void main(String[] args) {
// 连接Redis
Jedis jedis = new Jedis("localhost", 6379);
// jedis.auth("password"); // 如果有密码

// String操作
jedis.set("name", "zhangsan");
System.out.println(jedis.get("name"));

// 数字自增
jedis.set("count", "0");
jedis.incr("count");
System.out.println(jedis.get("count"));

// Hash操作
jedis.hset("user:1", "name", "zhangsan");
jedis.hset("user:1", "age", "25");
System.out.println(jedis.hgetAll("user:1"));

// List操作
jedis.lpush("tasks", "task1");
jedis.rpush("tasks", "task2");
System.out.println(jedis.lrange("tasks", 0, -1));

// Set操作
jedis.sadd("tags", "java", "python", "go");
System.out.println(jedis.smembers("tags"));

// ZSet操作
jedis.zadd("leaderboard", 100, "player1");
jedis.zadd("leaderboard", 90, "player2");
System.out.println(jedis.zrevrangeWithScores("leaderboard", 0, -1));

// 设置过期时间(秒)
jedis.setex("verify:code", 300, "123456");

// 关闭连接
jedis.close();
}
}

6.2 Spring Boot整合Redis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 1. 添加依赖
// <dependency>
// <groupId>org.springframework.boot</groupId>
// <artifactId>spring-boot-starter-data-redis</artifactId>
// </dependency>

// 2. 配置application.yml
// spring:
// data:
// redis:
// host: localhost
// port: 6379
// password: yourpassword

// 3. 使用RedisTemplate
@Autowired
private RedisTemplate<String, Object> redisTemplate;

// 存取值
redisTemplate.opsForValue().set("name", "zhangsan");
Object value = redisTemplate.opsForValue().get("name");

// Hash操作
redisTemplate.opsForHash().put("user:1", "name", "zhangsan");
Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1");

// 过期时间
redisTemplate.opsForValue().set("token", "abc123", Duration.ofHours(1));

七、实战案例

7.1 接口限流

1
2
3
4
5
6
7
8
9
10
11
12
// 简单限流:每分钟最多10次
public boolean isAllowed(String userId) {
String key = "rate:limit:" + userId;
Long count = redisTemplate.opsForValue().increment(key);

if (count == 1) {
// 第一次,设置过期时间
redisTemplate.expire(key, 60, TimeUnit.SECONDS);
}

return count <= 10;
}

7.2 分布式锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取锁
public boolean tryLock(String lockKey, String requestId, int expireTime) {
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, Duration.ofSeconds(expireTime));
return Boolean.TRUE.equals(result);
}

// 释放锁(只能释放自己的锁)
public void releaseLock(String lockKey, String requestId) {
String value = (String) redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(value)) {
redisTemplate.delete(lockKey);
}
}

7.3 Session共享

1
2
3
4
5
6
7
8
9
10
11
12
// 存储用户Session
public void saveSession(String sessionId, Map<String, Object> sessionData) {
String key = "session:" + sessionId;
redisTemplate.opsForHash().putAll(key, sessionData);
redisTemplate.expire(key, 30, TimeUnit.MINUTES);
}

// 获取Session
public Map<Object, Object> getSession(String sessionId) {
String key = "session:" + sessionId;
return redisTemplate.opsForHash().entries(key);
}

7.4 验证码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 发送验证码
public String sendVerifyCode(String phone) {
String code = String.valueOf((int)((Math.random() * 9 + 1) * 100000));
String key = "verify:phone:" + phone;

// 存Redis,5分钟过期
redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);

// 实际发送短信(调用短信平台API)
// smsService.send(phone, code);

return code;
}

// 验证验证码
public boolean verifyCode(String phone, String code) {
String key = "verify:phone:" + phone;
String savedCode = (String) redisTemplate.opsForValue().get(key);

if (savedCode != null && savedCode.equals(code)) {
redisTemplate.delete(key); // 验证后删除
return true;
}
return false;
}

八、Redis集群

8.1 主从复制

1
2
3
4
5
6
7
8
9
10
# 主节点配置
# redis.conf
bind 0.0.0.0
port 6379

# 从节点配置
# redis.conf
bind 0.0.0.0
port 6380
replicaof 127.0.0.1 6379

8.2 Sentinel哨兵

1
2
3
4
5
6
7
# 启动哨兵
redis-sentinel /path/to/sentinel.conf

# sentinel.conf配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000

九、常用命令速查

9.1 Key操作

命令 说明
KEYS pattern 查找key
DEL key 删除key
EXISTS key key是否存在
EXPIRE key seconds 设置过期
TTL key 查看剩余过期时间
PERSIST key 移除过期时间

9.2 String操作

命令 说明
SET key value 设置值
GET key 获取值
INCR key 自增1
DECR key 自减1
SETEX key seconds value 设置值+过期

9.3 Hash操作

命令 说明
HSET key field value 设置字段
HGET key field 获取字段
HGETALL key 获取全部
HDEL key field 删除字段

9.4 List操作

命令 说明
LPUSH/RPUSH key value 插入元素
LPOP/RPOP key 弹出元素
LRANGE key start end 范围查询

9.5 Set/ZSet操作

命令 说明
SADD/ZADD key score member 添加元素
SMEMBERS/ZRANGE key 获取元素
SCARD/ZCARD key 元素数量

十、常见问题

10.1 内存占用过高

1
2
3
4
5
6
7
# 查看内存使用
INFO memory

# 设置最大内存
# redis.conf
maxmemory 512mb
maxmemory-policy allkeys-lru

10.2 持久化阻塞

1
2
# 生产环境建议使用AOF + BGSAVE
# 在从节点做持久化

10.3 连接数过多

1
2
3
# 设置最大连接数
# redis.conf
maxclients 10000

十一、Redis vs Memcached

特性 Redis Memcached
数据结构 丰富 简单
持久化 支持 不支持
复制 支持 不支持
集群 支持 支持
内存效率 中等
单线程 多线程

参考资料


持续更新中…欢迎收藏!

#Redis #缓存 #NoSQL #数据库 #教程


Redis缓存入门与实战
https://r0f2.my/post/25-redis-caching-strategy/
作者
JA
发布于
2026年2月13日
许可协议