前言
在传统的单体应用中,所有用户请求都由同一台服务器处理,会话(Session)信息通常保存在服务器内存中即可。
客户端第一次登录后,服务端会创建一个 Session 并生成 SessionId,保存在服务端内存中,同时将 SessionId 通过 Cookie 返回给客户端。之后客户端的每次请求都会携带该 SessionId,服务端即可识别用户的登录状态。
然而,随着业务规模扩大和访问量增加,单台服务器已无法承受高并发请求,我们往往会采用 Nginx + 多台应用服务器 的负载均衡方式进行水平扩展。
此时,Session 共享问题便随之出现。
问题分析:为什么会出现 Session 丢失?
假设现在有两台后端服务器:
- Server A
- Server B
前端请求通过 Nginx 负载均衡随机分配给这两台服务器。
- 用户第一次登录请求被分配到 Server A;
- Server A 处理登录逻辑,生成
SessionId = ABC123并保存在本机内存; - 响应返回后,浏览器在 Cookie 中保存该 SessionId;
- 用户的第二次请求被 Nginx 分配到 Server B;
- Server B 收到请求时,会去本机内存中查找 SessionId = ABC123;
- 然而 Server B 并没有这个 Session,因此无法识别用户身份。
结果就是:用户会被系统强制登出,需要重新登录。
这种现象即为Session 不共享问题。在分布式架构中,每台服务器都有独立的内存空间,如果 Session 保存在本地,就会出现用户登录态无法跨服务器识别的情况。
解决方案:分布式 Session
既然问题的根本在于 Session 只保存在本机内存中,那么解决方案自然是:
将 Session 从本地内存中“抽离”,放到一个所有服务器都能访问的公共存储中。
常见的共享方案包括:
| 方案 | 优点 | 缺点 |
|---|---|---|
| Session 粘滞(Sticky Session) | 配置简单(Nginx 层绑定同一用户请求到同一服务器) | 无法应对服务器宕机、扩容不灵活 |
| Session 复制 | 各节点自动同步 Session | 实现复杂,扩展性差 |
| 集中式 Session 存储(Redis、Memcached) | 高性能、易扩展、实现简单 | 需依赖外部缓存系统 |
在实际生产中,将 Session 存储到 Redis 是最常见且稳定的方案。
Redis 分布式 Session 实现方案
Redis 作为高性能的内存数据库,支持多种数据结构、持久化、主从同步与集群部署,非常适合用作分布式 Session 存储。
实现步骤
1. 登录时创建 Session
- 用户登录成功后,服务端生成一个随机的 Token(可用 UUID 生成)。
1 | String token = UUID.randomUUID().toString(); |
- 将用户信息(如 userId、username 等)保存到 Redis:
1 | redisTemplate.opsForValue().set("session:" + token, userInfo, 30, TimeUnit.MINUTES); |
- 将该 Token 返回给客户端,保存在 Cookie 或 Header 中。
2. 请求拦截与 Session 校验
每次用户请求接口时:
前端携带 Token(Cookie 或 Header 中传递)。
服务端通过拦截器或过滤器读取 Token。
校验 Redis 中是否存在对应的 Session:
1 | String token = request.getHeader("Authorization"); |
- 如果存在,则刷新 Redis 过期时间(保持用户活跃登录状态)。
实战案例:Spring Boot + Redis 实现分布式 Session
1. 环境准备
- Spring Boot 3.x
- Redis 7.x
- Nginx(负载均衡)
2. 项目配置示例
application.yml
1 | spring: |
3. 登录接口实现
1 |
|
4. 拦截器实现 Session 校验
1 |
|
5. 注册拦截器
1 |
|
效果验证
在 Nginx 中配置两台服务器轮询访问:
1 | upstream backend { |
用户登录后访问多次接口,即使请求被分配到不同服务器,也不会丢失登录态,说明 Session 已实现分布式共享。
架构示意图
1 | ┌────────────┐ |
总结
本文从传统单体 Session 管理出发,逐步分析了分布式环境下的 Session 共享问题,并结合 Redis 给出了完整解决方案与实战案例,希望能帮助你在分布式架构实践中少踩坑。
文章信息
| 时间 | 说明 |
|---|---|
| 2019-04-20 | 初稿 |