• 【Redis】分布式Session


    一、问题引出

    1.1 Session的原理

    //默认创建一个session,默认值为true没有找到对应的session 自动创建session
    HttpSession session = request. getSession();
    session.setAttribute("user", nameValue);
    Object value = session.getAttribute("user");
    
    1. Session分为SessionIdSessionValue,Session本身是一个临时的,sessionid和token(令牌)非常相似保证临时且唯一;
    2. 请求和响应过程:服务器端接受到客户端请求,会创建一个Session,使用响应头返回SessionId给客户端。浏览器获取到SessionId后,保存在本地Cookie中;
    3. 下一次请求时:客户端读取到本地的SessionId,存放在请求头中,服务器端从请求头中获取到对应的Sessionid,使用SesisonId在本地Session内存中查询。

    1.2 问题概述

    1.分布式Session一致性(白话文服务器集群Session共享的问题)
    2.分析分布式Session一致性
    3.Session的作用?服务器(Tomcat) 与客户端(浏览器)保存整个通讯的会话基本信息。
    4.应用场景: javaee基础 登陆流程做法(账号密码登陆成功之后,获取到userid,存放在session,下次获取用户信息的之后,直接从session会话中获取。)防止表单重复提交。
    Session理解本地jvm缓存,sesison存放 服务器,返回sessionid给客户端。

    二、解决方案

    1. 使用nginx (反向代理) ip绑定 同一个ip 只能在指定的同一个机器访问(没有 负载均衡)
    2. 使用数据库效率不是很高
    3. tomcat内置支持对session同步( 不推荐),同步可能会产生延迟
    4. 使用SpringSession框架相当于把我们的Session值缓存到redis中。面试题:你们项目在发布的时候,Session如何控制不失效的? 使用缓存框架,缓存Session的值(一级和二级) Spring Session重写httpsession框架,将对应的值缓存到redis中有点类似与一级和二级缓存
    5. 以使用token替代Session功能, sessionid不同他的域名也不同,移动会话信息使用令牌方式替代Session,Token最终存放在redis中, redis支持分布式共享

    三、代码实现-使用Token代替Session

    Token存放在Redis中

    3.1 Service

    RedisService.java

    @Component
    public class RedisService {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        // public void set(String key, Object object, Long time) {
        // stringRedisTemplate.opsForValue();
        // // 存放String 类型
        // if (object instanceof String) {
        // setString(key, object);
        // }
        // // 存放 set类型
        // if (object instanceof Set) {
        // setSet(key, object);
        // }
        // // 设置有效期 以秒为单位
        // stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        // }
        //
        public void setString(String key, Object object) {
            // 开启事务权限
            // stringRedisTemplate.setEnableTransactionSupport(true);
            try {
                // 开启事务 begin
                // stringRedisTemplate.multi();
                String value = (String) object;
                stringRedisTemplate.opsForValue().set(key, value);
                System.out.println("存入完毕,马上开始提交redis事务");
                // 提交事务
                // stringRedisTemplate.exec();
            } catch (Exception e) {
                // 需要回滚事务
                // stringRedisTemplate.discard();
            }
        }
    
        public void setSet(String key, Object object) {
            Set<String> value = (Set<String>) object;
            for (String oj : value) {
                stringRedisTemplate.opsForSet().add(key, oj);
            }
        }
    
        public String getString(String key) {
            return stringRedisTemplate.opsForValue().get(key);
        }
    
    }
    

    TokenService.java

    
    @Service
    public class TokenService {
        @Autowired
        private RedisService redisService;
    
        // 新增 返回token
        public String put(String value) {
            //1.判断是否为空
            if(value == null) {
                return null;
            }
        
            //2. 获取对应的token(token实际等于key)
            String token = getToken();
            //3.存入redis中
            redisService.setString(token, value);
            //4.返回token
            return token;
        }
    
        // 获取信息
        public String get(String token) {
            String reuslt = redisService.getString(token);
            return reuslt;
        }
    
        public String getToken() {
            return UUID.randomUUID().toString();
        }
    
    }
    
    

    3.2 TokenController

    @RestController
    public class TokenController {
        @Autowired
        private TokenService tokenService;
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping("/put")
        public String put(String nameValue) {
            String token = tokenService.put(nameValue);
            return token + "-" + serverPort;
        }
    
        @RequestMapping("/get")
        public String get(String token) {
            String value = tokenService.get(token);
            return value + "-" + serverPort;
        }
    }
    
  • 相关阅读:
    拯救公主
    爱情之路
    无聊的会议
    对拍检验程序
    TCP三次握手
    OA系统走过的的坑之部门岗位管理
    蓝屏警告
    三级联动
    Ajax二级联动
    近期疑惑和总结
  • 原文地址:https://www.cnblogs.com/haoworld/p/redis-fen-bu-shisession.html
Copyright © 2020-2023  润新知