SpringBoot 项目 如何用Redis实现分布式Session?

本文详细解释了如何使用Redis在SpringBoot中实现分布式Session,涉及原理、区别、分布式Session问题及解决方法,包括配置步骤和Redis序列化问题的处理。
摘要由CSDN通过智能技术生成

目录

原理:如何用Redis实现分布式Session

1-1 什么是Session

1-2 Session和Cookie的区别

1-3 什么是分布式 Session

1-4 如何用 Redis 实现分布式 Session?

实践:SpringBoot 使用Redis实现分布式Session

步骤1:添加依赖

步骤2:配置Redis连接,配置Session

步骤3:添加注解(可省略)

Redis 存储 Session 值乱码解决


原理:如何用Redis实现分布式Session

1-1 什么是Session

Session是一种在 服务器 上存储用户数据以支持 Web应用会话管理的技术。当用户与Web应用交互时,服务器为每个用户创建一个独特的会话。这个会话允许服务器存储用户的状态信息,比如用户的身份认证信息、购物车内容、偏好设置等,即使用户在多个页面间导航,这些信息也会被保留。

1.用户登录(Login)

  • 用户首次登录Web应用时,会通过输入用户名和密码请求服务器验证身份。

2.创建Session和设置属性(Create session + setAttribute)

  • 一旦身份验证通过,服务器会为该用户创建一个Session。
  • 服务器为这个Session设置一个独特的标识符,通常称为Session ID。
  • 服务器还可以在Session中设置属性,这些属性是关于用户的特定信息,如用户ID、角色、权限等。

3.设置Cookie(set-cookie: JSESSIONID:888)

  • 服务器将创建的Session ID发送回客户端(用户的浏览器),通常是通过设置一个名为JSESSIONID的Cookie实现的。
  • 该Cookie会保存在用户的浏览器中,并且每次向服务器发送请求时都会自动包含这个Cookie。

4.后续请求(Request cookie:JSESSIONID:888)

  • 用户在后续的每一个请求中,浏览器都会携带这个Cookie,包含Session ID,发送给服务器。
  • 服务器通过Session ID识别出用户,并获取之前存储的Session信息。

5.资源访问(resource)

  • 服务器根据Session信息处理用户的请求,并返回相应的资源,例如用户请求的网页或数据。
  • 这样用户就能访问只有登录后才能看到的资源,如个人信息页面、购物车等。

通过以上步骤,Session允许用户在Web应用中进行无缝的、状态保持的交互,即使是在无状态的HTTP协议上。服务器通过Session机制识别用户并提供个性化服务,而用户无需在每个页面或请求中重复登录。


1-2 Session和Cookie的区别

Session:

  • Session是服务端用来维护用户状态的技术,常用于跟踪如购物车等用户特定操作。HTTP协议本身无法识别用户,但通过为每位用户创建独特的Session,服务器可以识别并追踪用户的行为。

Cookie

  • 与之相对的是Cookie,它存储在客户端浏览器中,用于存储用户信息。由于保存在客户端,Cookie的安全性相对较低,因此敏感信息不应直接存储在Cookie中,而应进行加密处理,只在服务器端解密使用。

总结来说,Cookie和Session都用于跟踪用户状态,但它们存储的位置不同:Cookie存储在客户端,易于访问但安全性较低;Session存储在服务器端,安全性较高。


1-3 什么是分布式 Session

分布式Session是一种在服务器集群中保持用户会话状态一致性的机制。在单体应用中,用户的Session信息通常由单个服务器管理。但在分布式系统或微服务架构中,应用可能被部署在多个服务器上,这些服务器共同对外提供服务。分布式Session的目的是确保用户的会话信息能在这个服务器集群中共享,无论用户的请求是被哪个服务器接收。

问题:

在集群环境下,如果不采用分布式Session,那么会有一些潜在的问题和后果,如图所示,有两个服务器(Server1和Server2)以及一个用户,这里是可能发生的情况:

  1.Session不一致:

  • 如果用户首次请求被Server1处理,并且在这里创建了Session,那么这个Session信息存储在Server1的内存中。
  • 当用户的下一个请求由于负载均衡的原因被路由到Server2时,Server2没有这个用户的Session信息,因为Server1和Server2不共享内存。
  • 结果是Server2不认识这个用户的Session,可能导致用户需要重新登录。

  2.用户体验不佳:

  • 用户可能在一个会话中多次被要求登录,每次他们的请求被路由到不同的服务器时,都需要重新验证身份。
  • 这不仅影响用户体验,也可能导致用户的操作无法持续进行,比如购物车中的物品可能在不同服务器间丢失。

  3.数据丢失:

  • 如果用户在Server1上执行了某些操作(比如添加商品到购物车),这些操作的结果存储在Server1的Session中。
  • 如果后续的请求转到了Server2,而Server2没有这些信息,那么这些操作就会丢失,因为Server2不知道用户之前在Server1上做了什么。

  4.安全隐患:

  • 由于Session数据分散在多个服务器上,这可能增加数据一致性和同步的复杂性,从而增加了出错和安全漏洞的风险。

解决方案:

  • 共享存储 ,而不是把数据放到单台服务器的内存中


1-4 如何用 Redis 实现分布式 Session?

在分布式系统中,通常会将 Session 存储在 Redis 中来实现 分布式 Session,这样就可以在多台服务器之间共享 Session 数据。实现分布式Session通常使用Redis的Hash结构:

  • 1. 在用户登录成功后,将 Session 数据存储在 Redis 中。
  • 2. 将 Redis 中的 Session 数据的 Key 设置为一个全局唯一的 ID,一般使用类似于“session:token”这样的格式,其中 token 是一个随机生成的字符串,用来标识这个 Session 数据。
  • 3. 在客户端返回响应的同时,将 Session ID(即 token)以 Cookie 的形式返回给客户端。客户端在后续的请求中都会携带这个 Cookie。
  • 4. 在后续的请求中,服务器会从客户端传递过来的 Cookie 中获取 Session ID,然后根据这个 ID 从 Redis 中获取对应的 Session 数据。如果 Redis 中没有找到对应的 Session 数据,那么就表示这个请求无法通过认证。
  • 5. 在用户退出登录或 Session 失效时,需要将 Redis 中的对应 Session 数据删除。

实践:SpringBoot 使用Redis实现分布式Session

步骤1:添加依赖

pom.xml 文件添加如下依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
  <version>2.6.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
  <version>2.6.3</version>
</dependency>

步骤2:配置Redis连接,配置Session

  • 配置 Redis
  • 从Spring Boot 2.0开始,如果你已经添加了spring-boot-starter-data-redis依赖,并且在配置文件中配置了Redis的信息,Spring Boot会自动配置Redis作为Session存储。
# application.yml
spring:
  redis:
    host: redis服务器地址
    port: 6379
    password: 你的Redis密码
    
  // session失效时间
  session:
    timeout: 86400
    store-type: redis

步骤3:添加注解(可省略)

  • @EnableRedisHttpSession 注解是 Spring Session 项目提供的,用于启用Spring Session支持和配置,它会创建一个名为 springSessionRepositoryFilter 的 Bean,这个 Bean 负责替换默认的 HTTP Session 实现。
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
    // 可以添加更多的配置信息
}

在Spring Boot中,如果你依赖于 spring-boot-starter-data-redis 并且已经配置了 application.yml 中的 spring.session.store-typeredis,Spring Boot 的自动配置机制可能会自动注册必要的 Spring Session 仓库和配置,因此你可能不需要显式地添加 @EnableRedisHttpSession 注解。Spring Boot的自动配置机制足够智能,能够根据你的依赖和配置属性来决定是否启用特定的配置。


Redis 存储 Session 值乱码解决

在 Spring Session 中,可以通过定义一个 RedisSerializer bean来覆盖默认的序列化器。这个bean的名字必须是 springSessionDefaultRedisSerializer。可以在现有的 Redis 配置类中添加该 bean

/**
 *
 *  自定义序列化
 *
 */
@Configuration
public class RedisTemplateConfig {

    // 添加的 Bean 解决 Session 值乱码
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        //创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
       //设置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置Key的序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());

        //创建Json序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置Value的序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);


        return redisTemplate;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值