利用redis实现平滑的token刷新

我们通过伪代码来讲解整个设计思想,具体实现细节不再赘述。

设计思想:
双缓存机制:主token + 备用token,实现平滑过渡
Redis分布式锁:防止多个线程同时刷新token
预刷新策略:token有效期80%时就刷新,避免临期失效
容错机制:主token失效时可使用备用token继续服务

1、多个任务并行执行,调用mgr.run函数实现对资源的访问,访问时要求携带有效的token


List<MyJob> jobList = job.getJobList();
if (CollectionUtils.isEmpty(jobList)) { 
     return ;
}
jobList.parallelStream()
                .forEach(job -> {
                     mgr.run(job);
                    }
                });

2、mgr.run函数的伪代码如下

public void run(MyJob job) {  
        try {
            String token = getToken(jobFish.getId());
 
            // 拿着token请求资源获取结果
        } catch (Exception e) { 
            return;
        }
    }

3、getToken函数的伪代码如下

public String getToken(String id) { 

        // 从缓存中获取token
        Object token = redisTemplate.opsForValue().get(tokenKey);
        if (Objects.nonNull(token)) {
            return token.toString();
        }

        // 如果token为空,则刷新token(使用redis的nx锁实现仅允许一个线程去刷新token)
        boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockThreadKey, "lock", Duration.ofSeconds(30)));
        if(lock){
            // 锁定成功的线程去刷新token
            return getTokenByHttp(id,tokenKey,tokenKeyBack);
        }else{
            // 锁定失败的线程继续使用旧的token(旧的token有5分钟的缓冲时间)
            Object tokenBack = redisTemplate.opsForValue().get(tokenKeyBack);
            if (Objects.nonNull(tokenBack)) {
                return tokenBack.toString();
            }else{
                return "error";
            }
        }

    }

4、getTokenByHttp函数的伪代码如下

private String getTokenByHttp(String id,String tokenKey,String tokenKeyBack) {

         TokenResp tokenResp resp=null;//正式的从http请求中拿到token,这里以null代替

        // token默认有效期7200秒,这里设定redis缓存有效期为token的80%,提前24分钟让redis过期但token还有24分钟有效期,如此可以规避token临近过期时被拿去使用,http请求发过去时token已失效
        int expiresIn = (int) (tokenResp.getExpires_in() * 0.8);
        // 保存新的token到redis中,并设置有效期
        redisTemplate.opsForValue().set(tokenKey, tokenResp.getAccess_token(), expiresIn, TimeUnit.SECONDS);
        // 保存新的token到redis的备份key中,并设置有效期+300秒即5分钟(为什么+5分钟?token刷新会导致之前一次获取的token有效期缩短为 5 分钟,这5分钟内新旧token都可以使用,完成token的平滑过度)
        redisTemplate.opsForValue().set(tokenKeyBack, tokenResp.getAccess_token(), expiresIn+300, TimeUnit.SECONDS);

        return tokenResp.getAccess_token();

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Run Out Of Brain

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

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

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

打赏作者

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

抵扣说明:

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

余额充值