如何为Redis持久化的Spring Session启用本地缓存?
Spring Session Redis 本地二级缓存实现方案
核心思路
为Spring Session会话数据添加本地二级缓存,实现先查本地缓存,未命中再查Redis的逻辑,同时保证本地缓存与Redis数据的一致性。针对你之前出现的StatefulRedisConnection缺失问题,可通过Spring Data Redis的LettuceConnectionFactory获取原生连接来构建Lettuce的CacheFrontend。
具体实现步骤
1. 完善Redis配置类,添加本地缓存相关Bean
保留你原有的redisConnectionFactory配置,新增以下Bean实现二级缓存逻辑:
@Configuration(proxyBeanMethods = false) @EnableRedisHttpSession public class RedisConfig { // 原有的redisConnectionFactory方法保持不变 @Bean LettuceConnectionFactory redisConnectionFactory() throws Exception { // 你的原有代码省略 } // 获取Lettuce原生连接,解决StatefulRedisConnection缺失问题 @Bean StatefulRedisConnection<String, Object> statefulRedisConnection(LettuceConnectionFactory connectionFactory) { return connectionFactory.getNativeConnection(); } // 构建二级缓存前端:本地缓存(Caffeine) + Redis后端 @Bean CacheFrontend<String, Object> sessionCacheFrontend(StatefulRedisConnection<String, Object> connection) { // 本地缓存配置:最大1000条,30分钟无访问过期 Cache<String, Object> localCache = Caffeine.newBuilder() .maximumSize(1000) .expireAfterAccess(Duration.ofMinutes(30)) .build(); // Redis缓存后端 RedisCache<String, Object> redisCache = RedisCache.create(connection.sync()); // 组合二级缓存:优先查本地,未命中自动查Redis并同步到本地 return CacheFrontend.compose(localCache, redisCache); } // 自定义RedisTemplate,封装二级缓存操作 @Bean @Primary // 让Spring Session优先使用该模板 RedisTemplate<String, Object> sessionRedisTemplate(LettuceConnectionFactory connectionFactory, CacheFrontend<String, Object> cacheFrontend) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 替换默认ValueOperations为带二级缓存的实现 template.setValueOperations(new CachingValueOperations(template, cacheFrontend)); return template; } // 自定义ValueOperations,整合CacheFrontend的缓存逻辑 static class CachingValueOperations extends DefaultValueOperations<String, Object> { private final CacheFrontend<String, Object> cacheFrontend; public CachingValueOperations(RedisTemplate<String, Object> template, CacheFrontend<String, Object> cacheFrontend) { super(template); this.cacheFrontend = cacheFrontend; } @Override public Object get(Object key) { try { return cacheFrontend.get((String) key); } catch (CacheLoader.ValueRetrievalException e) { return null; } } @Override public void set(String key, Object value) { cacheFrontend.put(key, value); } @Override public void delete(Object key) { cacheFrontend.remove((String) key); } } }
2. 配置本地缓存依赖(以Caffeine为例)
在Maven的pom.xml中添加Caffeine依赖:
<dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
3. 验证逻辑
- 会话读取:首次读取会从Redis加载并写入本地缓存,后续读取直接命中本地缓存
- 会话更新/删除:操作会同时同步到本地缓存和Redis,保证数据一致性
关键细节说明
CacheFrontend.compose自动实现了二级缓存的读写逻辑,无需手动处理缓存同步- 自定义
CachingValueOperations让Spring Session的会话操作无缝适配二级缓存,无需修改业务代码 - 通过
LettuceConnectionFactory.getNativeConnection()获取原生连接,解决了之前的StatefulRedisConnection缺失异常
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

