示例说明:获取第三方请求token,token的有效时长为24小时,且获取接口存在qps=3的限制
1、先查询缓存,在加锁请求第三方
java
private void getAccessToken(Config config){
String key = "redisKey";
Object redisValue = redisUtils.get(key);
if (ObjectUtils.isNotEmpty(redisValue)){
config.setAccessToken(redisValue.toString());
}
boolean locked = redisUtils.lockOn("redisLockOnKey", 3000, 3000, ()->{
String token = HttpClientUtil.doPostJson();
config.setAccessToken(token);
redisUtils.set(key, token, 23 * 3600);
});
if (!locked){
// 异常提示
}
}
2、先加锁在查询缓存,缓存不存在再去请求第三方
java
private void getAccessToken(Config config){
boolean locked = redisUtils.lockOn("redisLockOnKey", 3000, 3000, ()->{
String key = "redisKey";
Object redisValue = redisUtils.get(key);
if (ObjectUtils.isNotEmpty(redisValue)){
config.setAccessToken(redisValue.toString());
}else {
String token = HttpClientUtil.doPostJson();
config.setAccessToken(token);
redisUtils.set(key, token, 23 * 3600);
}
});
if (!locked){
// 异常提示
}
}
我的结论和想说明的问题
锁外查询缓存:当缓存不存在时会多请求进入锁等待,当请求进入时还是会存在多次请求的问题
锁内查询缓存:当缓存存在时直接返回,当缓存不存在时仅会请求一次,并将结果放入缓存,等待获取锁的线程便会从缓存中获取,避免多次请求。
AI提供的最优解流程:
java
查缓存
↓
命中,直接返回(无锁)
↓
未命中
↓
竞争分布式锁
↓
再次查缓存(Double Check)
↓
存在,直接返回
↓
不存在,请求第三方
↓
写入缓存
java
private void getAccessToken(Config config){
String key = "redisKey";
Object redisValue = redisUtils.get(key);
if (ObjectUtils.isNotEmpty(redisValue)){
config.setAccessToken(redisValue.toString());
}
boolean locked = redisUtils.lockOn("redisLockOnKey", 3000, 3000, ()->{
redisValue = redisUtils.get(key);
if (ObjectUtils.isNotEmpty(redisValue)){
config.setAccessToken(redisValue.toString());
}else {
String token = HttpClientUtil.doPostJson();
config.setAccessToken(token);
redisUtils.set(key, token, 23 * 3600);
}
});
if (!locked){
// 异常提示
}
}