What

并发更新的坑指在并发更新缓存的时候,会出现并发更新的异常问题。导致与预期结果不一致,有的甚至会导致应用短时间不可用。

比如微信里面可以根据appId 和 appSecret来获取access-token,这个access-token是微信接口访问的凭证,有效期两个小时,一般会保存到缓存。

常见实现方式如下:(对应下面case1和case2)

  1. 获取access-token,如果存在则调用接口
  2. 如果不存在,则调用微信接口获取access-token,并缓存进redis,继续请求。

实现方式二:(对应下面case3)

  1. 获取access-token,如果存在则调用接口,如果调用失败则调用微信接口获取acceess-token直到access-token合法继续请求。
  2. 如果不存在,则调用微信接口获取access-token,并缓存进redis,继续请求,如果请求失败,继续调用微信接口获取access-token直到access-token合法继续请求。

Case 1:部分请求失败
如果A和B两个请求同时到达,都会得到缓存过期失效的结果,那么A和B会同时请求微信服务器获取新access-token2,如果A先返回,然后保存到缓存,继续请求,A请求成功并结束。此时请求C来了,并且获取到了A缓存的access-token2,同时请求B返回了新的access-token3,然后保存到缓存,继续请求,B请求成功。请求C因为access-token2陈旧导致请求失败。

Case2:一段时间的所有请求失败
在case1里面,如果微信服务器响应A比B早返回,但是B先存缓存,A后存缓存,那么缓存里面的access-token2就一直是旧的,后面一段时间(一般是2个小时)内所有的请求都会失败

Case3:无限递归获取token

axios token失效刷新token怎么重新请求_微信接口


(1)取旧token,访问接口,发现token过期;

(2)并发请求,取旧token,访问接口,也发现token过期;

(3)去申请新token1;

(3)并发申请新token2(此时token1会过期);

(4)把token1放入缓存,同时使用token1访问接口(此时token1已经过期),发现token1过期,可能会递归申请新token3(此时token2过期);

(5)把token2放入缓存,同时使用token2访问接口(此时token2已经过期),发现token2过期,可能会递归申请新token4(此时token3过期);

Why

并发更新导致了数据更新异常,顺序的代码逻辑被并发的更新打乱了。

How

  1. 分布式锁
    参考主流的分布式锁方案,比如redis分布式锁,或者zookeeper分布式锁,在更新前上锁,更新后释放锁。
  2. 同步并发更新 进化为 单线程异步更新
  3. axios token失效刷新token怎么重新请求_分布式锁_02

  4. a. 线上s1和s2只从缓存读取token
    b. 更新token异步,asy-Master定期更新token,避免并发更新
    c. 使用shadow-master保证token更新高可用,asy-Master挂了,asy-Backup顶上