Skip to content
基础

一句话答案

推荐 Redis 集中存储 Session(简单高效),也可用 JWT Token(无状态但无法主动失效)。

核心要点

问题背景: 负载均衡下,同一客户端的多次请求可能被分发到不同服务器,服务器之间需要共享 Session 才能正确处理请求。

四种方案对比:

方案原理优点缺点
粘性 Session(Sticky Session)负载均衡器对源 IP 做哈希,同一 IP 始终路由到同一服务器实现简单,无需改代码服务器宕机则该 IP 用户 Session 全部丢失;负载不均衡
Session 复制/同步集群内通过广播同步 Session 数据,每台服务器都有全量 SessionSession 不丢失,任意节点可处理请求同步开销大,集群规模受限;内存占用翻倍增长
集中式存储(推荐)用 Redis / 数据库集中存储 Session,所有服务器读写同一存储扩展性好,服务器无状态;Session 不随服务器宕机丢失依赖外部存储的可用性;增加一次网络 IO
客户端存储将 Session 数据存在 Cookie 中(或使用 JWT),客户端每次请求自带服务端完全无状态,扩展性最好Cookie 大小限制(4KB);安全性低(数据在客户端);无法服务端主动失效

方案一:粘性 Session(Sticky Session)

实现:Nginx 的 ip_hash 指令

upstream backend {
    ip_hash;       # 同一 IP 固定路由到同一后端
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

问题:
  ① 服务器宕机 → 该服务器上的所有 Session 丢失
  ② 某些 IP 段请求量大 → 负载不均
  ③ 客户端使用代理时,大量用户共享同一 IP → 热点问题

方案二:Session 复制

实现:Tomcat 集群的 DeltaManager 广播同步

问题:
  每新增一个 Session → 广播到 N-1 台机器 → O(N^2) 通信量
  适合小集群(3~5 台),大规模集群不可用

方案三:Redis 集中存储(推荐)

实现:Spring Session + Redis

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
    // Spring 自动将 HttpSession 存储到 Redis
}

Redis 中存储结构:
  Key:   spring:session:sessions:<sessionId>
  Value: Hash(属性名 → 属性值)
  TTL:   30 分钟(可配置)

优势:
  ✅ 服务器完全无状态,随时水平扩展
  ✅ Redis 高性能(内存存储 + 主从高可用)
  ✅ Session 不随某台服务器宕机丢失

方案四:JWT 无状态方案

流程:
  1. 用户登录 → 服务端生成 JWT Token(包含用户 ID、角色、过期时间等)
  2. 返回 Token 给客户端(存 Cookie / LocalStorage)
  3. 客户端每次请求携带 Token(Header: Authorization: Bearer xxx)
  4. 服务端验证 Token 签名 → 提取用户信息 → 无需查 Session

优势:完全无状态,服务端不存储任何东西
劣势:Token 无法主动失效(除非引入黑名单机制,又回到有状态)

推荐方案:Redis 集中存储 + JWT 结合

JWT 存放轻量信息(用户 ID、角色),用于鉴权
需要存储的会话数据(购物车、用户偏好等)放 Redis
兼顾无状态的可扩展性和服务端数据管理的灵活性
追问与易错

追问方向:

  • JWT 怎么让 Token 失效?
  • Redis Session 挂了怎么办?
  • JWT Token 太大影响性能吗?

易错点:

  • ❌ JWT 就是安全的——不做加密不应放敏感信息
  • ❌ Redis Session 和 JWT 选一个——可以结合

💡 记忆锚点

四种方案像存行李:粘性Session=每次去同一个柜子(柜子坏了行李没了);Session复制=每个柜子都放一份(浪费空间);Redis集中存储=寄存处统一保管(推荐,服务器无状态随便扩);JWT=行李自己背(无状态但不能远程锁箱子)。最佳实践:JWT做身份证+Redis存行李。