共享会话存储

这里的核心概念是:会话共享存储(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 集群、分布式键值数据库或专门的会话服务。

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

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

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

相关推荐
記億揺晃着的那天10 天前
Amazon SP-API 报告创建全流程与状态机:从创建、轮询到下载入库,新手避坑指南
api·架构设计·系统设计·amazon api·sp-api
梁辰兴15 天前
软件工程:系统设计
软件工程·设计原则·系统设计·设计工具·设计方法·梁辰兴·设计阶段
郝学胜-神的一滴18 天前
《C++11 工程级应用01:告别冗长类型,开启简洁高效编码新时代》深度解读
开发语言·c++·算法·软件开发·系统设计
thesky12345619 天前
智能体面试准备(五十二):大厂面试实战——系统设计/简历包装/30天冲刺
大厂面试·系统设计·智能体·面试实战·简历包装·30天冲刺·axb协同
万亿少女的梦1681 个月前
基于Spring Boot、Java与MySQL的同城宠物服务系统设计与实现
java·spring boot·mysql·系统设计·协同过滤
书香门第1 个月前
系统设计练习 - 分布式黑名单服务(design a distributed denylist service)
分布式·系统架构·系统设计
doiito1 个月前
【Agent Harness】Gliding Horse 最新升级:把“智能闭环”真正跑通的一次深度优化
rust·架构设计·系统设计·ai agent
doiito1 个月前
【Agent Harness】流马(Gliding Horse)DeepSeek Responses API 接入介绍
rust·系统设计·ai agent
万亿少女的梦1681 个月前
基于微信小程序、Express与MongoDB的校园失物招领系统设计
mongodb·微信小程序·node.js·express·系统设计