示例说明获取第三方请求tokentoken的有效时长为24小时且获取接口存在qps3的限制1、先查询缓存在加锁请求第三方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、先加锁在查询缓存缓存不存在再去请求第三方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提供的最优解流程查缓存 ↓ 命中直接返回无锁 ↓ 未命中 ↓ 竞争分布式锁 ↓ 再次查缓存Double Check ↓ 存在直接返回 ↓ 不存在请求第三方 ↓ 写入缓存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){ // 异常提示 } }
日常bug -- 锁内查询缓存还是锁外查询缓存
示例说明获取第三方请求tokentoken的有效时长为24小时且获取接口存在qps3的限制1、先查询缓存在加锁请求第三方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、先加锁在查询缓存缓存不存在再去请求第三方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提供的最优解流程查缓存 ↓ 命中直接返回无锁 ↓ 未命中 ↓ 竞争分布式锁 ↓ 再次查缓存Double Check ↓ 存在直接返回 ↓ 不存在请求第三方 ↓ 写入缓存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){ // 异常提示 } }