内容纲要
缓存
缓存的基本原理是将可能重复使用的数据放到内存中,一次生成,多次读取,避免每次去数据库读取。
为什么需要缓存
虽然我们通过各种手段来提高存储服务的性能,但是某些场景下,单纯依靠存储性能的提升是无法达成目标的,如:
- 需要复杂计算
- 读多写少
缓存带来的复杂度
缓存穿透
缓存穿透是指缓存没有发挥作用:业务系统虽然去缓存查询数据,但是在缓存中没有找到数据,然后又去了数据库查询。
缓存穿透发生的情况:
- 数据不存在:通常业务系统读取不存在的数据的可能性不大;如果出现异常读取不存在数据,会导致数据库访问量增大,最终可能拖垮数据库
- 解决办法:设置策略,在读取不到后通过返回默认值、设置读取次数上限等操作阻止异常访问不断的访问数据库
- 缓存数据生成耗费大量时间和资源:如大型数据存在缓存速度较慢、资源消耗巨大的问题,在设计缓存的时候,按照算法来生成缓存,但是在碰到异常访问(如爬虫)的时候,会导致建立大量缓存,消耗大量资源,以及在缓存未建立时,数据库被大量访问,最终导致数据库被拖垮
- 解决办法:没有特别有效的办法(爬虫);可以适当的限制爬虫行为
缓存雪崩
缓存雪崩是指当缓存失效(过期)后引起的系统性能急剧下降的情况(失效后重新建立缓存会消耗时间、资源;在高并发场景下,可能会瞬间让大量请求被转发到数据库,并进一步导致系统崩溃)。
解决办法:
- 更新锁
- 保证在更新的时候,只有一个线程能进行更新操作(分布式锁);其余线程要么等待,要么返回默认值
- 后台更新
- 缓存有效时间设置为永久,由后台线程(非业务线程)进行更新
- 问题:系统资源不足的情况下,部分缓存会被踢出缓存服务,由于后台线程是定时的,所以会导致一段时间内,被踢出的缓存不存在(表现为数据丢失)
- 解决办法(最直接有效的办法就是加服务器)
- 后台线程除了更新缓存,需要频繁读取缓存,如发现缓存被踢出,需要及时更新缓存
- 业务线程发现缓存失效,通知后台线程更新缓存(注意多个重复请求的处理)
- 缓存有效时间设置为永久,由后台线程(非业务线程)进行更新
缓存热点
当某份缓存的访问量特别大的时候,缓存所在的服务器也将面临性能问题。
解决办法就是:复制多分缓存副本,将请求分发到不同的服务器上来减轻单台服务器的压力。不同的副本不要设置同一过期时间,否则会出现雪崩效应,解决办法就是设置一个过期时间范围,不同的副本随机过期时间。