1.缓存击穿
缓存击穿是指热点key失效之后,所有请求都访问到数据库,对数据库造成较大压力。 解决方案: 1.加锁,获取到锁的线程去更新缓存;如果是集群部署,则需要使用分布式锁。问题:没获取到锁的其他线程走什么逻辑呢?如果是等待获取锁,那么同一时刻所有线程串行获取锁,后获取到锁的线程等待时间较长。如果直接返回获取不到,要根据具体情况考虑是否能够接受。
2.热点key缓存设置永不失效,更新采用异步更新的方式。具体实现可以是启动一个单独线程去定时判断缓存是否失效,失效时进行缓存更新。 存在更新不及时的情况,不能保证缓存和数据库的一致性。
2.缓存穿透
缓存穿透是指大量查询数据库中不存在的数据,这些数据不存在于数据库,也没有被缓存。所以每次请求都被打到数据上,造成数据库压力增大。 解决方案: 1.缓存空值,设置较短过期时间。 既然查询出来的是null,那么直接缓存好了。这样之后的查询就走缓存了。但是要注意一个问题是,后面对应的数据可能又被创建了,而数据创建时一般是不会直接写到缓存的(一般在数据第一次读取时写入缓存、数据被更新时删除缓存)。所以这里缓存的空值感知不到数据库变化,就会造成缓存和数据库不一致问题。为了减少这个问题,可以设置一个较短的过期时间。相当于定时去数据库里读取一次。
缺点:数据短时间不一致 优点:容易实现
2.布隆过滤器。 使用布隆过滤器存储所有合法的值。访问数据库前先过一遍布隆过滤器,存在的数据才去访问数据库。注:布隆过滤器特点是返回true说明key可能存在,返回false说明key一定不存在。这样就可以把一定不存在的key过滤掉了。 缺点:需要多一次布隆过滤器的访问,需要权衡访问量等 优点:避免了数据不一致
实际使用的一个case:记一次线上接口调用量过大报警问题处理
3.缓存雪崩
缓存雪崩是指大量key在同一时间过期,导致同时访问数据库,造成数据库压力过大,进而带来系统崩溃等风险。
解决方案: 1.给过期时间加减一个随机数,避免同一个时刻过期。
|