跳到主要内容

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


📚 延伸阅读