一次redis悲观锁 实现 微信jssdk token缓存

(一)背景:

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,且每天有额度配额,最大调用次数限制

这一条决定:必须将access_token 缓存起来,否则每天都超标返回null


2 正常情况下access_token有效期为7200秒重复获取将导致上次获取的access_token失效

这一条决定:

(1)我们应将access_token 缓存7000秒,使用redis指定缓存时间是最好不过的

(2)先来看一下一般缓存代码:

        String token = (String)stringRedisTemplate.opsForValue().get(ACCESS);

        if(token == null) {
            token = WeXinCodeUtils.getAccessToken();
            stringRedisTemplate.opsForValue().set(ACCESS, token);
            System.out.println("request");
        } else {
            System.out.println("cache");
        }

先读后写,单线程下没有问题,输出:

request
cache

单在多线程下会有问题,而且会导致事故,比如:


B线程的请求token会导致A线程请求的token失效,A线程拿着失效的token,就失败了

对于这样的场景,我们都会想到两种方案:

1.悲观锁


这个方案可行,有点像单例模式,但是不应用于集群,同样会出事故:


synchronized不受多应用限制,导致应用A的token失效


故可以将synchronized替换为redis分布式锁


2.乐观锁


B线程请求token那会儿,A线程的token已经失效了,不管你乐观锁会报错,请求可不是数据库还给你token回滚,所以乐观锁在这个地方不适用,


故只能考虑分布式锁,有点像处理缓存击穿,这里是大并发场景,则是防大量请求同时爆到微信服务器,导致当日服务超次数限制。



(二)实现

1. 实现过程中,实践证明“正常情况下access_token有效期为7200秒重复获取将导致上次获取的access_token失效。“不准确,

重复获取不会导致上次获取的access_token失效,获取后7200秒自然失效

2. 本实例也不存在超高并发导致一秒内请求微信超限;


此2点决定:此次代码不考虑并发同步问题,一般代码处理即可,即:

一般缓存代码:

        String token = (String)stringRedisTemplate.opsForValue().get(ACCESS);

        if(token == null) {
            token = WeXinCodeUtils.getAccessToken();
            stringRedisTemplate.opsForValue().set(ACCESS, token);
            System.out.println("request");
        } else {
            System.out.println("cache");
        }



posted on 2018-03-03 19:45  silyvin  阅读(709)  评论(0编辑  收藏  举报