1. 通用代码
java
public SysUser getCache(String sysUserId) {
String cacheKey = "litgery:warehouse:" + sysUserId;
// 尝试从缓存中获取数据
CacheData cacheData = redisUtils.get(cacheKey);
if (null != cacheData) {
if (Boolean.TRUE.equals(cacheData.getExist())) {
return cacheData.getSysUser();
} else {
return null;
}
}
// RedisLockClient 获取锁
RLock rLock = redisLockClient.getRLock("litgery:warehouse:lock");
try {
// 尝试获取锁,如果锁已被其他线程持有,则等待
rLock.lock();
// 再次检查数据是否存在,因为可能在等待锁的过程中,其他线程已经填充了数据
cacheData = redisUtils.get(cacheKey);
if (null != cacheData && Boolean.TRUE.equals(cacheData.getExist())) {
return cacheData.getSysUser();
}
//随机过期时间,随机生成0.5小时-1小时之内的时间(减少缓存同时失效的机会)
Long expireTime = CacheUtils.getRandomExpireTimeInOneOrTowDay();
SysUser sysUser = sysUserService.getById(sysUserId);
if (null == sysUser) {
// 如果数据仍然不存在,从数据库中获取数据并填充缓存,避免不存在的数据一直请求打到数据库
CacheData emptyCache = new CacheData();
emptyCache.setExist(Boolean.FALSE);
redisUtils.setEx(cacheKey, emptyCache, expireTime);
return null;
}
CacheData cache = new CacheData();
cache.setSysUser(sysUser);
cache.setExist(Boolean.TRUE);
redisUtils.setEx(cacheKey, cache, expireTime);
return sysUser;
} finally {
// 释放锁
rLock.unlock();
}
}
redisUtils 为redis工具类,例如:设置缓存获取缓存等等。
redisLockClient 为:RedisLockClient 的分布式锁
2.整体步骤
- 获取缓存,若有值直接返回
2.获取一个分布式锁。
加锁
再次检查数据是否存在,因为可能在等待锁的过程中,其他线程已经填充了数据
5.从数据库获取。若为空,设置一个空值到redis。若不为空,直接返回,最好设置随机过期时间
6.释放锁
可优化的点,可添加布隆过滤器