Sa-Token 微服务分布式 Session 四种方案怎么选?
2026/9/15 12:49:32 网站建设 项目流程

Sa-Token 微服务分布式 Session 四种方案怎么选?

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

把使用 Sa-Token 的服务从单机扩成多节点后,会遇到一个典型问题:用户在节点一登录成功,下一次请求落在节点二上时,节点二判断该用户仍未登录。原因是 Sa-Token 默认将会话数据保存在内存中(位于 core 核心包),这种模式读写最快、避免了序列化开销,但有两个硬伤:重启后数据丢失、无法在分布式环境中共享数据。

官方文档 微服务 - 分布式Session会话 归纳了四种主流方案,本文给出每种方案的取舍依据,以及其中两条可落地路径(Redis 会话中心、jwt 无状态令牌)的完整集成步骤与验证方式。

四种方案各自适合什么情况

方案做法文档给出的取舍
方案一:Session 同步一个节点的数据改变时,强制同步到其它所有节点性能消耗太大,不太考虑
方案二:Session 粘滞通过算法保证一个用户的所有请求稳定落在同一节点需要从网关处动手,与框架无关
方案三:建立会话中心Session 存储在专业缓存中间件上(如 Redis),每个节点变成无状态服务Sa-Token 整合 Redis 非常简单,官方更推荐
方案四:颁发无状态 token放弃 Session,把用户数据写入令牌本身(jwt)服务端不存储数据,对比较复杂的业务可能会功能受限

也就是说:方案一基本排除,方案二要改网关而不是改框架,真正在 Sa-Token 侧做决策的是方案三和方案四——默认走方案三(Redis),只有接受 jwt 的功能限制时才走方案四。

主路径:用 Redis 作为会话中心(方案三)

准备条件

  • 项目已引入 Sa-Token(如sa-token-spring-boot-starter),并准备一个可用的 Redis 服务。
  • Redis 版本要求 6.0+:自 v1.46.0 起,sa-token-redis-template/sa-token-redisson使用了 Redis 的SET KEEPTTL特性,低于 6.0 会报ERR syntax error
  • 版本对齐:Sa-Token-Redis 集成包的版本尽量与 Sa-Token-Starter 集成包的版本一致,否则可能出现兼容性问题(当前仓库根 pom.xml 的revision为 1.46.0,可参照对齐)。

引入依赖

Maven 方式:

<!-- Sa-Token 整合 RedisTemplate --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-redis-template</artifactId> <version>1.46.0</version> </dependency> <!-- 提供 Redis 连接池 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>

文档原始片段中的版本写作${sa.top.version},替换为你项目实际使用的 Sa-Token 版本号即可。Gradle 对应写法:

// Sa-Token 整合 RedisTemplate implementation 'cn.dev33:sa-token-redis-template:1.46.0' implementation 'org.apache.commons:commons-pool2'

引入的是 SpringBoot 官方推荐的 RedisTemplate 客户端,这是文档推荐给"省心省事"用户的默认方案。

配置 Redis 连接信息

只引依赖还不够:只有项目初始化了正确的 Redis 实例,Sa-Token 才能用 Redis 做数据持久化。在application.yml配置(文档示例值,host/port/password按你的实际环境替换):

spring: # redis配置 redis: # Redis数据库索引(默认为0) database: 1 # Redis服务器地址 host: 127.0.0.1 # Redis服务器连接端口 port: 6379 # Redis服务器连接密码(默认为空) # password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池最大连接数 max-active: 200 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # 连接池中的最大空闲连接 max-idle: 10 # 连接池中的最小空闲连接 min-idle: 0

注意一点:如果你使用的是SpringBoot 3.x,前缀spring.redis要改为spring.data.redis

使用与验证

集成 Redis 不需要改任何上层代码:框架自动保存数据,所有上层 API 保持不变,登录、会话读写照旧调用即可。

验证方式:登录一次后,到 Redis 中查看,能看到带satoken:前缀的键(前缀来自配置项sa-token.token-name,默认值satoken),默认以 json 格式存储。然后在多节点环境下重复文档描述的场景——在节点 A 登录后让请求落到节点 B,若节点 B 也能识别登录态,即达到"分布式环境下多节点的会话一致性"这一集成目标。

完整示例可参考仓库中的 sa-token-demo-springboot-redis。

可选分支一:项目已在用 Redisson

如果项目里用的是 Redisson 而不是 RedisTemplate,可以改用 集成 Redis 文档第 5 节 的方案。这是与 RedisTemplate并列的可选项,不要两套 Dao 同时引入。两种集成方式二选一:

方式一:通用插件sa-token-redisson(Spring Boot、Solon、JFinal 等均可用,要求项目里已有RedissonClient):

<!-- Sa-Token 整合 Redisson --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-redisson</artifactId> <version>1.46.0</version> </dependency>

然后自己注册 Dao(RedissonClient由你现有的 Redisson 配置提供):

@Configuration public class SaTokenDaoConfig { @Bean public SaTokenDao saTokenDao(RedissonClient redissonClient) { return new SaTokenDaoForRedisson(redissonClient); } }

方式二:sa-token-redisson-spring-boot-starter(Spring Boot 专用自动配置包,内部已含sa-token-redisson和官方redisson-spring-boot-starter,引入后自动注册SaTokenDao,不用手写 Java)。Redis 连接配置与官方 Redisson starter 相同,Spring Boot 3.x 同样要把spring.redis前缀改为spring.data.redis。示例见 sa-token-demo-springboot-redisson。

升级注意(从旧版本升级时必须看)SaTokenDaoForRedisson按 String 读写,新版默认StringCodec;而 v1.45.0 及更早版本下getBucket(key)跟随RedissonClient全局 codec(一般默认Kryo5Codec)。升级后旧缓存将无法反序列化、登录态失效,处理方式二选一:

  1. 清空 Redis 中 Sa-Token 相关的旧 key(默认前缀satoken:),让用户重新登录(文档推荐);
  2. 构造时显式传入升级前的 codec 保持兼容,例如未自定义过 Redisson codec 时传入new Kryo5Codec()
@Configuration public class SaTokenDaoConfig { @Bean @Primary public SaTokenDao saTokenDao(RedissonClient redissonClient) { return new SaTokenDaoForRedisson(redissonClient, new Kryo5Codec()); } }

若你曾在 Redisson 配置里指定过其它 codec(如JsonJacksonCodec),应传入当时使用的那个,而不是Kryo5Codec。若需要权限缓存与业务缓存分离,改用 Alone 独立 Redisson 插件。

可选分支二:颁发无状态 jwt 令牌(方案四)

如果业务允许完全不做服务端存储,可以走 jwt 路径。步骤见 和 jwt 集成:

  1. 在已引入 Sa-Token 的基础上添加依赖(${sa.top.version}替换为实际版本):
<!-- Sa-Token 整合 jwt --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-jwt</artifactId> <version>1.46.0</version> </dependency>

版本兼容性注意:sa-token-jwt显式依赖 hutool-jwt 5.7.14,项目中要么不引入 hutool,要么引入 >= 5.7.14 的版本;hutool 5.8.13 / 5.8.14 会出现类型转换问题。

  1. application.yml配置生成秘钥(文档示例的字符串仅演示格式,请按文档提示自行随机生成):
sa-token: # jwt秘钥 jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
  1. 三种模式选择其中一种注入:
@Configuration public class SaTokenConfigure { // Sa-Token 整合 jwt (Simple 简单模式 / Mixin 混入模式 / Stateless 无状态模式) @Bean public StpLogic getStpLogicJwt() { return new StpLogicJwtForSimple(); } }
  1. 之后照常使用 Sa-Token,访问登录接口即可观察生成的 Token 是否变成 jwt 风格。

三种模式的差异(文档以同时引入 jwt 与 Redis 为前提比较):

功能点Simple 简单模式Mixin 混入模式Stateless 无状态模式
Token 风格jwt 风格jwt 风格jwt 风格
登录数据存储Redis 中存储Token 中存储Token 中存储
Session 存储Redis 中存储Redis 中存储无 Session
踢人下线 / 顶人下线 API支持不支持不支持
active-timeout 有效期支持支持不支持
id 反查 Token / 账号封禁支持支持不支持
会话管理支持部分支持不支持
模式总结Token 风格替换jwt 与 Redis 逻辑混合完全舍弃 Redis,只用 jwt

使用 jwt 还有三个配置层注意点(来自 jwt 集成文档"注意点"一节):Simple 模式下is-share恒等于false;Mixin 模式下is-concurrent必须为truemax-try-times恒等于-1

集成 Redis 后容易踩的坑

  • Redis 低于 6.0 报ERR syntax error:这是SET KEEPTTL特性不被旧版 Redis 支持。文档给出的解决方式是:升级到 Redis 6.0+(推荐),或按 常见问题文档 中对应条目重写SaTokenDaoupdate方法恢复旧写法。
  • 自定义实体类反序列化报错:往 Session 存自定义实体类后,从 Redis 读回若报无法反序列化的类型:xxx,请先将其注册到 JSON 全局类型白名单,参考 JSON 序列化扩展 中的全局类型白名单机制。
  • 多个项目共用同一个 Redis 的键冲突:如无特殊需求建议不要共用;确实要共用时可用不同database索引、配置不同的sa-token.token-name(注意它同时是前端提交 Token 的参数名/Header 名)、使用 Alone 独立 Redis 插件(见 Alone 独立 Redis 插件),或重写wrapKey给所有键加项目前缀作为保底方案,详见 集成 Redis 文档第 4 节。
  • 序列化格式想改:默认序列化层是String 序列化->JSON 序列化(引入 spring-boot-starter 时自动用 Jackson),可换成 Fastjson/Fastjson2/Snack3,或改用 jdk 序列化(base64/16 进制/ISO-8859-1),扩展入口汇总在 缓存层扩展。

选型结论

  • 默认需求下走方案三:引入sa-token-redis-template+ Redis 连接配置,上层 API 零改动,这是文档明确推荐的路线;
  • 项目已有 Redisson 则走sa-token-redisson系列,注意旧缓存 codec 不兼容问题;
  • 业务确实简单、可接受 Stateless 模式下列出的功能限制(无 Session、无踢人/顶人下线等)时,才选 jwt 方案;官方文档也指出 jwt 模式因不在服务端存储数据,对较复杂业务可能功能受限,因此更推荐方案三。

jwt 与更多集成点的完整示例,可参考 集成示例大全下载说明。

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询