本文目录导读:

我将详细介绍SpringBoot集成Redis实现缓存的完整方案。
添加依赖
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池依赖(可选但推荐) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- JSON序列化支持 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
配置文件
application.yml
spring:
redis:
host: localhost
port: 6379
password:
database: 0
timeout: 10000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: -1ms
cache:
type: redis
redis:
time-to-live: 3600000ms # 默认缓存过期时间1小时
cache-null-values: false # 是否缓存空值
Redis配置类
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// JSON序列化配置
Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSerializer.setObjectMapper(om);
// String序列化配置
StringRedisSerializer stringSerializer = new StringRedisSerializer();
// key使用String序列化
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// value使用JSON序列化
template.setValueSerializer(jacksonSerializer);
template.setHashValueSerializer(jacksonSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
}
缓存注解使用
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String email;
private Integer age;
}
Service层实现缓存
@Service
@Slf4j
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 使用@Cacheable注解实现缓存
*/
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
log.info("查询数据库获取用户: {}", id);
return userMapper.findById(id);
}
/**
* 根据条件缓存
*/
@Cacheable(value = "users", key = "#username",
condition = "#username.length() > 3")
public User getUserByUsername(String username) {
log.info("查询数据库获取用户: {}", username);
return userMapper.findByUsername(username);
}
/**
* 使用@CachePut更新缓存
*/
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
log.info("更新用户信息: {}", user);
userMapper.update(user);
return user;
}
/**
* 使用@CacheEvict删除缓存
*/
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
log.info("删除用户: {}", id);
userMapper.deleteById(id);
}
/**
* 清除所有用户缓存
*/
@CacheEvict(value = "users", allEntries = true)
public void clearAllUserCache() {
log.info("清除所有用户缓存");
}
/**
* 组合使用注解
*/
@Caching(
cacheable = {
@Cacheable(value = "users", key = "#username")
},
put = {
@CachePut(value = "users", key = "#result.id",
condition = "#result != null")
}
)
public User findOrCreateUser(String username) {
User user = userMapper.findByUsername(username);
if (user == null) {
user = new User();
user.setUsername(username);
userMapper.insert(user);
}
return user;
}
}
手动操作Redis
@Service
@Slf4j
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 字符串操作
public void setValue(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public void setValueWithExpire(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
public Object getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
// List操作
public void leftPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
public Object rightPop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
public List<Object> getList(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
// Set操作
public void addToSet(String key, Object... values) {
redisTemplate.opsForSet().add(key, values);
}
public Set<Object> getSetMembers(String key) {
return redisTemplate.opsForSet().members(key);
}
// Hash操作
public void hashPut(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
public Object hashGet(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
public Map<Object, Object> hashGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
// 分布式锁
public boolean tryLock(String key, String value, long expireTime) {
return Boolean.TRUE.equals(
stringRedisTemplate.opsForValue()
.setIfAbsent(key, value, expireTime, TimeUnit.SECONDS)
);
}
public void unlock(String key, String value) {
String currentValue = stringRedisTemplate.opsForValue().get(key);
if (currentValue != null && currentValue.equals(value)) {
stringRedisTemplate.delete(key);
}
}
// 删除操作
public boolean delete(String key) {
return Boolean.TRUE.equals(redisTemplate.delete(key));
}
public long deletePattern(String pattern) {
Set<String> keys = redisTemplate.keys(pattern);
if (keys != null && !keys.isEmpty()) {
return redisTemplate.delete(keys);
}
return 0;
}
// 过期时间操作
public boolean expire(String key, long timeout, TimeUnit unit) {
return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
}
public long getExpire(String key) {
return redisTemplate.getExpire(key);
}
}
Controller示例
@RestController
@RequestMapping("/api/users")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisService redisService;
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return Result.success(user);
}
@PostMapping
public Result<User> createUser(@RequestBody User user) {
// 手动缓存
redisService.setValueWithExpire(
"user:" + 1,
user,
1,
TimeUnit.HOURS
);
return Result.success(user);
}
@PutMapping
public Result<User> updateUser(@RequestBody User user) {
return Result.success(userService.updateUser(user));
}
@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return Result.success();
}
}
高级配置
自定义Key生成器
@Component
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder key = new StringBuilder();
key.append(target.getClass().getSimpleName()).append(":");
key.append(method.getName()).append(":");
for (Object param : params) {
if (param != null) {
key.append(param.toString()).append("_");
}
}
return key.toString().replaceAll("_$", "");
}
}
自定义缓存异常处理
@Component
@Slf4j
public class RedisCacheErrorHandler implements CacheErrorHandler {
@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
log.error("Redis GET error - cache: {}, key: {}", cache.getName(), key, exception);
}
@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
log.error("Redis PUT error - cache: {}, key: {}", cache.getName(), key, exception);
}
@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
log.error("Redis EVICT error - cache: {}, key: {}", cache.getName(), key, exception);
}
@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
log.error("Redis CLEAR error - cache: {}", cache.getName(), exception);
}
}
缓存策略建议
-
缓存穿透防护:
- 使用布隆过滤器
- 缓存空对象(设置较短的过期时间)
-
缓存雪崩防护:
- 设置不同的过期时间
- 使用缓存预热
- 使用多级缓存
-
缓存击穿防护:
- 使用互斥锁
- 热点数据设置永不过期
-
性能优化:
- 合理设置序列化方式
- 使用连接池
- 批量操作使用pipeline
这个方案提供了完整的Redis缓存集成方案,包括注解缓存和手动缓存操作,可以根据实际需求选择合适的实现方式。