Service层:
直接查询MySQL返回数据
public UserQueryRespDTO queryUserByUserId(Long userId) {
LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
.eq(UserDO::getUserId, userId);
List<UserDO> userDOList = userMapper.selectList(queryWrapper);
UserDO userDO = CollUtil.isNotEmpty(userDOList) ? userDOList.get(0) : null;
UserQueryRespDTO userQueryRespDTO = new UserQueryRespDTO();
BeanUtil.convert(userDO, userQueryRespDTO);
return userQueryRespDTO;
}
流程图:
http 请求直接打到 MySQL 数据库,不宕机才怪嘞
Service层:
public UserQueryRespDTO queryUserByUserId(Long userId) {
UserDO userDO = distributedCache.safeGet(
USER_INFO_KEY + userId,
UserDO.class,
() -> {
LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
.eq(UserDO::getUserId, userId);
List<UserDO> userDOList = userMapper.selectList(queryWrapper);
return CollUtil.isNotEmpty(userDOList) ? userDOList.get(0) : null;
},
30,
TimeUnit.MINUTES,
null,
null,
key -> {
// 缓存空对象,解决缓存穿透。也可以使用布隆过滤器。
distributedCache.put(key, new UserDO(), 5, TimeUnit.MINUTES);
});
UserQueryRespDTO userQueryRespDTO = new UserQueryRespDTO();
BeanUtil.convert(userDO, userQueryRespDTO);
return userQueryRespDTO;
}
第二行distributedCache.safeGet方法
public <T> T safeGet(String key, Class<T> clazz, CacheLoader<T> cacheLoader, long timeout, TimeUnit timeUnit,
RBloomFilter<String> bloomFilter, CacheGetFilter<String> cacheGetFilter, CacheGetIfAbsent<String> cacheGetIfAbsent) {
T result = get(key, clazz);
// 缓存结果不等于空或空字符串直接返回;通过函数判断是否返回空,为了适配布隆过滤器无法删除的场景;两者都不成立,判断布隆过滤器是否存在,不存在返回空
if (!CacheUtil.isNullOrBlank(result)
|| Optional.ofNullable(cacheGetFilter).map(each -> each.filter(key)).orElse(false)
|| Optional.ofNullable(bloomFilter).map(each -> !each.contains(key)).orElse(false)) {
return result;
}
RLock lock = redissonClient.getLock(SAFE_GET_DISTRIBUTED_LOCK_KEY_PREFIX + key);
lock.lock();
try {
// 双重判定锁,减轻获得分布式锁后线程访问数据库压力
if (CacheUtil.isNullOrBlank(result = get(key, clazz))) {
// 如果访问 cacheLoader 加载数据为空,执行后置函数操作
if (CacheUtil.isNullOrBlank(result = loadAndSet(key, cacheLoader, timeout, timeUnit, true, bloomFilter))) {
Optional.ofNullable(cacheGetIfAbsent).ifPresent(each -> each.execute(key));
}
}
} finally {
lock.unlock();
}
return result;
}
流程图: