Redis 与缓存
Personal Blog Backend 使用 Redis 作为分布式缓存层,通过 Spring Cache 注解实现声明式缓存。
🔧 配置
application.yaml
spring:
data:
redis:
host: 127.0.0.1
port: 6379
password: ${REDIS_PASSWORD:} # 生产环境通过环境变量注入
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 2
生产环境
- 必须设置密码 — 通过
REDIS_PASSWORD环境变量 - 建议启用 SSL — 加密传输
💾 Spring Cache 注解
@Cacheable — 读取缓存
@Cacheable(value = "user:roles", key = "#userId")
public List<String> getUserRoleKeys(Long userId) {
// 首次调用查数据库,后续从缓存读取
return userMapper.selectRolesByUserId(userId);
}
@CacheEvict — 失效缓存
@CacheEvict(value = "user:roles", key = "#userId")
public void evictUserRolesCache(Long userId) {
log.info("失效用户角色缓存: userId={}", userId);
}
@CachePut — 更新缓存
@CachePut(value = "user:detail", key = "#result.id")
public UserDTO createUser(UserDTO dto) {
return super.saveByDto(dto);
}
🛠️ RedisUtils 工具类
项目提供 RedisUtils 封装 RedisTemplate,用于复杂缓存场景:
String 操作
// 设置值
redisUtils.set("key", value);
redisUtils.set("key", value, 30, TimeUnit.MINUTES);
// 获取值
Object value = redisUtils.get("key");
UserDTO user = redisUtils.get("key", UserDTO.class);
// 原子操作
redisUtils.increment("counter");
redisUtils.setIfAbsent("lock:order:123", "locked", 10, TimeUnit.SECONDS);
Hash 操作
redisUtils.hSet("user:1", "name", "张三");
redisUtils.hGetAll("user:1");
Set / List 操作
redisUtils.sAdd("tags", "java", "spring");
redisUtils.lPush("queue", task);
批量操作
// 批量获取(MGET)— 一次网络请求
List<Object> values = redisUtils.mGet(List.of("key1", "key2"));
// 批量删除
redisUtils.delete(List.of("key1", "key2"));
📋 缓存键命名
使用 CacheKeys 工具类统一管理:
// ✅ 推荐:使用 CacheKeys
String key = CacheKeys.userRolesKey(userId);
// ❌ 不推荐:硬编码
String key = "user:roles:" + userId;
命名规范
格式: {模块}:{实体}:{参数}
示例:
- user:roles:123
- role:detail:1
- article:list:page:1
🎯 使用场景选择
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 方法返回值缓存 | Spring Cache 注解 | 声明式,统一管理 |
| 批量操作 | RedisUtils | 支持 MGET/MSET |
| 复杂逻辑 | RedisUtils | 精确控制 |
| 分布式锁 | RedisUtils.setIfAbsent | 原子操作 |
⚠️ 注意事项
避免缓存穿透
// ✅ 使用 unless 条件,不缓存 null
@Cacheable(value = "user", key = "#id", unless = "#result == null")
public UserDTO getById(Long id) { }
设置过期时间
// ✅ 总是设置 TTL
redisUtils.set("key", value, 30, TimeUnit.MINUTES);
// ❌ 避免永不过期
redisUtils.set("key", value);
及时失效
// 更新数据时失效缓存
@CacheEvict(value = "user:detail", key = "#dto.id")
public boolean updateByDto(UserDTO dto) { }
📊 监控
Actuator 端点
# 查看缓存列表
curl http://localhost:8080/actuator/cache
# 清除指定缓存
curl -X DELETE http://localhost:8080/actuator/cache/user:roles
Spring Boot Admin
可视化监控:http://localhost:9000
📚 延伸阅读
- 缓存管理 API — 缓存管理接口测试