高 基础
分布式Session方案#
一句话答案#
推荐 Redis 集中存储 Session(简单高效),也可用 JWT Token(无状态但无法主动失效)。
核心要点
问题背景: 负载均衡下,同一客户端的多次请求可能被分发到不同服务器,服务器之间需要共享 Session 才能正确处理请求。
四种方案对比:
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 粘性 Session(Sticky Session) | 负载均衡器对源 IP 做哈希,同一 IP 始终路由到同一服务器 | 实现简单,无需改代码 | 服务器宕机则该 IP 用户 Session 全部丢失;负载不均衡 |
| Session 复制/同步 | 集群内通过广播同步 Session 数据,每台服务器都有全量 Session | Session 不丢失,任意节点可处理请求 | 同步开销大,集群规模受限;内存占用翻倍增长 |
| 集中式存储(推荐) | 用 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 → 热点问题plaintext方案二:Session 复制
实现:Tomcat 集群的 DeltaManager 广播同步
问题:
每新增一个 Session → 广播到 N-1 台机器 → O(N^2) 通信量
适合小集群(3~5 台),大规模集群不可用plaintext方案三: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 不随某台服务器宕机丢失plaintext方案四:JWT 无状态方案
流程:
1. 用户登录 → 服务端生成 JWT Token(包含用户 ID、角色、过期时间等)
2. 返回 Token 给客户端(存 Cookie / LocalStorage)
3. 客户端每次请求携带 Token(Header: Authorization: Bearer xxx)
4. 服务端验证 Token 签名 → 提取用户信息 → 无需查 Session
优势:完全无状态,服务端不存储任何东西
劣势:Token 无法主动失效(除非引入黑名单机制,又回到有状态)plaintext推荐方案:Redis 集中存储 + JWT 结合
JWT 存放轻量信息(用户 ID、角色),用于鉴权
需要存储的会话数据(购物车、用户偏好等)放 Redis
兼顾无状态的可扩展性和服务端数据管理的灵活性plaintext面试回答(2分钟版)
分布式环境下负载均衡会把同一用户的请求分发到不同服务器,如果 Session 存在单台服务器上就会出现会话丢失。常见有四种方案:第一是粘性 Session,通过 Nginx 的 ip_hash 让同一 IP 始终路由到同一台机器,简单但服务器宕机则该用户 Session 全丢。第二是 Session 复制,集群内广播同步所有 Session 数据,但同步开销是 O(N^2),只适合小集群。第三是 Redis 集中存储,这是最推荐的方案,用 Spring Session + Redis 把所有 Session 统一存到 Redis,服务器完全无状态可以随意水平扩展,Session 也不会因某台机器宕机而丢失。第四是 JWT 无状态方案,服务端签发 Token 客户端每次请求自带,完全无状态但 Token 无法主动失效。最佳实践是两者结合:JWT 存放轻量的身份信息用于鉴权,需要管理的会话数据如购物车、偏好等放 Redis,兼顾无状态的扩展性和服务端数据管理的灵活性。
追问与易错
追问方向:
- “JWT 怎么让 Token 失效?”→ JWT 本身无法主动失效(无状态),变通方案:短过期时间(如 15 分钟)+ Redis 维护黑名单(注销时将 Token 加入黑名单直到过期)
- “Redis Session 挂了怎么办?”→ Redis 部署主从 + Sentinel 哨兵保证高可用,或用 Redis Cluster;极端情况 Redis 全挂则降级为 JWT 无状态模式
- “JWT Token 太大影响性能吗?”→ 会,JWT 包含 Header+Payload+Signature 通常 300~500 字节,每次请求都携带增加带宽开销,应只存必要信息(用户 ID、角色)不存大量业务数据
易错点:
- ❌ JWT 就是安全的——不做加密不应放敏感信息
- ❌ Redis Session 和 JWT 选一个——可以结合