Spring:Redis

Spring:Redis

介绍

Redis(Remote Dictionary Server) 是一个开源的内存数据库,用来存储键值对(key-value)的数据。和传统的 MySQL 这些“硬盘数据库”不同,Redis 是把数据放在内存里,速度非常快,适合做缓存、计数器、排行榜、验证码这些对性能要求很高的场景。

Redis 有啥特点?

  • 基于内存,读写巨快(能达到几十万QPS)

  • 支持多种数据结构

    • String 字符串(最常用)

    • List 列表(可以当消息队列用)

    • Set 集合(不重复元素)

    • Hash 哈希(类似小型对象)

    • ZSet 有序集合(排行榜)

  • 支持过期时间(适合验证码、登录状态)

  • 支持发布/订阅、事务、Lua 脚本

  • 可持久化:虽然是内存数据库,但也可以保存到磁盘,断电不丢数据(RDB、AOF)

为什么不用SQL呢?

  • 数据库操作更重、I/O 更慢,不适合高频的验证码读写。

  • 验证码属于“临时数据”,放进主业务数据库污染数据表。

  • 还要考虑清理过期验证码的问题,而 Redis 本身就能自动淘汰。

Redis 常见应用场景

  • 缓存热点数据(比如首页文章列表)

  • 存验证码、短连接、Token 等临时信息

  • 限流防刷(比如登录失败超过5次就锁账号)

  • 实现排行榜(有序集合 ZSet)

  • 实现分布式锁(高并发资源控制)

代码实践

既然要使用Redis,我们首先得拥有Redis
常见的有两种使用方法,使用各大平台上的云Redis,免费的或者付费的
或者下载一个本地的Redis服务。

在本地使用Redis

Redis下载

好,你下好了,接下来我们进入解压好的文件夹
直接点击start.bat开始运行……吗?
你也不想让别人知道你的Redis吧😋
我们直接进入redis.conf文件进行配置

修改端口号

CTRL + F 搜索 port 6379
6379是你的默认端口号,请修改为自己喜欢的

1
port 1145

修改密码

1
2
# requirepass foobared
requirepass 114514

测试

在Redis根目录打开控制台输入

1
2
3
redis-cli -p 1145
auth 114514
>OK

这样本地服务就正常启动了

GUI

推荐一个可视化Redis管理客户端咩~
Another Redis Desktop Manager | 更快、更好、更稳定的Redis桌面(GUI)管理客户端,兼容Windows、Mac、Linux,性能出众,轻松加载海量键值

在Spring中使用

配置

首先,和其他模块一样,上来先配置一手

1
2
3
4
5
6
7
8
9
10
11
12
spring:
redis:
host: 你的Redis地址
port: Redis端口号
password: 密码
username: default
timeout: 5000 # 连接超时时间(ms)
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0

工具类

无非就是 设置,获取,删除

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.dawnlight.chronicle_dawnlight.common.utils;  

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

@Autowired
private StringRedisTemplate stringRedisTemplate;

// 配置支持 Java 8 时间类型的 ObjectMapper private final ObjectMapper objectMapper;

public RedisUtil() {
this.objectMapper = new ObjectMapper();
this.objectMapper.registerModule(new JavaTimeModule());
this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 避免时间戳格式
}

/**
* 设置键值对(对象序列化为 JSON 存储),并设置过期时间
*/
public <T> void set(String key, T value, long timeout) {
if (key == null || value == null) {
throw new IllegalArgumentException("Key or value cannot be null");
}
try {
String json = objectMapper.writeValueAsString(value);
stringRedisTemplate.opsForValue().set(key, json, timeout, TimeUnit.MINUTES);
} catch (Exception e) {
throw new RuntimeException("Redis set operation failed", e);
}
}

/**
* 获取值(JSON 反序列化为对象)
*/
public <T> T get(String key, TypeReference<T> typeReference) {
try {
String json = stringRedisTemplate.opsForValue().get(key);
if (json == null) {
return null;
}
// 使用 ObjectMapper 解析 JSON 字符串为指定类型
return objectMapper.readValue(json, typeReference);
} catch (Exception e) {
throw new RuntimeException("Redis get operation failed", e);
}
}

/**
* 删除键
*/
public void delete(String key) {
stringRedisTemplate.delete(key);
}
/**
* 删除指定前缀的所有键
* @param folderPrefix 前缀,例如 "folder:subfolder:"
*/ public void deleteFolder(String folderPrefix) {
try {
// 使用 Redis 模糊查询匹配键
Set<String> keys = stringRedisTemplate.keys(folderPrefix + "*");
if (keys != null && !keys.isEmpty()) {
// 删除匹配的键
stringRedisTemplate.delete(keys);
System.out.println("删除成功,删除键数量:" + keys.size());
} else {
System.out.println("未找到匹配的键");
}
} catch (Exception e) {
throw new RuntimeException("删除文件夹失败", e);
}
}
}

实例

拿验证码举例
当用户点击“获取验证码”按钮的时候,前端请求一个/sendMailCaptcha

1
2
3
4
5
6
@RequestMapping("/sendMailCaptcha")  
public void sendHtmlMailMessage(String to) {
//生成验证码
String code = generateSixDigitCode();
redisUtil.set(to + "code", code, 1);
...

生成验证码后,把用户的id和字段“code“拼接,作为key
把验证码的值作为 Value
过去时间设置为“1”(一分钟)

1
2
3
4
{
Key:xxxxxcode,
Value:1145
}

就把这串东西存到了Redis中。

验证码是用来用来注册或者邮箱登录之类的,
我们写注册或者邮箱登录的时候,除了基础信息,再新增一个 code字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Integer registerUser(UserDTO userDTO, String code) throws BaseException {
...
String redisCode = redisUtil.get(userDTO.getEmail() + "code", new TypeReference<String>() {});
// 校验验证码
if (code.isEmpty()) {
throw new BaseException("请输入验证码");
}
if (redisUtil.get(redisCode) == null){
throw new BaseException("验证码已过期");
}
if (!code.equals(redisCode)) {
throw new BaseException("验证码错误");
}
...

当验证码通过的时候,我们再使用

1
redisUtil.delete(userDTO.getEmail()+"code")

把验证码删除。

以上
如果有错误,还请在评论区指出,谢谢大佬们。


Spring:Redis
https://www.zheep.top/posts/1509927759/
作者
西行寺岩羊
发布于
2025年5月8日
许可协议