缓存击穿的定义
缓存击穿是一种现象,具体就是某一个数据过期时,恰好有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮。典型场景就是双十一等抢购活动中,首页广告页面的数据过期,此时刚好大量用户进行请求,那么数据库很容易抵挡不住,从而宕机。
解决方案之一:互斥锁(分布式锁)
当缓存失效时,先使用如 Redis 的 setnx 去设置一个互斥锁,当查询数据库重建缓存数据,成功返回并写入缓存时才释放锁,此时其他线程才能继续访问缓存。
优点、缺点、适用场景
优点:强一致性
缺点:性能较差,无法保障高可用性,可能产生死锁的问题。
适用场景:业务和钱等挂钩时,一般要保障强一致性,所以选择互斥锁。
解决方案之二:逻辑过期
逻辑过期就是除了业务逻辑真正需要的字段(如下图的id和title)之外,还额外设置一个字段用来判断缓存是否过期,一般为expire。而key本身是不设置过期时间的。
当查询数据时,首先会通过expire字段判断该数据是否过期,如果过期则获取互斥锁,并开启一个新线程。新线程进行查询db、重建缓存、写入缓存,重置逻辑过期时间等操作。**与此同时原线程直接返回过期了的数据。(不是等待新线程操作完成)**如果以上发现缓存过期的任意过程中,有其他线程想要查询该数据,也会首先通过expire字段来判断该数据是否过期,发现过期且此时新线程还未释放锁,就会因获取互斥锁失败而直接返回过期数据,如果已经释放了锁,那么就直接返回新数据。
优点、缺点、适用场景
优点:高可用、性能优
缺点:无法保障强一致性。
适用场景:除了和钱挂钩等业务场景,一般更看重用户体验,所以采用逻辑过期。
高可用的定义
高可用(Highavailability,缩写为HA),是指系统无中断地执行其功能的能力,代表系统的可用性程度。高可用的主要目的是为了保障“业务的连续性”,即在用户眼里,业务永远是正常对外提供服务的。
面试题回答模板
什么是缓存击穿 ? 怎么解决 ?
背熟以下回答,大概用时2分。
缓存击穿是一种现象,具体就是某一个数据过期时,恰好有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮。典型场景就是双十一等抢购活动中,首页广告页面的数据过期,此时刚好大量用户进行请求,那么数据库很容易抵挡不住,从而宕机。针对缓存击穿,我们一般有两种解决方案,分别是互斥锁和逻辑过期。
互斥锁就是当缓存失效时,先使用如 Redis 的 setnx 去设置一个互斥锁,当重建缓存成功时才释放锁,此时其他线程才能继续访问缓存。它的优点是保障了数据的强一致性,缺点是性能较差,无法保障高可用性,而且可能产生死锁的问题。当业务和钱等挂钩时,一般要保障强一致性,所以选择互斥锁。
逻辑过期就是除了业务逻辑真正需要的字段之外,还额外设置一个字段用来判断缓存是否过期,一般为expire。而key本身是不设置过期时间的。
当查询数据时,首先会通过expire字段判断该数据是否过期,如果过期则获取互斥锁,并开启一个新线程去重建缓存。与此同时原线程直接返回过期了的数据。如果以上过程中,有其他线程想要查询该数据,也会首先通过expire字段来判断该数据是否过期,发现过期且此时新线程还未释放锁,就会因获取互斥锁失败而直接返回过期数据,如果已经释放了锁,那么就直接返回新数据。采用逻辑过期的优点就是它有高可用性,性能较优。但与此同时,就无法保障数据的强一致性。
本文所有图片来自于黑马程序员。