共享会话存储

这里的核心概念是:会话共享存储(shared session storage)

用户登录以后,服务器需要保存一些与该用户当前访问相关的状态,例如:

复制代码
session_id: abc123
user_id: 9527
is_logged_in: true
shopping_cart: [商品A, 商品B]
expires_at: 2026-08-09 18:00

这些数据统称为用户会话(Session)。

浏览器通常只保存一个 Session ID:

复制代码
Cookie: session_id=abc123

服务器收到请求后,再用这个 ID 从共享存储中查找完整的会话数据。

为什么需要共享存储?

假设系统有三台应用服务器:

复制代码
                 ┌→ 应用服务器 1
用户 → 负载均衡器 ├→ 应用服务器 2
                 └→ 应用服务器 3

如果会话只保存在服务器 1 的内存中:

  1. 用户登录请求被服务器 1 处理。
  2. 登录状态保存在服务器 1。
  3. 下一个请求被分配给服务器 2。
  4. 服务器 2 找不到会话,便认为用户没有登录。

共享存储让不同的应用服务器访问同一个数据存储系统。

"同一个共享存储"指的是同一个逻辑存储服务,不一定只有一台物理服务器。它也可能是 Redis 集群。

如果三台服务器都访问同一个会话存储,则无论请求落在哪台服务器上,都能取得相同的登录状态:

复制代码
应用服务器 1 ─┐
应用服务器 2 ─┼→ 共享会话存储
应用服务器 3 ─┘

无论用户请求被分配到哪台应用服务器,服务器都会访问同一个会话,所以能够获得相同的会话数据。通常系统会选定一个共享会话存储。

关于数据存储系统

  • 数据存储系统(Data Storage System):所有能够保存、读取和管理数据的系统的统称,范围很广,包括数据库、文件系统、对象存储和缓存等。
  • 数据库(Database):一种结构化管理数据的数据存储系统,通常提供查询、更新、索引、事务或持久化等能力。

数据存储系统

├── 关系型数据库:MySQL、PostgreSQL

├── NoSQL 数据库:MongoDB、Redis

├── 缓存系统:Memcached

├── 文件系统

└── 对象存储:Amazon S3

在这里比较四类常见共享存储的选择:

  • Redis:内存型键值数据存储,常用于共享会话和缓存。
  • Memcached:内存缓存系统,适合保存可以丢失或重新生成的临时会话数据。
  • 数据库:这里通常指关系型数据库,例如 MySQL、PostgreSQL,通过会话表保存数据。
  • 其他共享存储系统:指任何能被所有应用服务器共同访问的存储系统。

Redis

Redis 是以内存为主的键值数据存储,数据通常采用下面的形式:

复制代码
键:session:abc123
值:{
  "user_id": 9527,
  "is_logged_in": true
}

读取过程类似于:

复制代码
GET session:abc123

Redis 很适合保存会话,因为它具有以下特点:

  • 读取和写入速度快
  • 可以为会话设置自动过期时间
  • 支持持久化和复制
  • 支持字符串、哈希、列表和集合等数据结构
  • 比较容易构建高可用集群

例如,可以把会话设置为 30 分钟后过期:

复制代码
SET session:abc123 "会话数据" EX 1800

如果用户在规定时间内没有继续访问,Redis 会自动删除该会话。

Memcached

Memcached 也是以内存为主的键值缓存系统:

复制代码
键:session:abc123
值:序列化后的会话数据

它的主要特点是:

  • 模型非常简单
  • 读取和写入速度快
  • 支持数据过期
  • 容易水平扩展
  • 通常不负责持久化数据

Memcached 更像一个纯缓存。服务器重启、缓存被淘汰或节点发生故障时,会话数据可能消失,用户可能需要重新登录。

缓存(Cache)是位于数据使用者和原始数据源之间的一层高速临时存储,用来保存近期使用过或经常使用的数据副本。缓存通常保存可重新获取或重新计算的数据;但 Redis、Memcached 用作会话存储时,会话数据也可能只存在于其中。

Redis 和 Memcached 的主要区别可以概括为:

对比项 Redis Memcached
数据模型 多种数据结构 简单键值
持久化 支持 通常不支持
复制和高可用 支持 能力有限
数据过期 支持 支持
典型用途 会话、缓存、计数器、队列 简单高速缓存
会话丢失风险 可通过持久化和复制降低 相对更高

在现代系统中,Redis 通常是共享会话存储的常见选择。

数据库

也可以把会话保存在 MySQL、PostgreSQL 等关系型数据库中:

session_id user_id data expires_at
abc123 9527 {...} 2026-08-09 18:00

所有应用服务器都连接到这个数据库,因此都可以读取同一份会话。

优点包括:

  • 数据可以持久保存
  • 事务和一致性能力较强
  • 系统可能已经有数据库,不需要引入新组件
  • 运维方式比较熟悉

缺点包括:

  • 通常比内存存储慢
  • 大量会话读写会增加数据库压力
  • 会话的访问频率通常很高,可能影响核心业务查询
  • 需要定期清理过期记录

数据库适合规模较小的系统,或者会话不能轻易丢失的场景。随着访问量增加,通常会把会话迁移到 Redis 等独立存储。

其他共享存储

"其他共享存储"不是某一种特定产品,而是指任何能被所有应用服务器共同访问的存储系统,例如:

  • 分布式键值数据库
  • 云服务商提供的托管 Redis
  • 分布式缓存集群
  • 专用会话服务
  • 共享文件系统
  • 某些支持过期机制的 NoSQL 数据库

它们必须满足一个关键条件:应用服务器之间看到的是同一份会话数据。

共享文件系统理论上也能保存会话,但文件锁、并发访问、延迟和扩展性往往比较麻烦,通常不是首选。

应该怎样选择?

一般可以这样判断:

  • 小型应用:数据库足够简单实用。
  • 普通生产系统:通常选择 Redis。
  • 只需要高速临时缓存,并且允许用户偶尔重新登录:可以选择 Memcached。
  • 大规模或多地域系统:使用高可用 Redis 集群、分布式键值数据库或专门的会话服务。

这里最重要的并不是具体选择哪个产品,而是让应用服务器保持无状态:

复制代码
应用服务器不拥有会话
应用服务器只是读取和修改共享存储中的会话

这样,任何一台服务器都可以处理任何用户的请求,也可以随时增加、替换或关闭应用服务器。

相关推荐
万亿少女的梦1688 天前
基于Spring Boot、Java与MySQL的同城宠物服务系统设计与实现
java·spring boot·mysql·系统设计·协同过滤
书香门第10 天前
系统设计练习 - 分布式黑名单服务(design a distributed denylist service)
分布式·系统架构·系统设计
doiito14 天前
【Agent Harness】Gliding Horse 最新升级:把“智能闭环”真正跑通的一次深度优化
rust·架构设计·系统设计·ai agent
doiito18 天前
【Agent Harness】流马(Gliding Horse)DeepSeek Responses API 接入介绍
rust·系统设计·ai agent
万亿少女的梦16818 天前
基于微信小程序、Express与MongoDB的校园失物招领系统设计
mongodb·微信小程序·node.js·express·系统设计
doiito23 天前
【AI 推理】在 Rockchip NPU 上实现 MoE 大模型流式推理的技术方案
ai·系统设计
doiito1 个月前
【开源项目】开源智能排产系统深度研究报告(第一部分)
架构设计·系统设计
万亿少女的梦1681 个月前
基于Spring Boot的游戏交易管理系统设计与实现
java·spring boot·mysql·系统设计·交易管理
万亿少女的梦1681 个月前
基于PHP的碳排放减排管理系统设计与实现
mysql·数据分析·php·系统设计·碳排放