缓存设计 - 并发更新的坑

本文探讨了并发更新缓存时可能出现的问题,如部分请求失败、一段时间内的所有请求失败及无限递归获取token等问题,分析了并发更新导致的数据更新异常,并提出了使用分布式锁和异步更新策略的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
在这里插入图片描述
(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. 同步并发更新 进化为 单线程异步更新
    在这里插入图片描述
    a. 线上s1和s2只从缓存读取token
    b. 更新token异步,asy-Master定期更新token,避免并发更新
    c. 使用shadow-master保证token更新高可用,asy-Master挂了,asy-Backup顶上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值