【Redis】Redis 实现分布式Session

Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。

在实际工作中我们建议使用外部的缓存设备来共享 Session,避免单个服务器节点挂掉而影响服务,共享数据都会放到外部缓存容器中。

Spring 官方针对 Session 管理这个问题,提供了专门的组件 Spring Session,使用 Spring Session 在项目中集成分布式 Session 非常方便。Spring 为 Spring Session 和 Redis 的集成提供了组件:spring-session-data-redis

使用 Redis 实现共享 Session 原理:

所有服务器的Session信息都存储到了同一个Redis集群中,即所有的服务都将 Session 的信息存储到 Redis 集群中,无论是对 Session 的注销、更新都会同步到集群中,达到了 Session 共享的目的。

1.导入依赖

XML 复制代码
<!-- Redis 依赖 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
</dependency>
<!-- Spring Session Redis 依赖-->
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
</dependency>

2.配置application.yml文件

XML 复制代码
server:
  port: 8080

spring:
  session:
    store-type: redis
  redis:
    host: 127.0.0.1
    port: 6379
    password:
    database: 0

3.配置Session

方法一:在启动类上加上 ***@EnableRedisHttpSession ***注解

java 复制代码
@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisSessionStudyApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisSessionStudyApplication.class, args);
    }

}

方法二:单独编写一个配置类并加上 @EnableRedisHttpSession 注解

java 复制代码
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

maxInactiveIntervalInSeconds: 设置 Session 失效时间

++使用 Redis Session 之后,原 Spring Boot 中的 server.session.timeout 属性不再生效。++

4.编写测试用户类

++一定要实现序列化接口,因为 Session 将数据存放到了 Redis 集群中,所以存入的数据也需要能够被序列化。++

java 复制代码
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Long id;
    private String username;
    private String password;

    public static final User defaultUser() {
        return builder().id(1L).username("MrVK").password("2333").build();
    }
}

5.编写控制器类

java 复制代码
    @RequestMapping("/index")
    public String index(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            return "index message";
        }
        return "please login first";
    }

    @RequestMapping("/login")
    public String login(HttpServletRequest request, String username, String password) {
        User userFromDB = defaultUser();
        if (username.equals(userFromDB.getUsername())) {
            if (password.equals(userFromDB.getPassword())) {
                request.getSession().setAttribute("user", userFromDB);
                return "login success";
            }
        }
        return "login failure";
    }

    @RequestMapping("/logout")
    public String login(HttpServletRequest request) {
        request.getSession().removeAttribute("user");
        return "has already logout";
    }

6.测试

8080端口的服务器与9090端口的服务器连接的是同一个Redis服务器,所以8080端口的服务器与9090端口的服务器共享的是同一个 Session,在8080端口服务器登录后,在9090端口服务器是可以访问受限制资源的。

同样,在9090端口上进行用户退出,然后再测试8080端口是否可以访问受限制资源,结果是用户退出后不可以访问受限制资源。

相关推荐
ProtonBase5 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
时时刻刻看着自己的心9 分钟前
clickhouse分布式表插入数据不用带ON CLUSTER
分布式·clickhouse
希忘auto1 小时前
详解Redis的常用命令
redis·1024程序员节
岁月变迁呀8 小时前
Redis梳理
数据库·redis·缓存
Data跳动9 小时前
Spark内存都消耗在哪里了?
大数据·分布式·spark
Code apprenticeship10 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站10 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle
装不满的克莱因瓶10 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
Java程序之猿10 小时前
微服务分布式(一、项目初始化)
分布式·微服务·架构
来一杯龙舌兰11 小时前
【RabbitMQ】RabbitMQ保证消息不丢失的N种策略的思想总结
分布式·rabbitmq·ruby·持久化·ack·消息确认