Session 共享不是加个 Redis 就行:一次登录态串号事故,和 4 种方案的真实取舍
title: Session 共享不是加个 Redis 就行一次登录态串号事故和 4 种方案的真实取舍tags: Session, Redis, 分布式, Spring Session, JWTdescription: 从一次用户 A 看到用户 B 数据的串号事故出发拆解 Session 复制、Cookie、集中存储、JWT 四种共享方案的适用边界以及 Spring Session 落地的真实坑。去年我们线上出过一个特别诡异的工单用户投诉我明明登录的是自己的账号刷新一下却变成了别人的名字。一开始我们以为是前端 bug查了三天才定位到——是 Session 共享那一层出了岔子。这篇文章把四种 Session 共享方案拆开讲重点是我不希望你踩的那几个坑。先给不熟悉的兄弟补一句背景传统的HttpSession默认存在应用服务器本地内存里。单体时代没问题但一旦上了负载均衡、应用起了多个实例用户第一次请求打到机器 A 登录第二次请求被轮询到机器 BB 上根本没有这个 Session于是又让你重新登录甚至更糟——读到 B 上残留的别人 Session。方案一Session 复制tomcat cluster早期最粗暴的做法让多个 Tomcat 互相广播 Session。配置一下Cluster节点就能用。!-- tomcat server.xml 里开启 DeltaManager 做 Session 复制 -- Cluster classNameorg.apache.catalina.ha.tcp.SimpleTcpCluster Manager classNameorg.apache.catalina.ha.session.DeltaManager expireSessionsOnShutdownfalse notifyListenersOnReplicationtrue/ !-- 复制的其实是序列化后的 Session 对象节点越多网络广播量越大 -- /Cluster逐行看DeltaManager只同步增量变更比全量广播好一点但本质还是把每个 Session 序列化后在节点间互发。我们的教训是当节点数超过 4 个、Session 里又塞了胖对象广播流量直接把内网带宽吃满。我不建议新项目用这个方案它和加机器是反向的——机器越多越慢而且 Session 里对象稍有不可序列化就直接报错。方案二客户端 Cookie 存状态把状态加密后直接写进 Cookie服务端无状态。好处是天然支持横向扩展坏处是体积受限Cookie 一般 4KB 上限且每次请求都带在头上。// 把少量登录信息签名后写 Cookie public void writeSessionCookie(HttpServletResponse resp, LoginUser user) { String payload user.getUserId() | user.getRole(); // 1. 用 HMAC 签名防止客户端篡改绝不只是 Base64 String signed payload . hmacSha256(payload, SECRET_KEY); Cookie c new Cookie(SESSION, Base64.getUrlEncoder().encodeToString(signed.getBytes())); c.setHttpOnly(true); // 2. 防 XSS 偷 Cookie c.setSecure(true); // 3. 只走 HTTPS c.setMaxAge(1800); // 4. 半小时过期和服务端逻辑对齐 resp.addCookie(c); }第 4 行的hmacSha256是重点Cookie 方案最大的雷是只编码不签名我见过有人直接 Base64 把 userId 塞进去前端把userId1001改成1002就串号了。签名 HttpOnlySecure这三件套缺一不可。这套方案适合登录态很薄的场景一旦要存一堆权限、购物车Cookie 装不下就得换。方案三集中存储Spring Session Redis这是现在最主流的方案spring-session-data-redis帮你把HttpSession透明地搬到 Redis业务代码几乎零改动。EnableRedisHttpSession(maxInactiveIntervalInSeconds 1800) Configuration public class SessionConfig { // 1. 默认用 Lettuce 连接 Redis注意连接池必须配否则高并发下拿不到连接 Bean public LettuceConnectionFactory connectionFactory() { LettucePoolingClientConfiguration pool LettucePoolingClientConfiguration.builder() .poolConfig(new GenericObjectPoolConfig() {{ setMaxTotal(200); setMaxIdle(50); setMinIdle(10); }}).build(); return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redis-1, 6379), pool); } } // 业务代码完全不用改继续用原生 HttpSession GetMapping(/cart) public Cart getCart(HttpSession session) { return (Cart) session.getAttribute(cart); // 实际读写都走 Redis }EnableRedisHttpSession是魔法入口它用一个SessionRepositoryFilter拦截请求把你代码里的HttpSession偷偷替换成 Redis -backed 的实现。第 9 行那个连接池配置是我们用血换来的——Spring Session 默认的连接工厂没有池化QPS 一上来RedisConnection直接被借光线程全阻塞在等连接上表现就是接口超时飙红。串号事故Redis 超时回退到本地撞了别人的 Session那次工单的根因就在这。我们的 Redis 连接池当时设的maxTotal20某天 Redis 因为一次大 key 删除卡了 2 秒连接池被瞬间借空。Spring Session 拿不到 Redis 连接时没有报错而是静默回退到了本地 Map 存 Session这是个隐藏行为文档里写得很隐晦。后果是用户登录在 A 实例创建了本地 Session负载均衡下一跳到了 B 实例B 也有自己的本地 Session 池。更致命的是我们当时为了省内存Session 的 key 用的是JSESSIONID而本地 Map 的 key 空间和 Redis 的 key 空间没有隔离。两个实例本地都生成了同名JSESSIONID的概率为 0但问题出在另一个地方——我们的 nginx 当时配了ip_hash失效请求乱跳而本地 Session 回退后getAttribute偶尔读到的是另一个用户上次残留的本地对象。修复三件事把 Redis 连接池调大到 200 并加监控给 Session 的本地回退明确关闭不允许无 Redis 就降级给 Spring Session 配置独立的redisNamespace避免 key 冲突。从此再没串过。方案四JWT 无状态令牌JWT 把用户信息 签名打包成一个 token服务端不存任何 Session靠签名校验真伪。特别适合前后端分离、跨域、移动端。// 用 jjwt 签发与校验注意别踩过期和刷新的坑 public String issueToken(LoginUser user) { return Jwts.builder() .setSubject(user.getUserId()) .claim(role, user.getRole()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() 1800_000)) // 30 分钟 .signWith(Keys.hmacShaKeyFor(SECRET.getBytes()), SignatureAlgorithm.HS256) .compact(); } public Claims parse(String token) { // 校验签名和过期失败直接抛异常不会解析出伪造的 payload return Jwts.parserBuilder() .setSigningKey(Keys.hmacShaKeyFor(SECRET.getBytes())) .build().parseClaimsJws(token).getBody(); }JWT 最大的争议是无法主动吊销token 发出去后在过期前都有效你没法像 Redis Session 那样del掉它。我们的做法是access token 短时效15 分钟 refresh token 长时效存 Redis要踢人就删 Redis 里的 refresh token。这样既享受无状态又能控制强制下线。我的取舍判断新项目、前后端分离、要跨域/移动端直接上 JWT 短 token 方案。Session 共享的复杂度可以省掉。老 Spring MVC 项目、不想改业务代码Spring Session Redis但连接池和命名空间这两件事必须当天配好否则迟早出串号或超时。Session 里别塞胖对象我们把整个Authentication对象含权限树塞进 Redis一个 key 20KB千万级 Session 直接把 Redis 内存打爆。改成只存 userId权限按需查体积降到 200 字节。Cookie 方案只适合极薄登录态别拿它当通用 Session 用。Session 这层看着简单真出事就是 P0 级的用户数据泄露。我不建议为了简单就上 Session 复制也不建议为了时髦就无脑 JWT 却不处理吊销。选型先问自己三个问题要不要主动踢人登录态有多胖要不要跨域答案清晰了方案自然就出来了。思考题如果你的 JWT 私钥泄露了你会怎么止血是立刻换 key 让所有老 token 失效误伤正常用户还是引入黑名单又回到了要存状态这两难你怎么解

相关新闻

小厂凭啥年入千万?医疗材料拉力机公司逆袭记!

小厂凭啥年入千万?医疗材料拉力机公司逆袭记!

在力学检测仪器这片看似由国际巨头主导的红海市场中,一家本土企业如何脱颖而出,实现年入千万级的增长?其背后的商业逻辑,远不止是“低价策略”,而是一场基于精准洞察、技术纵深与生态化服务的深度逆袭。特别是在对精度…

2026/10/14 1:36:09 阅读更多 →
RPA (Robotic Process Automation)

RPA (Robotic Process Automation)

RPA是如何提高人工情况下效率的,流程优化,流程重新组织组合,跨不同平台和系统流程组合,半自动化自动化。旨在极大提高工作效率。玩过游戏的应该都有用过【按键精灵】,RPA就是企业级应用的【按键精灵】,RPA不…

2026/10/14 0:15:02 阅读更多 →
AI做音效素材卖钱:7天实操手册——手把手教你用Stable Audio+商用授权避坑指南

AI做音效素材卖钱:7天实操手册——手把手教你用Stable Audio+商用授权避坑指南

更多请点击: https://kaifayun.com 第一章:AI做音效素材卖钱 AI音频生成技术正快速重塑音效创作与分发生态。过去依赖专业录音棚和版权采样库的音效生产模式,如今可通过文本提示(Prompt)驱动模型即时生成高质量、可商…

2026/10/13 10:34:34 阅读更多 →

最新新闻

YOLOv3电塔绝缘子检测权重:快速推理与微调实战

YOLOv3电塔绝缘子检测权重:快速推理与微调实战

简介:这是一份面向电力设施智能监测场景的YOLOv3电塔绝缘子检测训练成果包,适合目标检测初学者、电力巡检算法开发者及需要小目标检测参考方案的技术人员使用。资源包共990个文件,约520.07MB,包含json标注数据、png与jpg图像样本、…

2026/10/14 1:38:10 阅读更多 →
单链表头尾插法:带尾指针的工业级实现

单链表头尾插法:带尾指针的工业级实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 1:38:10 阅读更多 →
编译原理试卷A考点剖析:从词法分析到代码生成的完整复习链路

编译原理试卷A考点剖析:从词法分析到代码生成的完整复习链路

简介:常州工学院《编译原理》试卷A是一份面向计算机专业学生的期末试题,覆盖词法分析、语法分析、中间代码生成等编译流程核心知识点,既适合考前自测、查漏补缺,也可供教师布置作业或命题时参考。资源为单个doc文档,体…

2026/10/14 1:38:10 阅读更多 →
从JSON到Parquet:半结构化数据全链路处理与优化实战

从JSON到Parquet:半结构化数据全链路处理与优化实战

1. 半结构化数据到底是什么,为什么大数据绕不开它1.1 从数据形态演变看半结构化数据的定位做了这几年大数据的人应该都有同感:早期大家张口闭口都是“结构化数据”,建表、写SQL、跑报表,一切井然有序。可随着业务系统越接越多&…

2026/10/14 1:38:10 阅读更多 →
普通人抓住国产大模型红利:从提示词工程到工作流自动化

普通人抓住国产大模型红利:从提示词工程到工作流自动化

简介:清华大学新闻与传播学院新媒体研究中心发布的DeepSeek实用指南,面向希望借助AI提升工作、学习与生活效率的普通用户。文档系统梳理了DeepSeek-R1的模型定位与核心能力,涵盖智能对话、文本生成、语义理解、代码补全、联网搜索与深度思考等…

2026/10/14 1:38:10 阅读更多 →
Lua面试题深度拆解:从数据类型到协程的性能避坑指南

Lua面试题深度拆解:从数据类型到协程的性能避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 1:37:10 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →