解决思路:
只需要加上过期时间随机值,能够保证上万条数据不同时过期,减少对数据库的压力,同一时刻缓存中还是有数据的
redisUtil.set(key, JSON.toJSONString(cookies), 24 * 60 * 60 , TimeUnit.SECONDS);
new Random().nextInt(30)60; 随机产生一个[0~3060)int类型的数值
redisUtil.set(key, JSON.toJSONString(cookies), 24 * 60 * 60 + new Random().nextInt(30)*60, TimeUnit.SECONDS);
上万条数据同时请求数据,缓存中没有数据,去数据库中数据库中也没有数据,穿透所有的持久层
解决思路:
为了防止缓存穿透,在第一条数据进行请求的时候发现缓存和数据库中都没有要求请的数据,就在缓存中放一个空串{},下次再次请求的时,读取到缓存中的值,判断值如果是空串则返回null ,否则返回对应的值。
上万条请求同时请求某一条数据
方法一:
添加同步锁机制synchronized,,,,
(双重检测锁)解决突发热点并发重建导致DB压力暴增
让第一个请求先查Redis缓存,若不存在查DB,查到写入Redis缓存
后续的请求再访问Redis时,直接取值
synchronized(this){
//Redis缓存中取数据,
//缓存中不存在该条数据,请求DB,存到Redis中
}
方法二:
使用Redis分布式锁

引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redissson</artifactId>
<version>3.6.5</version>
</dependency>
@Autowired
private Redisson redisson;
RLock hotCacheCreateLock = redisson.getLock(key);
hotCacheCreateLock.locak(); //相当于执行了setnx(k,v) // 加锁
try{
//Redis缓存中取数据,
//缓存中不存在该条数据,请求DB,存到Redis中
} finally {
hotCacheCreateLock.unlock(); //删除锁 del k 删除key
}

解决办法:Redis 分布式锁
@Autowired
private Redisson redisson;
RLock hotCacheCreateLock = redisson.getLock(key);
hotCacheCreateLock.locak(); //相当于执行了setnx(k,v) // 加锁
try{
//Redis缓存中取数据,
RLock updateCreateLock = redisson.getLock(key2);
updateCreateLock.locak(); //相当于执行了setnx(k,v) // 加锁
try{
//缓存中不存在该条数据,读取DB中数据,并存到Redis中
} finally {
updateCreateLock.unlock(); //删除锁 del k 删除key2
}
} finally {
hotCacheCreateLock.unlock(); //删除锁 del k 删除key
}
优化:可以用读写锁
对读多写少进行优化——所有的读操作并行执行,读和写互斥串行执行
读数据库中的数据
@Autowired
private Redisson redisson;
RLock hotCacheCreateLock = redisson.getLock(key);
hotCacheCreateLock.locak(); //相当于执行了setnx(k,v) // 加锁
try{
//Redis缓存中取数据,
//RLock updateCreateLock = redisson.getLock(key2);
RReadWriteLock readWriteLock = redisson.getReadWriteLock(ke2)
RLock rLock = readWriteLock.readLock();
rLock.locak(); // 加读锁 setnx(k,v)
try{
//缓存中不存在该条数据,读取DB中数据,并存到Redis中
} finally {
rLock.unlock(); //删除锁
}
} finally {
hotCacheCreateLock.unlock(); //删除锁 del k 删除key
}
更新数据库中数据
RReadWriteLock readWriteLock = redisson.getReadWriteLock(ke2)
RLock wLock = readWriteLock.writeLock();
wLock.locak(); // 加写锁 setnx(k,v)
try{
//修改数据库中的数据操作
} finally {
wLock.unlock();
}
读数据缓存锁优化
@Autowired
private Redisson redisson;
RLock hotCacheCreateLock = redisson.getLock(key);
//hotCacheCreateLock.locak(); //相当于执行了setnx(k,v) // 加锁
hotCacheCreateLock.tryLock(2,TimeUnit.SECONDS); //等待2秒后锁失效(设置合适的时间)
try{
//Redis缓存中取数据,
//RLock updateCreateLock = redisson.getLock(key2);
RReadWriteLock readWriteLock = redisson.getReadWriteLock(ke2)
RLock rLock = readWriteLock.readLock();
rLock.locak(); // 加读锁 setnx(k,v)
try{
//缓存中不存在该条数据,读取DB中数据,并存到Redis中
} finally {
rLock.unlock(); //删除锁
}
} finally {
hotCacheCreateLock.unlock(); //删除锁 del k 删除key
}
Redis单节点高并发最高10W+,,,瞬间来了几十W上百W的请求来查Redis中数据,Redis直接宕机了,,,缓存雪崩问题
web应用分流,,,
多级缓存——JVM进程级别缓存
JVM进程级别的缓存一般来说都是有容量上的限制