缓存击穿
什么是缓存击穿呢?
在高并发的场景下,一个热点的缓存数据在redis中突然失效(过期或被删除时,所有的读请求都会直接落在数据库上,导致数据库瞬间压力剧增,严重时可能会造成数据库宕机。这种情况就是所谓的“缓存击穿”。(重点在于同一时间访问某一个热点的key数据库中有,redis中没有)
失效的可能原因
- 热点数据过期:如果缓存中的某些数据是访问非常频繁的热点数据,这些数据在缓存中过期后,如果有大量请求同时访问,这些请求都会穿透到数据库。
- 缓存数据被误删除:由于操作不当或系统bug等原因,缓存中的热点数据被误删除,也会导致缓存击穿。
解决方案
1.设置热点数据永不过期:对于一些访问非常频繁的热点数据,可以设置为永不过期,然后通过其他机制(如定时任务或后台线程)去更新这些数据。
2.设置缓存预热:在系统启动或者低峰期时,预先将一些热点数据加载到缓存中,这样在系统高峰期时,这些热点数据就已经存在于缓存中了,从而避免了缓存击穿的发生。
3.分布式锁:在分布式系统中,可以使用分布式锁来控制只有一个服务实例去数据库查询数据并更新缓存,其他服务实例则等待锁释放。这种方式需要引入分布式锁的实现(这个在我的另一篇博客有写到分布式锁 ——》http://t.csdnimg.cn/50hUT)
缓存雪崩
什么是缓存雪崩呢?
缓存雪崩指的是缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至宕机的现象。就是当缓存中的大量数据在同一时间失效,且这些数据的访问量又非常大时,所有的请求都会直接打到数据库上,导致数据库负载急剧增加,可能引发数据库崩溃,进而影响整个系统的正常运行。(重点在于同一时间访问大量的失效的key数据库中有,redis中没有)
失效的可能原因
- 缓存数据的过期策略:如果大量的缓存数据被设置为在同一时间点过期,那么在这个时间点,这些缓存数据将同时失效,导致大量的请求直接打到数据库上。
- 缓存服务器的故障:如果缓存服务器出现故障,所有原本应该由缓存处理的请求都会直接转发到数据库,给数据库带来巨大的压力。
解决方案
1.设置合理的过期时间:避免大量的缓存数据在同一时间点过期。可以通过随机设置过期时间或者为不同类型的缓存数据设置不同的过期策略来实现。
2.设置缓存预热:在系统启动或者低峰期时,提前将热点数据加载到缓存中,避免在高峰期时缓存数据失效导致大量请求直接打到数据库上。
缓存穿透
什么是缓存穿透呢?
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,而查询的结果在数据库中也不存在,因此不会写入缓存。这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。(重点在于访问某个的key数据库中没有,redis中没有,所以每次只能去数据库中查询)
发生的情况
- 当用户或系统查询一个在数据库中不存在的数据时,由于缓存中没有缓存该数据(因为数据本身不存在),每次查询都会失败并直接访问数据库。
- 如果攻击者利用这个漏洞进行大量伪造ID的请求,将极大地增加数据库的负担,甚至可能导致数据库崩溃。
解决方案
1.输入参数校验:在请求到达前,对请求参数进行合法性验证,如对请求的ID进行有效性检查,过滤掉无效或恶意的请求。
2.缓存空对象:对于查询为空的结果,也将其缓存起来(但设置较短的过期时间),这样下次查询相同的数据时可以直接从缓存中返回空对象,避免再次访问数据库。
3.使用布隆过滤器:使用布隆过滤器对请求进行预处理,过滤掉可能不存在的数据。布隆过滤器通过哈希函数将元素映射到位数组上,可以快速判断一个元素是否可能存在于集合中。如果请求被布隆过滤器拦截,则可以直接返回结果,而无需查询数据库。但是,布隆过滤器存在误判的情况,即可能将不存在的元素判断为存在。(布隆过滤器我的另一篇博客有详细介绍)