支持分布式部署的主流方式 - Session 持久化到 Redis

1.为什么要将 Session 存储在 Redis 中

如果我们不将 Session 存储在 MySQL 或者 Redis 中, 那么做出来的项目就只能支持单机部署, 不支持分布式部署. 因为之前我们只是将 Session 存储在当前电脑的内存里面. 当张三去登录的时候, 将 Session 信息存储在 A 服务器, 这个时候负载均衡器将张三转到 B 服务器了, 而 B 服务器里面是没有张三的登录信息的, 那么这个时候, 张三又得登录一次, 这就不太合理了.

为了解决这个问题, 我们就需要将 Session 存储在 MySQL 或者 Redis 中, 而大部分的做法几乎都是将 Session 存储在 Redis 中.

画图理解 >>

  1. 单机部署

  1. 分布式部署

分布式部署相较于单机部署的区别 :

  1. 一台服务器升级为多台服务器

好处 : 1. 提升性能. 2. 当 A 服务器挂了, 还有 B 服务器, C 服务器顶着.

假设 1 台服务器每秒能够承载的并发数是 100 的话, 那么升级为 3 台服务器之后, 服务器能够承载的并发数的理论值就提升了 3 倍, 相当于性能提升了 3 倍. 但是它也带来了相应的问题 :
1. 最早只有一台服务器的时候, 张三的 Session 信息就存储在 A 服务器里, 如果不考虑服务器重启, Session 信息过期等情况, 那么服务器就会认为张三一直处于登录状态.
2. 而多台服务器中, 张三去访问程序的时候, 就不再是固定的去访问 A 服务器了, 第二次访问的时候, 张三的请求就被分配给了 B 服务器了, 这是完全可能的.如果不配置负载均衡规则的话, 默认是轮询的负载均衡策略, 也就是第一次请求分配了 A , 下一次就分配给了 B , 这样轮着分配. 如果 Session 存储在当前电脑的内存中, A 的第一次请求, 已经将 Session 信息存储在 A 服务器了, 那么下一次访问程序时, 如果请求被分配给了 B 服务器, 而 B 服务器并没有张三的登录信息, 那么就需要重新登录一次, 这就不合理了.
  1. 将 Session 持久化到数据库 - 支持分布式部署

对于上述问题, 将 Session 持久化到数据库中, 就解决了这个问题, 轮询的是程序, 而不是数据库, 所以无论请求被分配到哪个服务器, 都是可以获取到当前用户的登录信息的.

2. 如何将 Session 存储到 Redis

2.1 添加依赖

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.session</groupId>
 <artifactId>spring-session-data-redis</artifactId>
</dependency>

2.2 修改配置

application.properties

# 告诉 spring 将 session 存储在什么介质中
spring.session.store-type=redis
# session 的过期时间
server.servlet.session.timeout=1800
# session 的存储方式 - 磁盘存储
spring.session.redis.flush-mode=on_save
# 存储 session 的文件目录 (作用域)
spring.session.redis.namespace=spring:session
spring.data.redis.host=43.139.1.94
spring.data.redis.password=
spring.data.redis.port=6379
spring.data.redis.database=2

2.3 存储和读取 Session

创建 User 类 >>

@Data
public class User implements Serializable {
    private int id;
    private String username;
    private String password;
}

存储和读取 Session

@RestController
public class UserController {

    private final String user_session_key = "session_1";

    /**
     * 存储 Session
     * @param session
     * @return
     */
    @RequestMapping("/login")
    public boolean login(HttpSession session) {
        // .... 省去验证过程
        // 伪代码
        User user = new User();
        user.setId(1);
        user.setUsername("张三");
        user.setPassword("123");
        session.setAttribute(user_session_key, user);
        return true;
    }

    /**
     * 获取 Session
     * @param request
     * @return
     */
    @RequestMapping("/getsess")
    public User getSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if(session != null) {
            return (User) session.getAttribute(user_session_key);
        }
        return null;
    }
}

其实这个存储和读取 Session 的代码和以前的方式很像, 只不过将 Session 存储到 Redis 的事情都由框架帮我们做了, 我们只需要遵守约定即可.

验证程序 >> 127.0.0.1:8080/login

查看 Redis 客户端 >>

获取 Session >> 127.0.0.1:8080/getsess

此时就算我们重启服务器, 再去调用 getsess, 依然可以拿到张三的身份信息, 下来可以自己测试一下.

本篇博客就到这里了, 谢谢观看~

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
如果您在使用 Spring Session Redis 时遇到了配置序列化无效的问题,可能是因为 RedisTemplate 中使用的序列化器与 Spring Session Redis 中使用的不同。为了解决这个问题,您可以尝试以下步骤: 1. 确认 RedisTemplate 中使用的序列化器是否与 Spring Session Redis 中使用的一致。您可以在 RedisTemplate 中设置序列化器的方式如下: ```java RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); ``` 2. 如果 RedisTemplate 中使用的序列化器与 Spring Session Redis 中使用的不同,可以尝试在 Spring Session Redis 的配置中指定使用的序列化器: ```yaml spring: session: store-type: redis redis: namespace: myapp flush-mode: on_save cleanup-cron: '0 * * * * *' serializer: jackson ``` 3. 如果仍然无法解决问题,您可以尝试自定义 RedisTemplate,并将其注入到 Spring Session Redis 中: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, Object> redisTemplate) { return new RedisOperationsSessionRepository(redisTemplate); } } ``` 希望这些步骤可以帮助您解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Master_hl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值