1.Redis-缓存击穿
缓存击穿是指在高并发场景下,当一个缓存对象失效的瞬间,有大量的请求同时到达,这些请求发现缓存中没有该数据,就会去数据库查询,这可能会导致数据库在瞬间承受巨大的压力,甚至导致数据库宕机。
缓存击穿通常发生在对某个热点数据进行高频率访问时,这个数据的缓存在某一时刻过期,而此时如果有大量的请求到来,它们都会去查询数据库,因为缓存中没有这个数据。
这种情况在旁路缓存模式中容易触发,因为该模式更新数据时会删除缓存。特别是热点缓存数据一旦被删除,就需要考虑缓存被“击穿 ”的问题。
2.解决办法
2.1 互斥锁(Mutex Key):
在缓存失效时,先去获取一个互斥锁,只有获取到锁的请求才会去查询数据库并更新缓存,其他请求则等待或重试。这样可以保证在缓存失效时,只有一个请求去数据库查询数据并回写缓存。
public DataObject getData(Long id) {
// 从缓存读取数据
DataObject result = getDataFromCache(id);
if (result != null) {
return result;
}
// 缓存不存在,尝试获取互斥锁
RLock lock = redissonClient.getLock(DATA_LOCK_NAME + id);
lock.lock();
try {
// 双重检查,避免在等待锁的过程中,其他线程已经加载了数据
result = getDataFromCache(id);
if (result != null) {
return result;
}
// 从数据库查询数据
result = getDataFromDB(id);
// 将查询到的数据写入缓存
setDataToCache(id, result);
} finally {
lock.unlock();
}
return result;
}
2.2 逻辑过期:
在缓存数据时,同时存储数据的过期时间,当缓存数据被访问时,检查当前时间是否超过数据的逻辑过期时间,如果未过期,则直接返回数据;如果已过期,则从数据库加载新数据并更新缓存。
2.3 后台定时刷新:
通过后台任务定时刷新缓存数据,确保缓存数据不会同时过期,减少击穿的可能性。
2.4 热点数据不过期:
对于非常热点的数据,可以考虑设置为永不过期,或者过期时间非常长,由后台服务定期更新缓存数据。