spring session在redis中“看似同步延迟”实为配置错误:sessionrepositoryfilter未前置导致绕过redis、expires key缺失或序列化不一致,只要sessionid存在、可反序列化且expires key存活,同步即为即时原子操作。

Spring Boot集群部署时,Spring Session在Redis中“看似同步延迟”,其实绝大多数情况根本不是延迟,而是会话未真正写入或读取路径被绕过——问题常出在过滤器链顺序、序列化不一致、或Redis写操作未落库。
SessionRepositoryFilter 是否在 DispatcherServlet 之前执行
这是最隐蔽也最高频的问题:SessionRepositoryFilter必须包裹整个请求生命周期,否则 HttpServletRequest.getSession() 拿到的是容器默认的内存 Session,压根没走 Redis。
- 检查
spring-session-data-redis是否启用(如存在@EnableSpringHttpSession或spring.session.store-type=redis) - 确认没有手动注册其他
Filter并设了@Order(Ordered.HIGHEST_PRECEDENCE),把SessionRepositoryFilter挤到了后面 - 在调试模式下打个断点进
SessionRepositoryFilter.doFilterInternal(),看它是否对每个请求都触发;如果只在登录/首次请求触发,说明后续请求被其他 Filter 或静态资源路径(如/actuator/**、/webjars/**)跳过了
Redis 写入是否成功但未触发 expires key
Spring Session 3.x 依赖两个 Key 协同工作:spring:session:sessions:{sessionId}(Hash)存数据,spring:session:sessions:expires:{sessionId}(String)设 TTL。后者缺失,会导致会话永不超时,且部分客户端(如小程序 WebView)因 Cookie 过期逻辑异常,误判为“状态不同步”。
- 用
redis-cli手动查:exists spring:session:sessions:expires:abc123,再查ttl spring:session:sessions:expires:abc123 - 若
exists返回 0,说明SessionRepository.save()调用失败,或被事务回滚吞掉(比如在@Transactional方法里修改 session 属性后抛异常) - 若
ttl返回 -1,说明 Redis 写入时没带过期时间——常见于自定义RedisOperationsSessionRepository时漏配defaultRedisOperations的序列化器,导致setEx命令降级为set
序列化器不一致导致读取失败
集群节点 A 用 GenericJackson2JsonRedisSerializer 写入,节点 B 却用默认的 JdkSerializationRedisSerializer 尝试反序列化,结果静默失败,getSession() 返回新会话 —— 表现为“刚登录就掉线”、“多端状态不一致”。
- 检查所有节点的
RedisTemplate配置是否统一:必须显式设置setDefaultSerializer(new GenericJackson2JsonRedisSerializer()) - 特别注意:若用了
@Bean RedisOperationsSessionRepository自定义 Bean,它内部持有的RedisOperations必须复用全局配置好的模板,不能 new 一个没配序列化器的 - 验证方式:在 Redis 中直接
hgetall spring:session:sessions:xxx,看 value 是 JSON 字符串还是乱码二进制;前者正常,后者就是序列化错配
真正需要盯住的,不是“延迟多少毫秒”,而是“这个 sessionId 在 Redis 里有没有、能不能被正确反序列化、对应的 expires key 是否存活”。只要这三个条件满足,Spring Session 的同步就是即时的——它本质是读写 Redis 的原子操作,不涉及跨节点同步等待。











