session共享必须用redis等外部存储,因集群下各应用服务器内存session独立导致登录态丢失;spring boot需配置spring-session-data-redis、redis连接及@enableredishttpsession,并注意序列化、ttl、高可用与cookie传递。

Session 共享必须用外部存储,Redis 是最常用且可靠的选择;直接依赖应用服务器内置 Session(如 tomcat 默认内存存储)在集群下必然失效。
为什么不能靠应用服务器自己管 Session
多个实例启动后,每个进程的内存里都有一份独立 HttpSession,用户请求被负载均衡随机打到不同节点时,session.getId() 相同但内容不一致,登录态、购物车等数据直接丢失。这不是配置问题,是架构限制。
常见错误现象包括:
- 用户刚登录就跳转回登录页
- 刷新页面后
request.getSession().getAttribute("user")返回NULL - 同一浏览器开两个标签,一个登出另一个还显示已登录
spring boot + Redis 实现 Session 共享的关键配置
核心依赖是 spring-session-data-redis,它会自动替换默认的 HttpSession 实现,把读写委托给 Redis。
需要确认以下几点:
- 确保引入了
spring-boot-starter-data-redis和spring-session-data-redis(后者 3.x 版本起已不再需要额外 starter,但需显式启用) - 在
application.yml中配置 Redis 连接:spring: redis: host: 127.0.0.1 port: 6379 database: 0 timeout: 5000 session: store-type: redis timeout: 1800 - 加一个
@EnableRedisHttpSession配置类(Spring Boot 2.7+ 可省略,但建议保留以明确控制 maxInactiveInterval):@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) public class SessionConfig { } - 注意:Redis 中的 key 默认前缀是
spring:session:,可通过redisNamespace参数修改,避免多环境混用
Redis 存储结构和常见踩坑点
Session 数据不是简单存成字符串,而是序列化为 byte[] 存入 Redis 的 Hash 结构中,主 key 是 spring:session:sessions:<sessionid></sessionid>,其中包含 sessionAttr:xxx 字段存属性,creationTime、lastAccessedTime 等元数据。
容易出问题的地方:
-
java.io.NotSerializableException:存进 Session 的对象必须实现Serializable,否则序列化失败,Redis 写入为空,后续取值始终为null - Redis 内存爆满:Session 过期依赖 Redis 的 TTL,但如果用了
RedisTemplate自定义序列化器且没配对,可能导致 TTL 设置失败,过期不清理 - 集群环境下未配置 Redis sentinel 或 Cluster:单点 Redis 故障会导致全站 Session 不可用,生产必须用高可用部署
- 前端未携带
JSESSIONIDCookie:如果反向代理(如 nginx)或前端框架清除了 Cookie,Session ID 传不到后端,Redis 查不到对应记录
真正麻烦的不是配置几行代码,而是验证它是否真的生效——得用多实例 + 负载均衡 + 抓包看 Cookie 是否复用,再查 Redis key 是否随请求实时更新。很多“配好了”的人其实只测了单机。