单点登录架构中,Redis 主要通过集中存储会话信息(Session)或令牌(Token)来实现。用户登录后,服务端生成唯一 Token 存入 Redis 并设置过期时间,客户端携带 Token 访问其他子系统,子系统通过 Redis 验证 Token 有效性。优化策略包括:缩短 Key/Value 长度以减少内存和网络开销;使用 Hash 结构存储用户信息;启用 Lazy Free 避免删除大键阻塞;使用 Pipeline 批量操作降低网络延迟;部署 Redis 集群防止单点故障;合理设置过期时间避免缓存穿透。
单点登录 redis 实现 单点登录 redis 解决方案
每个 web 应用都有自己的 session,那如何在分布式或者集群环境下统一 session,即如何实现单点登录,如下图 解决方案:把 session 数据存放在 redis,统一管理,向外提供服务接口,redis 可以设置过期时间,对应 session 的失效时间 优点:存取速度快,效率高;无单点故障,可以部署集群;自定义登录页面 (即每个应用都可以设计自己的登录页面) 缺点:必须部署 redis;所有程序自行开发,例如:登录、登出等。系统架构,只关注 Taotao-sso 和 redis 缓存即可,如下图:基于 redis 实现的单点登录这套方案比 SSO CAS 来说比较简单,容易上手,主要是依赖每个应用的拦截器和 redis 实现单点登录 SSO 需要提供的接口如下:登录,根据用户名和密码查询数据库,如存在则生成 token 保存在 redis,token 作为 key,用户信息作为 value,设置过期时间,然后把 token 保存到 cookie,固定 key,token 作为 value; 根据 token 查询用户信息,根据 token 作为 key 查询 redis 的值,如存在重新设置过期时间 (即已登录),不存在即未登录 登出,根据 token 作为 key 删除 redis 的值 拦截器流程图如下:拦截器代码如下:public class OrderInterceptor implements HandlerInterceptor { @Autowired private UserService userService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //取用户 token String token = CookieUtils.getCookieValue(request, "TT_TOKEN"); //判断是否为空 if (StringUtils.isBlank(token)) { //如果为空就是未登录状态 //跳转到登录页面 response.sendRedirect(userService.getLoginUrl() + "?redirect=" + getBaseURL(request)); return false; } else { //如果能取到 token 说明用户可能已经登录 //从 sso 中取用户信息,判断用户是否登录 TbUser user = userService.getUserByToken(token); //判断用户是否过期 if (user == null) { //跳转到登录页面 response.sendRedirect(userService.getLoginUrl() + "?redirect=" + getBaseURL(request)); return false; } else { //用户已经登录,把用户信息放到 request 中 request.setAttribute("user", user); } } //放行 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } @Override public void afterCompletion(HttpServlet(撰于 2023 年 7 月 28 日)
单点登录中 redis 作用 单点登录 redis 解决方案
三种常见方式:1.1 第一种:session 广播机制实现 (已淘汰) 概念:就是 session 复制,一个模块登录后,该模块 session 存放用户登录信息,再把该 session 复制到其它模块中,实现 session 广播,让所有的模块都能共享 session; 缺点:当模块很多时,session 需要需要复制多次,造成资源和内存的浪费 1.2 第二种:使用 cookie+redis 实现 概念:在项目中的任意一个模块进行登录,登录之后把数据放在 redis 和 cookie 中。1.2.1 redis+cookie 存放用户数据 第一步:redis key:唯一随机值 (ip、用户 id 等) value:存放用户登录数据 cookie 把 redis 里面的唯一 key 值放到 cookie 里面 第二步:访问项目中的其他模块时,发送请求携带 cookie 进行发送,服务器接收到请求,获取 cookie 值,从 cookie 中获取 redis 存放的主键,通过 redis key 去查询对应用户数据,如果结果不为空,那么说明就已经登录了。1.3 第三种:使用 token 实现 在项目某个模块进行登录,登录之后按照一定的规则生成字符串 (token 令牌 - 包含用户信息),再将这个字符串返回。返回方式可以通过 cookie 返回,也可以通过地址栏返回。再去访问项目其他模块,每次访问都携带 token 令牌 (地址栏里面带上 token 参数),服务器从地址栏中获取字符串 (token 令牌),根据 token 获取用户信息,如果结果不为空,那么就已经登录过了。2 JWT(Json Web Token) 传统的登录鉴权方式:2.1 session 认证 概念:因为 http 协议本身是无状态的协议,那就意味着当有用户向系统使用账号和密码进行用户认证之后,下一次登录请求还要再进行一次用户认证才行。因为我们不能通过 http 协议知道是哪个用户发出的请求,所以如果要知道是哪个用户发出的请求,那就需要在服务器保存一份用户信息 (保存至 session),然后在认证成功后返回 cookie 值传递给浏览器,那么用户在下一次请求时就可以带上 cookie 值,服务器就可以识别是哪个用户发送的请求,是否已认证,是否登录过期等等。缺点:因为 session 是保存在服务器里面的,所以对于分布式应用来说,由于 session 不共享,所以造成每一块微服务都需要进行用户认证… 2.2 token 认证 概念:这种方式跟 session 的方式流程差不多,不同的地方在于保存的是一个 token 值到 redis,token 一般是一串随机的字符 (比如 UUID),value 一般是用户 ID,并且设置一个过期时间。每次请求服务的时候带上 token 在请求头,后端接收到 token 则根据 token 查一下 redis 是否存在,如果存在则表示用户已认证,如果 token 不存在则跳到登录界面让用户重新登录,登录成功后返回一个 token 值给客户端。(2023 年 10 月 22 日)
Redis 实现安全可靠的单点登录 (redis 解决单点登录)
Redis 是一个开源的内存数据结构存储系统,具有高性能、稳定可靠等特点,非常适合用作单点登录系统的存储引擎。本文将介绍如何使用 Redis 实现一个安全可靠的单点登录系统。1.登录流程 单点登录系统的流程如下:1) 用户在客户端输入用户名和密码,提交给认证中心。2) 认证中心验证用户名和密码的合法性,如果验证通过,生成一个全局唯一的 token,并将 token 和用户的登录信息存储在 Redis 中。3) 认证中心把 token 返回给客户端,客户端将 token 存储在本地。4) 用户使用 token 来访问其他应用系统,其他应用系统需要向认证中心验证 token 的有效性,并获取用户的登录信息。2.实现细节 下面主要介绍单点登录系统的实现细节。1) 存储用户信息 在 Redis 中可以使用 Hash 类型存储用户信息。使用用户名作为 Key,用户信息作为 Value 存储在 Hash 中。示例代码如下:// 存储用户信息 redisClient.hset("user:username", "username", "password"); // 获取用户信息 redisClient.hget("user:username", "username"); 2) 生成 token 生成 token 可以通过 Redis 的自增功能来实现。使用一个全局计数器作为 Key,每次自增后作为 token 返回。示例代码如下:// 生成 token redisClient.incr("token:count"); long token = redisClient.get("token:count"); 3) 存储 token 存储 token 可以使用 Redis 的 String 类型。使用 token 作为 Key,存储用户信息的 Hash 作为 Value。并设置过期时间,保证 token 的安全性。示例代码如下:// 存储 token redisClient.setex(token, 3600, "user:username"); // 获取 token 对应的用户信息 redisClient.get(token); 4) 验证 token 验证 token 需要查询 Redis 中是否存在该 token,并获取用户信息进行验证。示例代码如下:// 验证 token String user_info = redisClient.get(token); if (user_info != null) { // 验证通过,返回用户信息 return user_info; } else { // 验证失败 return null; } 3.安全性考虑 单点登录系统需要保证数据的安全性。下面列举一些安全性考虑。1) 加密存储用户密码 用户密码需要进行加密存储,防止敏感数据泄露。可以使用加密算法如 SHA256 进行加密,存储加密后的 hash 值即可。示例代码如下:// 加密用户密码 String password = "123456"; MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); byte[] encodedhash = messageDigest.digest(password.getBytes(StandardCharsets.UTF_8));(发布时间是 2025 年 5 月 15 日)
《吐血整理》Redis 性能优化的 13 条军规!史上最全
Redis 是基于单线程模型实现的,也就是 Redis 是使用一个线程来处理所有的客户端请求的,尽管 Redis 使用了非阻塞式 IO,并且对各种命令都做了优化 (大部分命令操作时间复杂度都是 O(1)),但由于 Redis 是单线程执行的特点,因此它对性能的要求更加苛刻,本文我们将通过一些优化手段,让 Redis 更加高效的运行。本文我们将使用以下手段,来提升 Redis 的运行速度:缩短键值对的存储长度; 使用 lazy free(延迟删除) 特性; 设置键值的过期时间; 禁用长耗时的查询命令; 使用 slowlog 优化耗时命令; 使用 Pipeline 批量操作数据; 避免大量数据同时失效; 客户端使用优化; 使用物理机而非虚拟机安装 Redis 服务; 检查数据持久化策略; 禁用 THP 特性; 1.缩短键值对的存储长度 键值对的长度是和性能成反比的,比如我们来做一组写入数据的性能测试,执行结果如下:从以上数据可以看出,在 key 不变的情况下,value 值越大操作效率越慢,因为 Redis 对于同一种数据类型会使用不同的内部编码进行存储,比如字符串的内部编码就有三种:int(整数编码)、raw(优化内存分配的字符串编码)、embstr(动态字符串编码),这是因为 Redis 的作者是想通过不同编码实现效率和空间的平衡,然而数据量越大使用的内部编码就越复杂,而越是复杂的内部编码存储的性能就越低。这还只是写入时的速度,当键值对内容较大时,还会带来另外几个问题:内容越大需要的持久化时间就越长,需要挂起的时间越长,Redis 的性能就会越低; 内容越大在网络上传输的内容就越多,需要的时间就越长,整体的运行速度就越低; 内容越大占用的内存就越多,就会更频繁的触发内存淘汰机制,从而给 Redis 带来了更多的运行负担。因此在保证完整语义的同时,我们要尽量的缩短键值对的存储长度,必要时要对数据进行序列化和压缩再存储,以 Java 为例,序列化我们可以使用 protostuff 或 kryo,压缩我们可以使用 snappy。2.使用 lazy free 特性 lazy free 特性是 Redis 4.0 新增的一个非常使用的功能,它可以理解为惰性删除或延迟删除。意思是在删除的时候提供异步延时释放键值的功能,把键值释放操作放在 BIO(Background I/O) 单独的子线程处理中,以减少删除删除对 Redis 主线程的阻塞,可以有效地避免删除 big key 时带来的性能和可用性问题。(2020 年 3 月 28 日的资料)
Redis 性能优化 18 招
redis 性能优化的方法有哪些?如何提高 redis 的响应速度?redis 内存管理如何优化?前言 redis 作为一个高性能的键值存储系统,在现代应用中扮演着越来越重要的角色。无论是在 web 应用,移动应用,游戏还是 大数据分析 等领域,redis 都能提供快速的数据访问速度和优秀的性能。然而,随着数据量的不断增长,如何优化 redis 的性能成为了一个重要的课题。这篇文章将分享 redis 性能优化的 18 招,希望对你会有所帮助。选择合适的数据结构 redis 支持多种 数据结构,包括字符串,哈希,列表,集合,有序集合等。选择合适的数据结构可以提高性能和存储效率。例如,如果要存储用户信息,使用哈希结构而不是多个字符串可以更高效地存储和访问多个属性:代码语言:javascript ai 代码解释 jedis . hset ( "user:1001" , "name" , "alice" ) ; jedis . hset ( "user:1001" , "age" , "30" ) ; 这样可以减少内存的使用,并且提高数据操作的效率。避免使用过大的 key 和 value 过长的 key 和 value 会占用更多的内存空间,并且可能影响性能。保持 key 简短,并使用简洁的命名约定。例如,将"user:1001:profile"简化为"u:1001:p"。此外,还可以考虑对 value 进行压缩,以减少存储空间的占用。使用 redis pipeline 对多个命令的批量操作,使用 pipeline 可以显著降低 网络延迟,提升性能。pipeline 允许客户端一次发送多个命令,服务器 端集中处理后一次性返回结果,减少了网络往返次数。例如,批量设置 key 可以这样做:代码语言:javascript ai 代码解释 pipeline p = jedis . pipelined ( ) ; for ( int i = 0 ; i < 1000 ; i ++ ) redis 性能优化的 18 招(截至 2024 年 12 月 10 日)
FAQ
单点登录中 Redis 存储 Token 过期了怎么办?
Token 过期意味着用户会话失效,系统应拦截请求并重定向到登录页,用户重新认证后生成新 Token 存入 Redis。
Redis 集群如何保障 SSO 高可用?
通过 Redis Sentinel 哨兵模式或 Redis Cluster 集群模式,实现主从复制和自动故障转移,避免单点故障导致无法登录。
SSO 架构中 Redis key 设计有什么讲究?
Key 应简短且有意义,如"token:用户 ID",避免过长占用内存,同时设置合理的过期时间防止内存泄漏。