Redission与Satoken整合时Redis数据库配置的那些坑(附完整解决方案)
Redission与Satoken整合时Redis数据库配置的那些坑(附完整解决方案)
当你在Spring Boot项目中同时使用Redission和Satoken时,Redis数据库配置可能会成为一个隐藏的"定时炸弹"。我就曾踩过这样的坑——明明所有配置看起来都正确,线上环境却突然出现所有用户登录状态失效的诡异现象。经过一番排查,发现问题竟然出在两个框架对Redis数据库配置的读取方式差异上。
1. 问题现象与初步排查
那天早上,我们刚把修改了Redis database配置的服务部署到线上,噩梦就开始了。用户反馈登录后系统频繁跳转回登录页面,查看Redis数据库发现token确实存在,但系统就是无法识别。以下是当时观察到的具体现象:
- 本地环境(database=0)一切正常
- 线上环境(database=1)登录状态无法保持
- Redis中确实存在token数据
- 服务重启后问题依旧
使用以下命令检查Redis数据存储情况时,确认数据确实写入了database 1:
redis-cli -n 1 keys *2. 深度问题分析
2.1 配置冲突的根源
问题的核心在于Spring Boot项目中存在两套Redis客户端配置:
Spring Data Redis:通过
application.properties配置spring.data.redis.database=1 spring.data.redis.host=127.0.0.1 spring.data.redis.port=6379Redission客户端:需要单独配置
@Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer() .setAddress("redis://localhost:6379") // 缺少database配置,默认使用0 .setPassword("password"); return Redisson.create(config); }
2.2 Satoken的工作机制
Satoken默认使用Spring Data Redis的RedisTemplate进行操作,但当项目中同时存在Redission时,可能会发生以下情况:
| 组件 | 配置来源 | 默认database | 影响范围 |
|---|---|---|---|
| Spring Data Redis | application.properties | 按配置 | Satoken鉴权 |
| Redission | 独立Java配置 | 0(如未显式设置) | 分布式锁等 |
3. 完整解决方案
3.1 统一Redission配置
确保Redission使用与Satoken相同的database配置:
@Configuration public class RedissonConfig { @Value("${spring.data.redis.host}") private String host; @Value("${spring.data.redis.port}") private String port; @Value("${spring.data.redis.database}") private int database; @Value("${spring.data.redis.password}") private String password; @Bean(destroyMethod = "shutdown") public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer() .setAddress("redis://" + host + ":" + port) .setPassword(password) .setDatabase(database); // 关键配置 return Redisson.create(config); } }3.2 验证配置生效
创建测试端点验证Redis连接使用的database:
@RestController public class RedisCheckController { @Autowired private RedissonClient redissonClient; @GetMapping("/check-redis") public String checkRedisConfig() { return "当前Redission使用的database: " + redissonClient.getConfig().useSingleServer().getDatabase(); } }4. 进阶配置建议
4.1 多数据源场景处理
当项目需要连接多个Redis实例时,建议采用以下结构:
src/main/resources ├── application.yml └── redis ├── redisson-config.yml └── satoken-redis-config.yml对应的Java配置:
@Configuration @ConfigurationProperties(prefix = "satoken.redis") public class SaTokenRedisConfig { private int database; private String host; private int port; // getters & setters @Bean(name = "saTokenRedisTemplate") public RedisTemplate<String, Object> saTokenRedisTemplate() { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory()); return template; } @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName(host); config.setPort(port); config.setDatabase(database); return new LettuceConnectionFactory(config); } }4.2 配置检查清单
部署前务必确认以下事项:
- [ ] Redission配置中的database与Satoken一致
- [ ] 测试环境与生产环境配置同步
- [ ] Redis服务端已创建目标database
- [ ] 防火墙规则允许访问指定端口
5. 常见问题排查指南
遇到问题时,可以按照以下步骤排查:
确认Redis连接信息
// 获取Redission当前配置 redissonClient.getConfig().useSingleServer().getAddress(); redissonClient.getConfig().useSingleServer().getDatabase();检查Satoken存储情况
// 获取当前会话token String tokenValue = SaHolder.getStorage().getSaToken(); // 检查Redis中是否存在 redisTemplate.opsForValue().get(tokenValue);网络连通性测试
telnet redis-host 6379权限验证
redis-cli -h host -p port -a password
6. 性能优化建议
在解决基础配置问题后,还可以考虑以下优化措施:
连接池配置:
config.useSingleServer() .setConnectionPoolSize(64) .setConnectionMinimumIdleSize(24) .setIdleConnectionTimeout(10000);序列化优化:
@Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; }监控集成:
<!-- pom.xml --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.17.0</version> </dependency>
在实际项目中,我们最终采用了配置中心动态刷新的方案,使得Redis配置可以在不重启服务的情况下进行更新。这个方案虽然增加了初期实现的复杂度,但为后续的运维工作带来了极大便利。
